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

Unified Diff: third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp

Issue 2254533002: [FeaturePolicy] Initial implementation of Feature Policy (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@fp-flag
Patch Set: Remove overaggressive bool transform Created 4 years, 3 months 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp
diff --git a/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ab075d930abbcd3dc709d89eb118616cb4a62b14
--- /dev/null
+++ b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp
@@ -0,0 +1,189 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/feature_policy/FeaturePolicy.h"
+
+#include "platform/json/JSONParser.h"
+#include "platform/json/JSONValues.h"
+#include "platform/weborigin/KURL.h"
+#include "platform/weborigin/SecurityOrigin.h"
+#include "wtf/text/StringBuilder.h"
+#include <algorithm>
+
+namespace blink {
+
+namespace {
+
+const FeaturePolicyFeature* featureForName(const String& featureName)
+{
+ // TODO: Use make_token_matcher.py to generate this code.
+ if (featureName == "cookie")
+ return &kDocumentCookie;
+ if (featureName == "domain")
+ return &kDocumentDomain;
+ if (featureName == "docwrite")
+ return &kDocumentWrite;
+ if (featureName == "vibrate")
+ return &kVibrate;
+ if (featureName == "webrtc")
+ return &kWebRTC;
+ return &kNoSuchFeature;
+}
+
+} // namespace
+
+const FeaturePolicyFeature kDocumentCookie { "cookie", true, true };
+const FeaturePolicyFeature kDocumentDomain { "domain", true, true };
+const FeaturePolicyFeature kDocumentWrite { "docwrite", true, true };
+const FeaturePolicyFeature kVibrate { "vibrate", true, false };
+const FeaturePolicyFeature kWebRTC { "webrtc", true, true };
+const FeaturePolicyFeature kNoSuchFeature { "", false, false };
+
+FeaturePolicy::Whitelist::Whitelist()
+ : m_matchesAllOrigins(false)
+{
+}
+
+void FeaturePolicy::Whitelist::addAll()
+{
+ m_matchesAllOrigins = true;
+}
+
+void FeaturePolicy::Whitelist::add(RefPtr<SecurityOrigin> origin)
+{
+ origins.append(origin);
+}
+
+bool FeaturePolicy::Whitelist::targets(const SecurityOrigin* origin) const
raymes 2016/09/19 09:19:05 nit: would "contains" be slightly clearer?
iclelland 2016/09/27 15:06:27 Probably; I was using the nomenclature from the or
iclelland 2016/10/14 19:37:49 Done.
+{
+ if (m_matchesAllOrigins)
+ return true;
+ return (std::any_of(origins.begin(), origins.end(),
+ [origin](const RefPtr<SecurityOrigin>& target)
+ {
+ return target->isSameSchemeHostPortAndSuborigin(origin);
+ }));
raymes 2016/09/19 09:19:04 (optionally) the long-hand way isn't much longer f
iclelland 2016/09/27 15:06:27 Thanks, that's clearer. (I always have such high h
+}
+
+// static
+FeaturePolicy* FeaturePolicy::createFromParentPolicy(const FeaturePolicy* parent, RefPtr<SecurityOrigin> currentOrigin)
+{
+ FeaturePolicy* newPolicy = new FeaturePolicy(currentOrigin, !parent);
+ if (parent) {
+ for (const auto& item : parent->m_whitelists) {
+ Whitelist newWhitelist;
+ if (item.value.targets(currentOrigin.get())) {
+ newWhitelist.add(currentOrigin);
+ }
+ newPolicy->m_whitelists.set(item.key, newWhitelist);
+ }
+ }
+ return newPolicy;
+}
+
+void FeaturePolicy::addPolicyFromString(const String& policy)
raymes 2016/09/19 09:19:04 I think it's a little unclear what it means to "ad
iclelland 2016/09/27 15:06:28 I wouldn't want to pass in the current frame's str
+{
+ if (policy.isEmpty())
+ return;
+ for (const auto& whitelist : parse(policy)) {
+ if (isFeatureEnabled(whitelist.key)) {
+ m_whitelists.set(whitelist.key, whitelist.value);
+ }
raymes 2016/09/19 09:19:05 Hmm, what about the case where the parent sets "do
iclelland 2016/09/27 15:06:27 No, I think you're right, and I didn't catch that
raymes 2016/09/29 07:17:00 Hmm, I'm still not sure I feel comfortable with th
iclelland 2016/09/30 15:39:26 Sounds like a good idea. I'll see if I can find so
+ }
+}
+
+bool FeaturePolicy::isFeatureEnabledForOrigin(const FeaturePolicyFeature* feature, const SecurityOrigin* origin)
+{
+ if (m_whitelists.contains(feature)) {
+ const Whitelist& whitelist = m_whitelists.get(feature);
+ return whitelist.targets(origin);
+ }
+ return isFeatureEnabledByDefault(feature, m_isTopLevel);
+}
+
+bool FeaturePolicy::isFeatureEnabled(const FeaturePolicyFeature* feature)
+{
+ return isFeatureEnabledForOrigin(feature, m_origin.get());
+}
+
+// static
+bool FeaturePolicy::isFeatureEnabledByDefault(const FeaturePolicyFeature* feature, bool isTopLevel)
+{
+ if (isTopLevel)
+ return feature->enabledByDefault;
+ return feature->enabledInNestedContext;
+}
+
+void FeaturePolicy::setFeaturePolicyBindingsInstalled()
+{
+ m_bindingsInstalled = true;
+}
+
+bool FeaturePolicy::featurePolicyBindingsInstalled()
+{
+ return m_bindingsInstalled;
+}
+
+FeaturePolicy::FeaturePolicy(PassRefPtr<SecurityOrigin> currentOrigin, bool isTopLevel)
+ : m_origin(currentOrigin)
+ , m_isTopLevel(isTopLevel)
+{
+}
+
+HashMap<const FeaturePolicyFeature*, FeaturePolicy::Whitelist>
+FeaturePolicy::parse(const String& policy)
+{
+ HashMap<const FeaturePolicyFeature*, Whitelist> whitelists;
+ std::unique_ptr<JSONValue> policyJSON = parseJSON(policy);
+
+ if (!policyJSON)
+ return whitelists;
+
+ std::unique_ptr<JSONArray> items = JSONArray::cast(std::move(policyJSON));
+ if (!items)
+ return whitelists;
+
+ for (size_t i = 0; i < items->size(); ++i) {
+ JSONObject* item = JSONObject::cast(items->at(i));
+ if (!item)
+ continue;
+
+ for (size_t j = 0; j < item->size(); ++j) {
+ JSONObject::Entry entry = item->at(j);
+ String featureName = entry.first;
+ const FeaturePolicyFeature* feature = featureForName(featureName);
+ if (feature != &kNoSuchFeature) {
+ JSONArray* targets = JSONArray::cast(entry.second);
+ if (targets) {
+ Whitelist whitelist;
+ String targetString;
+ for (size_t j = 0; j < targets->size(); ++j) {
+ if (targets->at(j)->asString(&targetString)) {
+ if (equalIgnoringCase(targetString, "self")) {
+ whitelist.add(m_origin);
+ } else if (targetString == "*") {
+ whitelist.addAll();
+ } else {
+ KURL originUrl = KURL(KURL(), targetString);
+ if (originUrl.isValid()) {
+ whitelist.add(SecurityOrigin::create(originUrl));
+ }
+ }
+ }
+ }
+ whitelists.set(feature, whitelist);
+ }
+ } else {
+ continue; // Not a string or an array; invalid policy spec.
+ }
+ }
+ }
+ return whitelists;
raymes 2016/09/19 09:19:05 I haven't reviewed the parsing yet :)
iclelland 2016/09/27 15:06:28 NP; I haven't written a fuzzer for it yet either :
iclelland 2016/10/14 19:37:49 https://codereview.chromium.org/2420013004 FYI
+}
+
+DEFINE_TRACE(FeaturePolicy)
+{
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698