OLD | NEW |
| (Empty) |
1 // Copyright (c) 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. | |
4 | |
5 #include "chrome/common/extensions/csp_handler.h" | |
6 | |
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 "chrome/common/extensions/csp_validator.h" | |
12 #include "chrome/common/extensions/manifest_handlers/sandboxed_page_info.h" | |
13 #include "extensions/common/manifest_constants.h" | |
14 | |
15 namespace extensions { | |
16 | |
17 namespace keys = manifest_keys; | |
18 namespace errors = manifest_errors; | |
19 | |
20 using csp_validator::ContentSecurityPolicyIsLegal; | |
21 using csp_validator::ContentSecurityPolicyIsSecure; | |
22 | |
23 namespace { | |
24 | |
25 const char kDefaultContentSecurityPolicy[] = | |
26 "script-src 'self' chrome-extension-resource:; object-src 'self'"; | |
27 | |
28 #define PLATFORM_APP_LOCAL_CSP_SOURCES \ | |
29 "'self' data: chrome-extension-resource:" | |
30 const char kDefaultPlatformAppContentSecurityPolicy[] = | |
31 // Platform apps can only use local resources by default. | |
32 "default-src 'self' chrome-extension-resource:;" | |
33 // For remote resources, they can fetch them via XMLHttpRequest. | |
34 "connect-src *;" | |
35 // And serve them via data: or same-origin (blob:, filesystem:) URLs | |
36 "style-src " PLATFORM_APP_LOCAL_CSP_SOURCES " 'unsafe-inline';" | |
37 "img-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";" | |
38 "frame-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";" | |
39 "font-src " PLATFORM_APP_LOCAL_CSP_SOURCES ";" | |
40 // Media can be loaded from remote resources since: | |
41 // 1. <video> and <audio> have good fallback behavior when offline or under | |
42 // spotty connectivity. | |
43 // 2. Fetching via XHR and serving via blob: URLs currently does not allow | |
44 // streaming or partial buffering. | |
45 "media-src *;"; | |
46 | |
47 } // namespace | |
48 | |
49 CSPInfo::CSPInfo(const std::string& security_policy) | |
50 : content_security_policy(security_policy) { | |
51 } | |
52 | |
53 CSPInfo::~CSPInfo() { | |
54 } | |
55 | |
56 // static | |
57 const std::string& CSPInfo::GetContentSecurityPolicy( | |
58 const Extension* extension) { | |
59 CSPInfo* csp_info = static_cast<CSPInfo*>( | |
60 extension->GetManifestData(keys::kContentSecurityPolicy)); | |
61 return csp_info ? csp_info->content_security_policy : EmptyString(); | |
62 } | |
63 | |
64 // static | |
65 const std::string& CSPInfo::GetResourceContentSecurityPolicy( | |
66 const Extension* extension, | |
67 const std::string& relative_path) { | |
68 return SandboxedPageInfo::IsSandboxedPage(extension, relative_path) ? | |
69 SandboxedPageInfo::GetContentSecurityPolicy(extension) : | |
70 GetContentSecurityPolicy(extension); | |
71 } | |
72 | |
73 CSPHandler::CSPHandler(bool is_platform_app) | |
74 : is_platform_app_(is_platform_app) { | |
75 } | |
76 | |
77 CSPHandler::~CSPHandler() { | |
78 } | |
79 | |
80 bool CSPHandler::Parse(Extension* extension, string16* error) { | |
81 const std::string key = Keys()[0]; | |
82 if (!extension->manifest()->HasPath(key)) { | |
83 if (extension->manifest_version() >= 2) { | |
84 // TODO(abarth): Should we continue to let extensions override the | |
85 // default Content-Security-Policy? | |
86 std::string content_security_policy = is_platform_app_ ? | |
87 kDefaultPlatformAppContentSecurityPolicy : | |
88 kDefaultContentSecurityPolicy; | |
89 | |
90 CHECK(ContentSecurityPolicyIsSecure(content_security_policy, | |
91 extension->GetType())); | |
92 extension->SetManifestData(keys::kContentSecurityPolicy, | |
93 new CSPInfo(content_security_policy)); | |
94 } | |
95 return true; | |
96 } | |
97 | |
98 std::string content_security_policy; | |
99 if (!extension->manifest()->GetString(key, &content_security_policy)) { | |
100 *error = ASCIIToUTF16(errors::kInvalidContentSecurityPolicy); | |
101 return false; | |
102 } | |
103 if (!ContentSecurityPolicyIsLegal(content_security_policy)) { | |
104 *error = ASCIIToUTF16(errors::kInvalidContentSecurityPolicy); | |
105 return false; | |
106 } | |
107 if (extension->manifest_version() >= 2 && | |
108 !ContentSecurityPolicyIsSecure(content_security_policy, | |
109 extension->GetType())) { | |
110 *error = ASCIIToUTF16(errors::kInsecureContentSecurityPolicy); | |
111 return false; | |
112 } | |
113 | |
114 extension->SetManifestData(keys::kContentSecurityPolicy, | |
115 new CSPInfo(content_security_policy)); | |
116 return true; | |
117 } | |
118 | |
119 bool CSPHandler::AlwaysParseForType(Manifest::Type type) const { | |
120 if (is_platform_app_) | |
121 return type == Manifest::TYPE_PLATFORM_APP; | |
122 else | |
123 return type == Manifest::TYPE_EXTENSION || | |
124 type == Manifest::TYPE_LEGACY_PACKAGED_APP; | |
125 } | |
126 | |
127 const std::vector<std::string> CSPHandler::Keys() const { | |
128 const std::string& key = is_platform_app_ ? | |
129 keys::kPlatformAppContentSecurityPolicy : keys::kContentSecurityPolicy; | |
130 return SingleKey(key); | |
131 } | |
132 | |
133 } // namespace extensions | |
OLD | NEW |