Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / extensions / common / manifest_handlers / csp_info.cc
blob5581d510ac4defccdf635729d57b43141d024ac4
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "extensions/common/manifest_handlers/csp_info.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "extensions/common/csp_validator.h"
12 #include "extensions/common/install_warning.h"
13 #include "extensions/common/manifest_constants.h"
14 #include "extensions/common/manifest_handlers/sandboxed_page_info.h"
16 namespace extensions {
18 namespace keys = manifest_keys;
19 namespace errors = manifest_errors;
21 using csp_validator::ContentSecurityPolicyIsLegal;
22 using csp_validator::SanitizeContentSecurityPolicy;
24 namespace {
26 const char kDefaultContentSecurityPolicy[] =
27 "script-src 'self' blob: filesystem: chrome-extension-resource:; "
28 "object-src 'self' blob: filesystem:;";
30 #define PLATFORM_APP_LOCAL_CSP_SOURCES \
31 "'self' blob: filesystem: data: chrome-extension-resource:"
33 const char kDefaultPlatformAppContentSecurityPolicy[] =
34 // Platform apps can only use local resources by default.
35 "default-src 'self' blob: filesystem: chrome-extension-resource:;"
36 // For remote resources, they can fetch them via XMLHttpRequest.
37 " connect-src *;"
38 // And serve them via data: or same-origin (blob:, filesystem:) URLs
39 " style-src " PLATFORM_APP_LOCAL_CSP_SOURCES " 'unsafe-inline';"
40 " img-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
41 " frame-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
42 " font-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
43 // Media can be loaded from remote resources since:
44 // 1. <video> and <audio> have good fallback behavior when offline or under
45 // spotty connectivity.
46 // 2. Fetching via XHR and serving via blob: URLs currently does not allow
47 // streaming or partial buffering.
48 " media-src *;";
50 int GetValidatorOptions(Extension* extension) {
51 int options = csp_validator::OPTIONS_NONE;
53 // crbug.com/146487
54 if (extension->GetType() == Manifest::TYPE_EXTENSION ||
55 extension->GetType() == Manifest::TYPE_LEGACY_PACKAGED_APP) {
56 options |= csp_validator::OPTIONS_ALLOW_UNSAFE_EVAL;
59 // Component extensions can specify an insecure object-src directive. This
60 // should be safe because non-NPAPI plugins should load in a sandboxed process
61 // and only allow communication via postMessage. Flash is an exception since
62 // it allows scripting into the embedder page, but even then it should
63 // disallow cross-origin scripting. At some point we may want to consider
64 // allowing this publicly.
65 if (extensions::Manifest::IsComponentLocation(extension->location()))
66 options |= csp_validator::OPTIONS_ALLOW_INSECURE_OBJECT_SRC;
68 return options;
71 } // namespace
73 CSPInfo::CSPInfo(const std::string& security_policy)
74 : content_security_policy(security_policy) {
77 CSPInfo::~CSPInfo() {
80 // static
81 const std::string& CSPInfo::GetContentSecurityPolicy(
82 const Extension* extension) {
83 CSPInfo* csp_info = static_cast<CSPInfo*>(
84 extension->GetManifestData(keys::kContentSecurityPolicy));
85 return csp_info ? csp_info->content_security_policy : base::EmptyString();
88 // static
89 const std::string& CSPInfo::GetResourceContentSecurityPolicy(
90 const Extension* extension,
91 const std::string& relative_path) {
92 return SandboxedPageInfo::IsSandboxedPage(extension, relative_path) ?
93 SandboxedPageInfo::GetContentSecurityPolicy(extension) :
94 GetContentSecurityPolicy(extension);
97 CSPHandler::CSPHandler(bool is_platform_app)
98 : is_platform_app_(is_platform_app) {
101 CSPHandler::~CSPHandler() {
104 bool CSPHandler::Parse(Extension* extension, base::string16* error) {
105 const std::string key = Keys()[0];
106 if (!extension->manifest()->HasPath(key)) {
107 if (extension->manifest_version() >= 2) {
108 // TODO(abarth): Should we continue to let extensions override the
109 // default Content-Security-Policy?
110 std::string content_security_policy = is_platform_app_ ?
111 kDefaultPlatformAppContentSecurityPolicy :
112 kDefaultContentSecurityPolicy;
114 CHECK_EQ(content_security_policy,
115 SanitizeContentSecurityPolicy(content_security_policy,
116 GetValidatorOptions(extension),
117 NULL));
118 extension->SetManifestData(keys::kContentSecurityPolicy,
119 new CSPInfo(content_security_policy));
121 return true;
124 std::string content_security_policy;
125 if (!extension->manifest()->GetString(key, &content_security_policy)) {
126 *error = base::ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
127 return false;
129 if (!ContentSecurityPolicyIsLegal(content_security_policy)) {
130 *error = base::ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
131 return false;
133 std::string sanitized_csp;
134 if (extension->manifest_version() >= 2) {
135 std::vector<InstallWarning> warnings;
136 content_security_policy =
137 SanitizeContentSecurityPolicy(content_security_policy,
138 GetValidatorOptions(extension),
139 &warnings);
140 extension->AddInstallWarnings(warnings);
143 extension->SetManifestData(keys::kContentSecurityPolicy,
144 new CSPInfo(content_security_policy));
145 return true;
148 bool CSPHandler::AlwaysParseForType(Manifest::Type type) const {
149 if (is_platform_app_)
150 return type == Manifest::TYPE_PLATFORM_APP;
151 else
152 return type == Manifest::TYPE_EXTENSION ||
153 type == Manifest::TYPE_LEGACY_PACKAGED_APP;
156 const std::vector<std::string> CSPHandler::Keys() const {
157 const std::string& key = is_platform_app_ ?
158 keys::kPlatformAppContentSecurityPolicy : keys::kContentSecurityPolicy;
159 return SingleKey(key);
162 } // namespace extensions