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

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: Replicate a parsed feature policy representation so it doesn't need to be parsed in the browser pro… 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 10 matching lines...) Expand all
113 "sync-script", FeaturePolicy::FeatureDefault::EnableForAll}; 50 "sync-script", FeaturePolicy::FeatureDefault::EnableForAll};
114 const FeaturePolicy::Feature kSyncXHR{ 51 const FeaturePolicy::Feature kSyncXHR{
115 "sync-xhr", FeaturePolicy::FeatureDefault::EnableForAll}; 52 "sync-xhr", FeaturePolicy::FeatureDefault::EnableForAll};
116 const FeaturePolicy::Feature kUsermedia{ 53 const FeaturePolicy::Feature kUsermedia{
117 "usermedia", FeaturePolicy::FeatureDefault::EnableForAll}; 54 "usermedia", FeaturePolicy::FeatureDefault::EnableForAll};
118 const FeaturePolicy::Feature kVibrateFeature{ 55 const FeaturePolicy::Feature kVibrateFeature{
119 "vibrate", FeaturePolicy::FeatureDefault::EnableForSelf}; 56 "vibrate", FeaturePolicy::FeatureDefault::EnableForSelf};
120 const FeaturePolicy::Feature kWebRTC{ 57 const FeaturePolicy::Feature kWebRTC{
121 "webrtc", FeaturePolicy::FeatureDefault::EnableForAll}; 58 "webrtc", FeaturePolicy::FeatureDefault::EnableForAll};
122 59
60 // static
61 std::unique_ptr<FeaturePolicy::Whitelist> FeaturePolicy::Whitelist::from(
62 const WebFeaturePolicy::ParsedWhitelist& parsedWhitelist) {
63 std::unique_ptr<Whitelist> whitelist(new FeaturePolicy::Whitelist);
64 if (parsedWhitelist.matchesAllOrigins) {
65 whitelist->addAll();
66 } else {
67 for (const WebSecurityOrigin& origin : parsedWhitelist.origins)
68 whitelist->add(static_cast<WTF::PassRefPtr<SecurityOrigin>>(origin));
69 }
70 return whitelist;
71 }
72
123 FeaturePolicy::Whitelist::Whitelist() : m_matchesAllOrigins(false) {} 73 FeaturePolicy::Whitelist::Whitelist() : m_matchesAllOrigins(false) {}
124 74
125 void FeaturePolicy::Whitelist::addAll() { 75 void FeaturePolicy::Whitelist::addAll() {
126 m_matchesAllOrigins = true; 76 m_matchesAllOrigins = true;
127 } 77 }
128 78
129 void FeaturePolicy::Whitelist::add(RefPtr<SecurityOrigin> origin) { 79 void FeaturePolicy::Whitelist::add(RefPtr<SecurityOrigin> origin) {
130 m_origins.append(std::move(origin)); 80 m_origins.append(std::move(origin));
131 } 81 }
132 82
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 } 138 }
189 139
190 // static 140 // static
191 std::unique_ptr<FeaturePolicy> FeaturePolicy::createFromParentPolicy( 141 std::unique_ptr<FeaturePolicy> FeaturePolicy::createFromParentPolicy(
192 const FeaturePolicy* parent, 142 const FeaturePolicy* parent,
193 RefPtr<SecurityOrigin> currentOrigin) { 143 RefPtr<SecurityOrigin> currentOrigin) {
194 return createFromParentPolicy(parent, std::move(currentOrigin), 144 return createFromParentPolicy(parent, std::move(currentOrigin),
195 getDefaultFeatureList()); 145 getDefaultFeatureList());
196 } 146 }
197 147
198 void FeaturePolicy::setHeaderPolicy(const String& policy, 148 // static
199 Vector<String>* messages) { 149 WebParsedFeaturePolicy FeaturePolicy::parseFeaturePolicy(
200 DCHECK(m_headerWhitelists.isEmpty()); 150 const String& policy,
151 RefPtr<SecurityOrigin> origin,
152 Vector<String>* messages) {
153 Vector<WebFeaturePolicy::ParsedWhitelist> whitelists;
154
201 // Use a reasonable parse depth limit; the actual maximum depth is only going 155 // 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 156 // 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. 157 // to report more specific errors, unless the string is really invalid.
204 std::unique_ptr<JSONArray> policyJSON = parseJSONHeader(policy, 50); 158 std::unique_ptr<JSONArray> policyItems = parseJSONHeader(policy, 50);
205 if (!policyJSON) { 159 if (!policyItems) {
206 if (messages) 160 if (messages)
207 messages->append("Unable to parse header"); 161 messages->append("Unable to parse header");
208 return; 162 return whitelists;
209 } 163 }
210 m_headerWhitelists = parseFeaturePolicyFromJson( 164
211 std::move(policyJSON), m_origin, m_features, messages); 165 for (size_t i = 0; i < policyItems->size(); ++i) {
166 JSONObject* item = JSONObject::cast(policyItems->at(i));
167 if (!item) {
168 if (messages)
169 messages->append("Policy is not an object");
170 continue; // Array element is not an object; skip
171 }
172
173 for (size_t j = 0; j < item->size(); ++j) {
174 JSONObject::Entry entry = item->at(j);
175 String featureName = entry.first;
176 JSONArray* targets = JSONArray::cast(entry.second);
177 if (!targets) {
178 if (messages)
179 messages->append("Whitelist is not an array of strings.");
180 continue;
181 }
182
183 WebFeaturePolicy::ParsedWhitelist whitelist;
184 whitelist.featureName = featureName;
185 Vector<WebSecurityOrigin> origins;
186 String targetString;
187 for (size_t j = 0; j < targets->size(); ++j) {
188 if (targets->at(j)->asString(&targetString)) {
189 if (equalIgnoringCase(targetString, "self")) {
190 if (!origin->isUnique())
iclelland 2016/11/30 22:13:10 This isn't strictly necessary for the policy objec
Marijn Kruisselbrink 2016/11/30 22:21:00 This is not true. isSameSchemeHostPort() starts wi
raymes 2016/11/30 23:18:23 Good point - I guess it just felt weird to add a u
iclelland 2016/12/01 03:31:25 You're absolutely right -- when I went to check to
191 origins.append(origin);
192 } else if (targetString == "*") {
193 whitelist.matchesAllOrigins = true;
194 } else {
195 WebSecurityOrigin targetOrigin =
196 WebSecurityOrigin::createFromString(targetString);
197 if (!targetOrigin.isNull() && !targetOrigin.isUnique())
198 origins.append(targetOrigin);
199 }
200 } else {
201 if (messages)
202 messages->append("Whitelist is not an array of strings.");
203 }
204 }
205 whitelist.origins = origins;
206 whitelists.append(whitelist);
207 }
208 }
209 return whitelists;
210 }
211
212 void FeaturePolicy::setHeaderPolicy(const WebParsedFeaturePolicy& policy) {
213 DCHECK(m_headerWhitelists.isEmpty());
214 for (const WebFeaturePolicy::ParsedWhitelist& parsedWhitelist : policy) {
215 const FeaturePolicy::Feature* feature =
216 featureForName(parsedWhitelist.featureName, m_features);
217 if (!feature)
218 continue;
219 m_headerWhitelists.set(feature, Whitelist::from(parsedWhitelist));
220 }
212 } 221 }
213 222
214 bool FeaturePolicy::isFeatureEnabledForOrigin( 223 bool FeaturePolicy::isFeatureEnabledForOrigin(
215 const FeaturePolicy::Feature& feature, 224 const FeaturePolicy::Feature& feature,
216 const SecurityOrigin& origin) const { 225 const SecurityOrigin& origin) const {
217 DCHECK(m_inheritedFeatures.contains(&feature)); 226 DCHECK(m_inheritedFeatures.contains(&feature));
218 if (!m_inheritedFeatures.get(&feature)) { 227 if (!m_inheritedFeatures.get(&feature)) {
219 return false; 228 return false;
220 } 229 }
221 if (m_headerWhitelists.contains(&feature)) { 230 if (m_headerWhitelists.contains(&feature)) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 sb.append(" "); 267 sb.append(" ");
259 sb.append(whitelist.key->featureName); 268 sb.append(whitelist.key->featureName);
260 sb.append(": "); 269 sb.append(": ");
261 sb.append(whitelist.value->toString()); 270 sb.append(whitelist.value->toString());
262 sb.append("\n"); 271 sb.append("\n");
263 } 272 }
264 return sb.toString(); 273 return sb.toString();
265 } 274 }
266 275
267 } // namespace blink 276 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698