OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "platform/feature_policy/FeaturePolicy.h" | 5 #include "platform/feature_policy/FeaturePolicy.h" |
6 | 6 |
7 #include "platform/json/JSONValues.h" | 7 #include "platform/json/JSONValues.h" |
8 #include "platform/network/HTTPParsers.h" | 8 #include "platform/network/HTTPParsers.h" |
9 #include "platform/weborigin/KURL.h" | 9 #include "platform/weborigin/KURL.h" |
raymes
2017/02/13 02:42:37
nit: can we remove this?
| |
10 #include "platform/weborigin/SecurityOrigin.h" | 10 #include "platform/weborigin/SecurityOrigin.h" |
11 #include "wtf/PtrUtil.h" | 11 #include "wtf/PtrUtil.h" |
12 #include "wtf/text/StringBuilder.h" | 12 #include "wtf/text/StringBuilder.h" |
raymes
2017/02/13 02:42:37
nit: can we remove this?
| |
13 | 13 |
14 namespace blink { | 14 namespace blink { |
15 | 15 |
16 namespace { | |
17 | |
18 // Given a string name, return the matching feature struct, or nullptr if it is | |
19 // not the name of a policy-controlled feature. | |
20 const FeaturePolicy::Feature* featureForName( | |
21 const String& featureName, | |
22 FeaturePolicy::FeatureList& features) { | |
23 for (const FeaturePolicy::Feature* feature : features) { | |
24 if (featureName == feature->featureName) | |
25 return feature; | |
26 } | |
27 return nullptr; | |
28 } | |
29 | |
30 } // namespace | |
31 | |
32 // Definitions of all features controlled by Feature Policy should appear here. | |
33 const FeaturePolicy::Feature kDocumentCookie{ | |
34 "cookie", FeaturePolicy::FeatureDefault::EnableForAll}; | |
35 const FeaturePolicy::Feature kDocumentDomain{ | |
36 "domain", FeaturePolicy::FeatureDefault::EnableForAll}; | |
37 const FeaturePolicy::Feature kDocumentWrite{ | |
38 "docwrite", FeaturePolicy::FeatureDefault::EnableForAll}; | |
39 const FeaturePolicy::Feature kFullscreenFeature{ | |
40 "fullscreen", FeaturePolicy::FeatureDefault::EnableForSelf}; | |
41 const FeaturePolicy::Feature kGeolocationFeature{ | |
42 "geolocation", FeaturePolicy::FeatureDefault::EnableForSelf}; | |
43 const FeaturePolicy::Feature kMidiFeature{ | |
44 "midi", FeaturePolicy::FeatureDefault::EnableForAll}; | |
45 const FeaturePolicy::Feature kNotificationsFeature{ | |
46 "notifications", FeaturePolicy::FeatureDefault::EnableForAll}; | |
47 const FeaturePolicy::Feature kPaymentFeature{ | |
48 "payment", FeaturePolicy::FeatureDefault::EnableForSelf}; | |
49 const FeaturePolicy::Feature kPushFeature{ | |
50 "push", FeaturePolicy::FeatureDefault::EnableForAll}; | |
51 const FeaturePolicy::Feature kSyncScript{ | |
52 "sync-script", FeaturePolicy::FeatureDefault::EnableForAll}; | |
53 const FeaturePolicy::Feature kSyncXHR{ | |
54 "sync-xhr", FeaturePolicy::FeatureDefault::EnableForAll}; | |
55 const FeaturePolicy::Feature kUsermedia{ | |
56 "usermedia", FeaturePolicy::FeatureDefault::EnableForAll}; | |
57 const FeaturePolicy::Feature kVibrateFeature{ | |
58 "vibrate", FeaturePolicy::FeatureDefault::EnableForSelf}; | |
59 const FeaturePolicy::Feature kWebRTC{ | |
60 "webrtc", FeaturePolicy::FeatureDefault::EnableForAll}; | |
61 | |
62 // static | 16 // static |
63 std::unique_ptr<FeaturePolicy::Whitelist> FeaturePolicy::Whitelist::from( | 17 WebParsedFeaturePolicyHeader parseFeaturePolicy(const String& policy, |
64 const WebParsedFeaturePolicyDeclaration& parsedDeclaration) { | 18 RefPtr<SecurityOrigin> origin, |
65 std::unique_ptr<Whitelist> whitelist(new FeaturePolicy::Whitelist); | 19 Vector<String>* messages) { |
66 if (parsedDeclaration.matchesAllOrigins) { | |
67 whitelist->addAll(); | |
68 } else { | |
69 for (const WebSecurityOrigin& origin : parsedDeclaration.origins) | |
70 whitelist->add(static_cast<WTF::PassRefPtr<SecurityOrigin>>(origin)); | |
71 } | |
72 return whitelist; | |
73 } | |
74 | |
75 FeaturePolicy::Whitelist::Whitelist() : m_matchesAllOrigins(false) {} | |
76 | |
77 void FeaturePolicy::Whitelist::addAll() { | |
78 m_matchesAllOrigins = true; | |
79 } | |
80 | |
81 void FeaturePolicy::Whitelist::add(RefPtr<SecurityOrigin> origin) { | |
82 m_origins.push_back(std::move(origin)); | |
83 } | |
84 | |
85 bool FeaturePolicy::Whitelist::contains(const SecurityOrigin& origin) const { | |
86 if (m_matchesAllOrigins) | |
87 return true; | |
88 for (const auto& targetOrigin : m_origins) { | |
89 if (targetOrigin->isSameSchemeHostPortAndSuborigin(&origin)) | |
90 return true; | |
91 } | |
92 return false; | |
93 } | |
94 | |
95 String FeaturePolicy::Whitelist::toString() { | |
96 StringBuilder sb; | |
97 sb.append("["); | |
98 if (m_matchesAllOrigins) { | |
99 sb.append("*"); | |
100 } else { | |
101 for (size_t i = 0; i < m_origins.size(); ++i) { | |
102 if (i > 0) { | |
103 sb.append(", "); | |
104 } | |
105 sb.append(m_origins[i]->toString()); | |
106 } | |
107 } | |
108 sb.append("]"); | |
109 return sb.toString(); | |
110 } | |
111 | |
112 // static | |
113 const FeaturePolicy::FeatureList& FeaturePolicy::getDefaultFeatureList() { | |
114 DEFINE_STATIC_LOCAL( | |
115 Vector<const FeaturePolicy::Feature*>, defaultFeatureList, | |
116 ({&kDocumentCookie, &kDocumentDomain, &kDocumentWrite, | |
117 &kGeolocationFeature, &kFullscreenFeature, &kMidiFeature, | |
118 &kNotificationsFeature, &kPaymentFeature, &kPushFeature, &kSyncScript, | |
119 &kSyncXHR, &kUsermedia, &kVibrateFeature, &kWebRTC})); | |
120 return defaultFeatureList; | |
121 } | |
122 | |
123 // static | |
124 std::unique_ptr<FeaturePolicy> FeaturePolicy::createFromParentPolicy( | |
125 const FeaturePolicy* parent, | |
126 RefPtr<SecurityOrigin> currentOrigin, | |
127 FeaturePolicy::FeatureList& features) { | |
128 DCHECK(currentOrigin); | |
129 std::unique_ptr<FeaturePolicy> newPolicy = | |
130 WTF::wrapUnique(new FeaturePolicy(currentOrigin, features)); | |
131 for (const FeaturePolicy::Feature* feature : features) { | |
132 if (!parent || | |
133 parent->isFeatureEnabledForOrigin(*feature, *currentOrigin)) { | |
134 newPolicy->m_inheritedFeatures.set(feature, true); | |
135 } else { | |
136 newPolicy->m_inheritedFeatures.set(feature, false); | |
137 } | |
138 } | |
139 return newPolicy; | |
140 } | |
141 | |
142 // static | |
143 std::unique_ptr<FeaturePolicy> FeaturePolicy::createFromParentPolicy( | |
144 const FeaturePolicy* parent, | |
145 RefPtr<SecurityOrigin> currentOrigin) { | |
146 return createFromParentPolicy(parent, std::move(currentOrigin), | |
147 getDefaultFeatureList()); | |
148 } | |
149 | |
150 // static | |
151 WebParsedFeaturePolicyHeader FeaturePolicy::parseFeaturePolicy( | |
152 const String& policy, | |
153 RefPtr<SecurityOrigin> origin, | |
154 Vector<String>* messages) { | |
155 Vector<WebParsedFeaturePolicyDeclaration> whitelists; | 20 Vector<WebParsedFeaturePolicyDeclaration> whitelists; |
156 | 21 |
157 // Use a reasonable parse depth limit; the actual maximum depth is only going | 22 // Use a reasonable parse depth limit; the actual maximum depth is only going |
158 // to be 4 for a valid policy, but we'll give the featurePolicyParser a chance | 23 // to be 4 for a valid policy, but we'll give the featurePolicyParser a chance |
159 // to report more specific errors, unless the string is really invalid. | 24 // to report more specific errors, unless the string is really invalid. |
160 std::unique_ptr<JSONArray> policyItems = parseJSONHeader(policy, 50); | 25 std::unique_ptr<JSONArray> policyItems = parseJSONHeader(policy, 50); |
161 if (!policyItems) { | 26 if (!policyItems) { |
162 if (messages) | 27 if (messages) |
163 messages->push_back("Unable to parse header"); | 28 messages->push_back("Unable to parse header"); |
164 return whitelists; | 29 return whitelists; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
204 messages->push_back("Whitelist is not an array of strings."); | 69 messages->push_back("Whitelist is not an array of strings."); |
205 } | 70 } |
206 } | 71 } |
207 whitelist.origins = origins; | 72 whitelist.origins = origins; |
208 whitelists.push_back(whitelist); | 73 whitelists.push_back(whitelist); |
209 } | 74 } |
210 } | 75 } |
211 return whitelists; | 76 return whitelists; |
212 } | 77 } |
213 | 78 |
214 void FeaturePolicy::setHeaderPolicy( | |
215 const WebParsedFeaturePolicyHeader& policy) { | |
216 DCHECK(m_headerWhitelists.isEmpty()); | |
217 for (const WebParsedFeaturePolicyDeclaration& parsedDeclaration : policy) { | |
218 const FeaturePolicy::Feature* feature = | |
219 featureForName(parsedDeclaration.featureName, m_features); | |
220 if (!feature) | |
221 continue; | |
222 m_headerWhitelists.set(feature, Whitelist::from(parsedDeclaration)); | |
223 } | |
224 } | |
225 | |
226 bool FeaturePolicy::isFeatureEnabledForOrigin( | |
227 const FeaturePolicy::Feature& feature, | |
228 const SecurityOrigin& origin) const { | |
229 DCHECK(m_inheritedFeatures.contains(&feature)); | |
230 if (!m_inheritedFeatures.get(&feature)) { | |
231 return false; | |
232 } | |
233 if (m_headerWhitelists.contains(&feature)) { | |
234 return m_headerWhitelists.get(&feature)->contains(origin); | |
235 } | |
236 if (feature.defaultPolicy == FeaturePolicy::FeatureDefault::EnableForAll) { | |
237 return true; | |
238 } | |
239 if (feature.defaultPolicy == FeaturePolicy::FeatureDefault::EnableForSelf) { | |
240 return m_origin->isSameSchemeHostPortAndSuborigin(&origin); | |
241 } | |
242 return false; | |
243 } | |
244 | |
245 bool FeaturePolicy::isFeatureEnabled( | |
246 const FeaturePolicy::Feature& feature) const { | |
247 DCHECK(m_origin); | |
248 return isFeatureEnabledForOrigin(feature, *m_origin); | |
249 } | |
250 | |
251 FeaturePolicy::FeaturePolicy(RefPtr<SecurityOrigin> currentOrigin, | |
252 FeaturePolicy::FeatureList& features) | |
253 : m_origin(std::move(currentOrigin)), m_features(features) {} | |
254 | |
255 String FeaturePolicy::toString() { | |
256 StringBuilder sb; | |
257 sb.append("Feature Policy for frame in origin: "); | |
258 sb.append(m_origin->toString()); | |
259 sb.append("\n"); | |
260 sb.append("Inherited features:\n"); | |
261 for (const auto& inheritedFeature : m_inheritedFeatures) { | |
262 sb.append(" "); | |
263 sb.append(inheritedFeature.key->featureName); | |
264 sb.append(": "); | |
265 sb.append(inheritedFeature.value ? "true" : "false"); | |
266 sb.append("\n"); | |
267 } | |
268 sb.append("Header whitelists:\n"); | |
269 for (const auto& whitelist : m_headerWhitelists) { | |
270 sb.append(" "); | |
271 sb.append(whitelist.key->featureName); | |
272 sb.append(": "); | |
273 sb.append(whitelist.value->toString()); | |
274 sb.append("\n"); | |
275 } | |
276 return sb.toString(); | |
277 } | |
278 | 79 |
279 } // namespace blink | 80 } // namespace blink |
OLD | NEW |