Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp

Issue 2520223002: Replicate a parsed feature policy representation so it doesn't need to be parsed in the browser pro… (Closed)
Patch Set: Fp2 Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
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"
13 13
14 namespace blink { 14 namespace blink {
15 15
16 namespace { 16 namespace {
17 17
18 // Given a string name, return the matching feature struct, or nullptr if it is 18 // Given a string name, return the matching feature struct, or nullptr if it is
19 // not the name of a policy-controlled feature. 19 // not the name of a policy-controlled feature.
20 const FeaturePolicy::Feature* featureForName( 20 const FeaturePolicy::Feature* featureForName(
21 const String& featureName, 21 const String& featureName,
22 FeaturePolicy::FeatureList& features) { 22 FeaturePolicy::FeatureList& features) {
23 for (const FeaturePolicy::Feature* feature : features) { 23 for (const FeaturePolicy::Feature* feature : features) {
24 if (featureName == feature->featureName) 24 if (featureName == feature->featureName)
25 return feature; 25 return feature;
26 } 26 }
27 return nullptr; 27 return nullptr;
28 } 28 }
29 29
30 // Converts a list of JSON feature policy items into a mapping of features to
31 // whitelists. For future compatibility, unrecognized features are simply
32 // ignored, as are unparseable origins. If |messages| is not null, then any
33 // errors in the input will cause an error message to be appended to it.
34 HashMap<const FeaturePolicy::Feature*,
35 std::unique_ptr<FeaturePolicy::Whitelist>>
36 parseFeaturePolicyFromJson(std::unique_ptr<JSONArray> policyItems,
37 RefPtr<SecurityOrigin> origin,
38 FeaturePolicy::FeatureList& features,
39 Vector<String>* messages) {
40 HashMap<const FeaturePolicy::Feature*,
41 std::unique_ptr<FeaturePolicy::Whitelist>>
42 whitelists;
43
44 for (size_t i = 0; i < policyItems->size(); ++i) {
45 JSONObject* item = JSONObject::cast(policyItems->at(i));
46 if (!item) {
47 if (messages)
48 messages->append("Policy is not an object");
49 continue; // Array element is not an object; skip
50 }
51
52 for (size_t j = 0; j < item->size(); ++j) {
53 JSONObject::Entry entry = item->at(j);
54 String featureName = entry.first;
55 JSONArray* targets = JSONArray::cast(entry.second);
56 if (!targets) {
57 if (messages)
58 messages->append("Whitelist is not an array of strings.");
59 continue;
60 }
61
62 const FeaturePolicy::Feature* feature =
63 featureForName(featureName, features);
64 if (!feature)
65 continue; // Feature is not recognized; skip
66
67 std::unique_ptr<FeaturePolicy::Whitelist> whitelist(
68 new FeaturePolicy::Whitelist);
69 String targetString;
70 for (size_t j = 0; j < targets->size(); ++j) {
71 if (targets->at(j)->asString(&targetString)) {
72 if (equalIgnoringCase(targetString, "self")) {
73 whitelist->add(origin);
74 } else if (targetString == "*") {
75 whitelist->addAll();
76 } else {
77 KURL originUrl = KURL(KURL(), targetString);
78 if (originUrl.isValid()) {
79 whitelist->add(SecurityOrigin::create(originUrl));
80 }
81 }
82 } else {
83 if (messages)
84 messages->append("Whitelist is not an array of strings.");
85 }
86 }
87 whitelists.set(feature, std::move(whitelist));
88 }
89 }
90 return whitelists;
91 }
92
93 } // namespace 30 } // namespace
94 31
95 // Definitions of all features controlled by Feature Policy should appear here. 32 // Definitions of all features controlled by Feature Policy should appear here.
96 const FeaturePolicy::Feature kDocumentCookie{ 33 const FeaturePolicy::Feature kDocumentCookie{
97 "cookie", FeaturePolicy::FeatureDefault::EnableForAll}; 34 "cookie", FeaturePolicy::FeatureDefault::EnableForAll};
98 const FeaturePolicy::Feature kDocumentDomain{ 35 const FeaturePolicy::Feature kDocumentDomain{
99 "domain", FeaturePolicy::FeatureDefault::EnableForAll}; 36 "domain", FeaturePolicy::FeatureDefault::EnableForAll};
100 const FeaturePolicy::Feature kDocumentWrite{ 37 const FeaturePolicy::Feature kDocumentWrite{
101 "docwrite", FeaturePolicy::FeatureDefault::EnableForAll}; 38 "docwrite", FeaturePolicy::FeatureDefault::EnableForAll};
102 const FeaturePolicy::Feature kGeolocationFeature{ 39 const FeaturePolicy::Feature kGeolocationFeature{
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 } 125 }
189 126
190 // static 127 // static
191 std::unique_ptr<FeaturePolicy> FeaturePolicy::createFromParentPolicy( 128 std::unique_ptr<FeaturePolicy> FeaturePolicy::createFromParentPolicy(
192 const FeaturePolicy* parent, 129 const FeaturePolicy* parent,
193 RefPtr<SecurityOrigin> currentOrigin) { 130 RefPtr<SecurityOrigin> currentOrigin) {
194 return createFromParentPolicy(parent, std::move(currentOrigin), 131 return createFromParentPolicy(parent, std::move(currentOrigin),
195 getDefaultFeatureList()); 132 getDefaultFeatureList());
196 } 133 }
197 134
198 void FeaturePolicy::setHeaderPolicy(const String& policy, 135 // static
199 Vector<String>* messages) { 136 WebVector<WebFeaturePolicy::ParsedWhitelist> FeaturePolicy::parseFeaturePolicy(
iclelland 2016/11/23 20:20:28 As a new public interface, it would be good to hav
raymes 2016/11/30 06:25:17 Done - I added a test.
200 DCHECK(m_headerWhitelists.isEmpty()); 137 const String& policy,
138 const SecurityOrigin* origin,
139 Vector<String>* messages) {
140 Vector<WebFeaturePolicy::ParsedWhitelist> whitelists;
141
142 if (origin->isUnique())
iclelland 2016/11/23 20:20:28 This is a new check -- as far as I can tell, a uni
raymes 2016/11/30 06:25:17 Yeah it is a new check. You're right - let me remo
143 return whitelists;
144
201 // Use a reasonable parse depth limit; the actual maximum depth is only going 145 // Use a reasonable parse depth limit; the actual maximum depth is only going
202 // to be 4 for a valid policy, but we'll give the featurePolicyParser a chance 146 // to be 4 for a valid policy, but we'll give the featurePolicyParser a chance
203 // to report more specific errors, unless the string is really invalid. 147 // to report more specific errors, unless the string is really invalid.
204 std::unique_ptr<JSONArray> policyJSON = parseJSONHeader(policy, 50); 148 std::unique_ptr<JSONArray> policyItems = parseJSONHeader(policy, 50);
205 if (!policyJSON) { 149 if (!policyItems) {
206 if (messages) 150 if (messages)
207 messages->append("Unable to parse header"); 151 messages->append("Unable to parse header");
208 return; 152 return whitelists;
209 } 153 }
210 m_headerWhitelists = parseFeaturePolicyFromJson( 154
211 std::move(policyJSON), m_origin, m_features, messages); 155 for (size_t i = 0; i < policyItems->size(); ++i) {
156 JSONObject* item = JSONObject::cast(policyItems->at(i));
157 if (!item) {
158 if (messages)
159 messages->append("Policy is not an object");
160 continue; // Array element is not an object; skip
161 }
162
163 for (size_t j = 0; j < item->size(); ++j) {
164 JSONObject::Entry entry = item->at(j);
165 String featureName = entry.first;
166 JSONArray* targets = JSONArray::cast(entry.second);
167 if (!targets) {
168 if (messages)
169 messages->append("Whitelist is not an array of strings.");
170 continue;
171 }
172
173 WebFeaturePolicy::ParsedWhitelist whitelist;
174 whitelist.featureName = featureName;
175 Vector<WebString> origins;
176 String targetString;
177 for (size_t j = 0; j < targets->size(); ++j) {
178 if (targets->at(j)->asString(&targetString)) {
179 if (equalIgnoringCase(targetString, "self")) {
180 origins.append(origin->toString());
181 } else if (targetString == "*") {
182 whitelist.matchesAllOrigins = true;
183 } else {
184 KURL originUrl = KURL(KURL(), targetString);
185 if (originUrl.isValid())
iclelland 2016/11/23 20:20:28 This might as well be if (KURL(KURL(), targetStrin
raymes 2016/11/29 08:20:34 Good point - we can probably use a WebSecurityOrig
186 origins.append(targetString);
187 }
188 } else {
189 if (messages)
190 messages->append("Whitelist is not an array of strings.");
191 }
192 }
193 whitelist.origins = origins;
194 whitelists.append(whitelist);
195 }
196 }
197 return whitelists;
198 }
199
200 void FeaturePolicy::setHeaderPolicy(
201 const WebVector<WebFeaturePolicy::ParsedWhitelist>& policy) {
202 DCHECK(m_headerWhitelists.isEmpty());
203 for (const WebFeaturePolicy::ParsedWhitelist& parsedWhitelist : policy) {
iclelland 2016/11/23 20:20:28 This method seems like it's mostly a conversion fu
raymes 2016/11/29 08:20:34 I haven't made this change yet (and my connection
raymes 2016/11/30 06:25:17 Done now.
204 const FeaturePolicy::Feature* feature =
205 featureForName(parsedWhitelist.featureName, m_features);
206 if (!feature)
207 continue;
208 std::unique_ptr<Whitelist> whitelist(new FeaturePolicy::Whitelist);
209 if (parsedWhitelist.matchesAllOrigins) {
210 whitelist->addAll();
211 } else {
212 for (const WebString& origin : parsedWhitelist.origins) {
213 KURL originUrl = KURL(KURL(), origin);
214 if (originUrl.isValid())
215 whitelist->add(SecurityOrigin::create(originUrl));
216 }
217 }
218 m_headerWhitelists.set(feature, std::move(whitelist));
219 }
212 } 220 }
213 221
214 bool FeaturePolicy::isFeatureEnabledForOrigin( 222 bool FeaturePolicy::isFeatureEnabledForOrigin(
215 const FeaturePolicy::Feature& feature, 223 const FeaturePolicy::Feature& feature,
216 const SecurityOrigin& origin) const { 224 const SecurityOrigin& origin) const {
217 DCHECK(m_inheritedFeatures.contains(&feature)); 225 DCHECK(m_inheritedFeatures.contains(&feature));
218 if (!m_inheritedFeatures.get(&feature)) { 226 if (!m_inheritedFeatures.get(&feature)) {
219 return false; 227 return false;
220 } 228 }
221 if (m_headerWhitelists.contains(&feature)) { 229 if (m_headerWhitelists.contains(&feature)) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 sb.append(" "); 266 sb.append(" ");
259 sb.append(whitelist.key->featureName); 267 sb.append(whitelist.key->featureName);
260 sb.append(": "); 268 sb.append(": ");
261 sb.append(whitelist.value->toString()); 269 sb.append(whitelist.value->toString());
262 sb.append("\n"); 270 sb.append("\n");
263 } 271 }
264 return sb.toString(); 272 return sb.toString();
265 } 273 }
266 274
267 } // namespace blink 275 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698