Adding Peter Thatcher to the owners file.
[chromium-blink-merge.git] / extensions / common / manifest_handlers / csp_info.cc
blobe75699525515fceeb88bf7a81e719c1468e96345
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' chrome-extension-resource:; object-src 'self';";
29 #define PLATFORM_APP_LOCAL_CSP_SOURCES \
30 "'self' data: chrome-extension-resource:"
31 const char kDefaultPlatformAppContentSecurityPolicy[] =
32 // Platform apps can only use local resources by default.
33 "default-src 'self' chrome-extension-resource:;"
34 // For remote resources, they can fetch them via XMLHttpRequest.
35 " connect-src *;"
36 // And serve them via data: or same-origin (blob:, filesystem:) URLs
37 " style-src " PLATFORM_APP_LOCAL_CSP_SOURCES " 'unsafe-inline';"
38 " img-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
39 " frame-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
40 " font-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";"
41 // Media can be loaded from remote resources since:
42 // 1. <video> and <audio> have good fallback behavior when offline or under
43 // spotty connectivity.
44 // 2. Fetching via XHR and serving via blob: URLs currently does not allow
45 // streaming or partial buffering.
46 " media-src *;";
48 int GetValidatorOptions(Extension* extension) {
49 int options = csp_validator::OPTIONS_NONE;
51 // crbug.com/146487
52 if (extension->GetType() == Manifest::TYPE_EXTENSION ||
53 extension->GetType() == Manifest::TYPE_LEGACY_PACKAGED_APP) {
54 options |= csp_validator::OPTIONS_ALLOW_UNSAFE_EVAL;
57 // Component extensions can specify an insecure object-src directive. This
58 // should be safe because non-NPAPI plugins should load in a sandboxed process
59 // and only allow communication via postMessage. Flash is an exception since
60 // it allows scripting into the embedder page, but even then it should
61 // disallow cross-origin scripting. At some point we may want to consider
62 // allowing this publicly.
63 if (extensions::Manifest::IsComponentLocation(extension->location()))
64 options |= csp_validator::OPTIONS_ALLOW_INSECURE_OBJECT_SRC;
66 return options;
69 } // namespace
71 CSPInfo::CSPInfo(const std::string& security_policy)
72 : content_security_policy(security_policy) {
75 CSPInfo::~CSPInfo() {
78 // static
79 const std::string& CSPInfo::GetContentSecurityPolicy(
80 const Extension* extension) {
81 CSPInfo* csp_info = static_cast<CSPInfo*>(
82 extension->GetManifestData(keys::kContentSecurityPolicy));
83 return csp_info ? csp_info->content_security_policy : base::EmptyString();
86 // static
87 const std::string& CSPInfo::GetResourceContentSecurityPolicy(
88 const Extension* extension,
89 const std::string& relative_path) {
90 return SandboxedPageInfo::IsSandboxedPage(extension, relative_path) ?
91 SandboxedPageInfo::GetContentSecurityPolicy(extension) :
92 GetContentSecurityPolicy(extension);
95 CSPHandler::CSPHandler(bool is_platform_app)
96 : is_platform_app_(is_platform_app) {
99 CSPHandler::~CSPHandler() {
102 bool CSPHandler::Parse(Extension* extension, base::string16* error) {
103 const std::string key = Keys()[0];
104 if (!extension->manifest()->HasPath(key)) {
105 if (extension->manifest_version() >= 2) {
106 // TODO(abarth): Should we continue to let extensions override the
107 // default Content-Security-Policy?
108 std::string content_security_policy = is_platform_app_ ?
109 kDefaultPlatformAppContentSecurityPolicy :
110 kDefaultContentSecurityPolicy;
112 CHECK_EQ(content_security_policy,
113 SanitizeContentSecurityPolicy(content_security_policy,
114 GetValidatorOptions(extension),
115 NULL));
116 extension->SetManifestData(keys::kContentSecurityPolicy,
117 new CSPInfo(content_security_policy));
119 return true;
122 std::string content_security_policy;
123 if (!extension->manifest()->GetString(key, &content_security_policy)) {
124 *error = base::ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
125 return false;
127 if (!ContentSecurityPolicyIsLegal(content_security_policy)) {
128 *error = base::ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
129 return false;
131 std::string sanitized_csp;
132 if (extension->manifest_version() >= 2) {
133 std::vector<InstallWarning> warnings;
134 content_security_policy =
135 SanitizeContentSecurityPolicy(content_security_policy,
136 GetValidatorOptions(extension),
137 &warnings);
138 extension->AddInstallWarnings(warnings);
141 extension->SetManifestData(keys::kContentSecurityPolicy,
142 new CSPInfo(content_security_policy));
143 return true;
146 bool CSPHandler::AlwaysParseForType(Manifest::Type type) const {
147 if (is_platform_app_)
148 return type == Manifest::TYPE_PLATFORM_APP;
149 else
150 return type == Manifest::TYPE_EXTENSION ||
151 type == Manifest::TYPE_LEGACY_PACKAGED_APP;
154 const std::vector<std::string> CSPHandler::Keys() const {
155 const std::string& key = is_platform_app_ ?
156 keys::kPlatformAppContentSecurityPolicy : keys::kContentSecurityPolicy;
157 return SingleKey(key);
160 } // namespace extensions