| 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/RuntimeEnabledFeatures.h" | 7 #include "platform/RuntimeEnabledFeatures.h" |
| 8 #include "platform/json/JSONValues.h" | 8 #include "platform/json/JSONValues.h" |
| 9 #include "platform/network/HTTPParsers.h" | 9 #include "platform/network/HTTPParsers.h" |
| 10 #include "platform/weborigin/SecurityOrigin.h" | 10 #include "platform/weborigin/SecurityOrigin.h" |
| 11 #include "platform/wtf/PtrUtil.h" | 11 #include "platform/wtf/PtrUtil.h" |
| 12 | 12 |
| 13 namespace blink { | 13 namespace blink { |
| 14 | 14 |
| 15 WebFeaturePolicyFeature GetWebFeaturePolicyFeature(const String& feature) { | 15 WebParsedFeaturePolicy ParseFeaturePolicy(const String& policy, |
| 16 if (feature == "fullscreen") | 16 RefPtr<SecurityOrigin> origin, |
| 17 return WebFeaturePolicyFeature::kFullscreen; | 17 Vector<String>* messages) { |
| 18 if (feature == "payment") | 18 return ParseFeaturePolicy(policy, origin, messages, |
| 19 return WebFeaturePolicyFeature::kPayment; | 19 GetDefaultFeatureNameMap()); |
| 20 if (feature == "vibrate") | |
| 21 return WebFeaturePolicyFeature::kVibrate; | |
| 22 if (RuntimeEnabledFeatures::featurePolicyExperimentalFeaturesEnabled()) { | |
| 23 if (feature == "camera") | |
| 24 return WebFeaturePolicyFeature::kCamera; | |
| 25 if (feature == "eme") | |
| 26 return WebFeaturePolicyFeature::kEme; | |
| 27 if (feature == "microphone") | |
| 28 return WebFeaturePolicyFeature::kMicrophone; | |
| 29 if (feature == "speaker") | |
| 30 return WebFeaturePolicyFeature::kSpeaker; | |
| 31 if (feature == "cookie") | |
| 32 return WebFeaturePolicyFeature::kDocumentCookie; | |
| 33 if (feature == "domain") | |
| 34 return WebFeaturePolicyFeature::kDocumentDomain; | |
| 35 if (feature == "docwrite") | |
| 36 return WebFeaturePolicyFeature::kDocumentWrite; | |
| 37 if (feature == "geolocation") | |
| 38 return WebFeaturePolicyFeature::kGeolocation; | |
| 39 if (feature == "midi") | |
| 40 return WebFeaturePolicyFeature::kMidiFeature; | |
| 41 if (feature == "notifications") | |
| 42 return WebFeaturePolicyFeature::kNotifications; | |
| 43 if (feature == "push") | |
| 44 return WebFeaturePolicyFeature::kPush; | |
| 45 if (feature == "sync-script") | |
| 46 return WebFeaturePolicyFeature::kSyncScript; | |
| 47 if (feature == "sync-xhr") | |
| 48 return WebFeaturePolicyFeature::kSyncXHR; | |
| 49 if (feature == "webrtc") | |
| 50 return WebFeaturePolicyFeature::kWebRTC; | |
| 51 } | |
| 52 return WebFeaturePolicyFeature::kNotFound; | |
| 53 } | 20 } |
| 54 | 21 |
| 55 WebParsedFeaturePolicy ParseFeaturePolicy(const String& policy, | 22 WebParsedFeaturePolicy ParseFeaturePolicy(const String& policy, |
| 56 RefPtr<SecurityOrigin> origin, | 23 RefPtr<SecurityOrigin> origin, |
| 57 Vector<String>* messages) { | 24 Vector<String>* messages, |
| 25 const FeatureNameMap& feature_names) { |
| 58 Vector<WebParsedFeaturePolicyDeclaration> whitelists; | 26 Vector<WebParsedFeaturePolicyDeclaration> whitelists; |
| 59 | 27 |
| 60 // Use a reasonable parse depth limit; the actual maximum depth is only going | 28 // Use a reasonable parse depth limit; the actual maximum depth is only going |
| 61 // to be 4 for a valid policy, but we'll give the featurePolicyParser a chance | 29 // to be 4 for a valid policy, but we'll give the featurePolicyParser a chance |
| 62 // to report more specific errors, unless the string is really invalid. | 30 // to report more specific errors, unless the string is really invalid. |
| 63 std::unique_ptr<JSONArray> policy_items = ParseJSONHeader(policy, 50); | 31 std::unique_ptr<JSONArray> policy_items = ParseJSONHeader(policy, 50); |
| 64 if (!policy_items) { | 32 if (!policy_items) { |
| 65 if (messages) | 33 if (messages) |
| 66 messages->push_back("Unable to parse header."); | 34 messages->push_back("Unable to parse header."); |
| 67 return whitelists; | 35 return whitelists; |
| 68 } | 36 } |
| 69 | 37 |
| 70 for (size_t i = 0; i < policy_items->size(); ++i) { | 38 for (size_t i = 0; i < policy_items->size(); ++i) { |
| 71 JSONObject* item = JSONObject::Cast(policy_items->at(i)); | 39 JSONObject* item = JSONObject::Cast(policy_items->at(i)); |
| 72 if (!item) { | 40 if (!item) { |
| 73 if (messages) | 41 if (messages) |
| 74 messages->push_back("Policy is not an object."); | 42 messages->push_back("Policy is not an object."); |
| 75 continue; // Array element is not an object; skip | 43 continue; // Array element is not an object; skip |
| 76 } | 44 } |
| 77 | 45 |
| 78 for (size_t j = 0; j < item->size(); ++j) { | 46 for (size_t j = 0; j < item->size(); ++j) { |
| 79 JSONObject::Entry entry = item->at(j); | 47 JSONObject::Entry entry = item->at(j); |
| 80 WebFeaturePolicyFeature feature = GetWebFeaturePolicyFeature(entry.first); | 48 if (!feature_names.Contains(entry.first)) |
| 81 if (feature == WebFeaturePolicyFeature::kNotFound) | |
| 82 continue; // Unrecognized feature; skip | 49 continue; // Unrecognized feature; skip |
| 50 WebFeaturePolicyFeature feature = feature_names.at(entry.first); |
| 83 JSONArray* targets = JSONArray::Cast(entry.second); | 51 JSONArray* targets = JSONArray::Cast(entry.second); |
| 84 if (!targets) { | 52 if (!targets) { |
| 85 if (messages) | 53 if (messages) |
| 86 messages->push_back("Whitelist is not an array of strings."); | 54 messages->push_back("Whitelist is not an array of strings."); |
| 87 continue; | 55 continue; |
| 88 } | 56 } |
| 89 | 57 |
| 90 WebParsedFeaturePolicyDeclaration whitelist; | 58 WebParsedFeaturePolicyDeclaration whitelist; |
| 91 whitelist.feature = feature; | 59 whitelist.feature = feature; |
| 92 Vector<WebSecurityOrigin> origins; | 60 Vector<WebSecurityOrigin> origins; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 Vector<WebParsedFeaturePolicyDeclaration> whitelists; | 92 Vector<WebParsedFeaturePolicyDeclaration> whitelists; |
| 125 for (const WebFeaturePolicyFeature feature : features) { | 93 for (const WebFeaturePolicyFeature feature : features) { |
| 126 WebParsedFeaturePolicyDeclaration whitelist; | 94 WebParsedFeaturePolicyDeclaration whitelist; |
| 127 whitelist.feature = feature; | 95 whitelist.feature = feature; |
| 128 whitelist.origins = Vector<WebSecurityOrigin>(1UL, {origin}); | 96 whitelist.origins = Vector<WebSecurityOrigin>(1UL, {origin}); |
| 129 whitelists.push_back(whitelist); | 97 whitelists.push_back(whitelist); |
| 130 } | 98 } |
| 131 return whitelists; | 99 return whitelists; |
| 132 } | 100 } |
| 133 | 101 |
| 102 const FeatureNameMap& GetDefaultFeatureNameMap() { |
| 103 DEFINE_STATIC_LOCAL(FeatureNameMap, default_feature_name_map, ()); |
| 104 if (default_feature_name_map.IsEmpty()) { |
| 105 default_feature_name_map.Set("fullscreen", |
| 106 WebFeaturePolicyFeature::kFullscreen); |
| 107 default_feature_name_map.Set("payment", WebFeaturePolicyFeature::kPayment); |
| 108 if (RuntimeEnabledFeatures::featurePolicyExperimentalFeaturesEnabled()) { |
| 109 default_feature_name_map.Set("vibrate", |
| 110 WebFeaturePolicyFeature::kVibrate); |
| 111 default_feature_name_map.Set("camera", WebFeaturePolicyFeature::kCamera); |
| 112 default_feature_name_map.Set("eme", WebFeaturePolicyFeature::kEme); |
| 113 default_feature_name_map.Set("microphone", |
| 114 WebFeaturePolicyFeature::kMicrophone); |
| 115 default_feature_name_map.Set("speaker", |
| 116 WebFeaturePolicyFeature::kSpeaker); |
| 117 default_feature_name_map.Set("cookie", |
| 118 WebFeaturePolicyFeature::kDocumentCookie); |
| 119 default_feature_name_map.Set("domain", |
| 120 WebFeaturePolicyFeature::kDocumentDomain); |
| 121 default_feature_name_map.Set("docwrit", |
| 122 WebFeaturePolicyFeature::kDocumentWrite); |
| 123 default_feature_name_map.Set("geolocation", |
| 124 WebFeaturePolicyFeature::kGeolocation); |
| 125 default_feature_name_map.Set("midi", |
| 126 WebFeaturePolicyFeature::kMidiFeature); |
| 127 default_feature_name_map.Set("notifications", |
| 128 WebFeaturePolicyFeature::kNotifications); |
| 129 default_feature_name_map.Set("push", WebFeaturePolicyFeature::kPush); |
| 130 default_feature_name_map.Set("sync-script", |
| 131 WebFeaturePolicyFeature::kSyncScript); |
| 132 default_feature_name_map.Set("sync-xhr", |
| 133 WebFeaturePolicyFeature::kSyncXHR); |
| 134 default_feature_name_map.Set("webrtc", WebFeaturePolicyFeature::kWebRTC); |
| 135 } |
| 136 } |
| 137 return default_feature_name_map; |
| 138 } |
| 139 |
| 134 } // namespace blink | 140 } // namespace blink |
| OLD | NEW |