OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/common/extensions/feature.h" | 5 #include "chrome/common/extensions/feature.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 | 44 |
45 // TODO(aa): Can we replace all this manual parsing with JSON schema stuff? | 45 // TODO(aa): Can we replace all this manual parsing with JSON schema stuff? |
46 | 46 |
47 void ParseSet(const DictionaryValue* value, | 47 void ParseSet(const DictionaryValue* value, |
48 const std::string& property, | 48 const std::string& property, |
49 std::set<std::string>* set) { | 49 std::set<std::string>* set) { |
50 ListValue* list_value = NULL; | 50 ListValue* list_value = NULL; |
51 if (!value->GetList(property, &list_value)) | 51 if (!value->GetList(property, &list_value)) |
52 return; | 52 return; |
53 | 53 |
| 54 set->clear(); |
54 for (size_t i = 0; i < list_value->GetSize(); ++i) { | 55 for (size_t i = 0; i < list_value->GetSize(); ++i) { |
55 std::string str_val; | 56 std::string str_val; |
56 CHECK(list_value->GetString(i, &str_val)) << property << " " << i; | 57 CHECK(list_value->GetString(i, &str_val)) << property << " " << i; |
57 set->insert(str_val); | 58 set->insert(str_val); |
58 } | 59 } |
59 } | 60 } |
60 | 61 |
61 template<typename T> | 62 template<typename T> |
62 void ParseEnum(const std::string& string_value, | 63 void ParseEnum(const std::string& string_value, |
63 T* enum_value, | 64 T* enum_value, |
64 const std::map<std::string, T>& mapping) { | 65 const std::map<std::string, T>& mapping) { |
65 typename std::map<std::string, T>::const_iterator iter = | 66 typename std::map<std::string, T>::const_iterator iter = |
66 mapping.find(string_value); | 67 mapping.find(string_value); |
67 CHECK(iter != mapping.end()) << string_value; | 68 CHECK(iter != mapping.end()) << string_value; |
68 *enum_value = iter->second; | 69 *enum_value = iter->second; |
69 } | 70 } |
70 | 71 |
71 template<typename T> | 72 template<typename T> |
72 void ParseEnum(const DictionaryValue* value, | 73 void ParseEnum(const DictionaryValue* value, |
73 const std::string& property, | 74 const std::string& property, |
74 T* enum_value, | 75 T* enum_value, |
75 const std::map<std::string, T>& mapping) { | 76 const std::map<std::string, T>& mapping) { |
76 std::string string_value; | 77 std::string string_value; |
77 if (!value->GetString(property, &string_value)) | 78 if (!value->GetString(property, &string_value)) |
78 return; | 79 return; |
| 80 |
79 ParseEnum(string_value, enum_value, mapping); | 81 ParseEnum(string_value, enum_value, mapping); |
80 } | 82 } |
81 | 83 |
82 template<typename T> | 84 template<typename T> |
83 void ParseEnumSet(const DictionaryValue* value, | 85 void ParseEnumSet(const DictionaryValue* value, |
84 const std::string& property, | 86 const std::string& property, |
85 std::set<T>* enum_set, | 87 std::set<T>* enum_set, |
86 const std::map<std::string, T>& mapping) { | 88 const std::map<std::string, T>& mapping) { |
| 89 if (!value->HasKey(property)) |
| 90 return; |
| 91 |
| 92 enum_set->clear(); |
| 93 |
87 std::string property_string; | 94 std::string property_string; |
88 if (value->GetString(property, &property_string)) { | 95 if (value->GetString(property, &property_string)) { |
89 if (property_string == "all") { | 96 if (property_string == "all") { |
90 for (typename std::map<std::string, T>::const_iterator j = | 97 for (typename std::map<std::string, T>::const_iterator j = |
91 mapping.begin(); j != mapping.end(); ++j) { | 98 mapping.begin(); j != mapping.end(); ++j) { |
92 enum_set->insert(j->second); | 99 enum_set->insert(j->second); |
93 } | 100 } |
94 } | 101 } |
95 return; | 102 return; |
96 } | 103 } |
(...skipping 12 matching lines...) Expand all Loading... |
109 | 116 |
110 namespace extensions { | 117 namespace extensions { |
111 | 118 |
112 Feature::Feature() | 119 Feature::Feature() |
113 : location_(UNSPECIFIED_LOCATION), | 120 : location_(UNSPECIFIED_LOCATION), |
114 platform_(UNSPECIFIED_PLATFORM), | 121 platform_(UNSPECIFIED_PLATFORM), |
115 min_manifest_version_(0), | 122 min_manifest_version_(0), |
116 max_manifest_version_(0) { | 123 max_manifest_version_(0) { |
117 } | 124 } |
118 | 125 |
| 126 Feature::Feature(const Feature& other) |
| 127 : whitelist_(other.whitelist_), |
| 128 extension_types_(other.extension_types_), |
| 129 contexts_(other.contexts_), |
| 130 location_(other.location_), |
| 131 platform_(other.platform_), |
| 132 min_manifest_version_(other.min_manifest_version_), |
| 133 max_manifest_version_(other.max_manifest_version_) { |
| 134 } |
| 135 |
119 Feature::~Feature() { | 136 Feature::~Feature() { |
120 } | 137 } |
121 | 138 |
122 // static | 139 bool Feature::Equals(const Feature& other) const { |
123 scoped_ptr<Feature> Feature::Parse(const DictionaryValue* value) { | 140 return whitelist_ == other.whitelist_ && |
124 scoped_ptr<Feature> feature(new Feature()); | 141 extension_types_ == other.extension_types_ && |
125 | 142 contexts_ == other.contexts_ && |
126 ParseSet(value, "whitelist", feature->whitelist()); | 143 location_ == other.location_ && |
127 ParseEnumSet<Extension::Type>(value, "extension_types", | 144 platform_ == other.platform_ && |
128 feature->extension_types(), | 145 min_manifest_version_ == other.min_manifest_version_ && |
129 g_mappings.Get().extension_types); | 146 max_manifest_version_ == other.max_manifest_version_; |
130 ParseEnumSet<Context>(value, "contexts", feature->contexts(), | |
131 g_mappings.Get().contexts); | |
132 ParseEnum<Location>(value, "location", &feature->location_, | |
133 g_mappings.Get().locations); | |
134 ParseEnum<Platform>(value, "platform", &feature->platform_, | |
135 g_mappings.Get().platforms); | |
136 | |
137 value->GetInteger("min_manifest_version", &feature->min_manifest_version_); | |
138 value->GetInteger("max_manifest_version", &feature->max_manifest_version_); | |
139 | |
140 return feature.Pass(); | |
141 } | 147 } |
142 | 148 |
143 // static | 149 // static |
144 Feature::Platform Feature::GetCurrentPlatform() { | 150 Feature::Platform Feature::GetCurrentPlatform() { |
145 #if defined(OS_CHROMEOS) | 151 #if defined(OS_CHROMEOS) |
146 return CHROMEOS_PLATFORM; | 152 return CHROMEOS_PLATFORM; |
147 #else | 153 #else |
148 return UNSPECIFIED_PLATFORM; | 154 return UNSPECIFIED_PLATFORM; |
149 #endif | 155 #endif |
150 } | 156 } |
151 | 157 |
152 // static | 158 // static |
153 Feature::Location Feature::ConvertLocation(Extension::Location location) { | 159 Feature::Location Feature::ConvertLocation(Extension::Location location) { |
154 if (location == Extension::COMPONENT) | 160 if (location == Extension::COMPONENT) |
155 return COMPONENT_LOCATION; | 161 return COMPONENT_LOCATION; |
156 else | 162 else |
157 return UNSPECIFIED_LOCATION; | 163 return UNSPECIFIED_LOCATION; |
158 } | 164 } |
159 | 165 |
| 166 void Feature::Parse(const DictionaryValue* value) { |
| 167 ParseSet(value, "whitelist", &whitelist_); |
| 168 ParseEnumSet<Extension::Type>(value, "extension_types", &extension_types_, |
| 169 g_mappings.Get().extension_types); |
| 170 ParseEnumSet<Context>(value, "contexts", &contexts_, |
| 171 g_mappings.Get().contexts); |
| 172 ParseEnum<Location>(value, "location", &location_, |
| 173 g_mappings.Get().locations); |
| 174 ParseEnum<Platform>(value, "platform", &platform_, |
| 175 g_mappings.Get().platforms); |
| 176 value->GetInteger("min_manifest_version", &min_manifest_version_); |
| 177 value->GetInteger("max_manifest_version", &max_manifest_version_); |
| 178 } |
| 179 |
160 std::string Feature::GetErrorMessage(Feature::Availability result) { | 180 std::string Feature::GetErrorMessage(Feature::Availability result) { |
161 switch (result) { | 181 switch (result) { |
162 case IS_AVAILABLE: | 182 case IS_AVAILABLE: |
163 return ""; | 183 return ""; |
164 case NOT_FOUND_IN_WHITELIST: | 184 case NOT_FOUND_IN_WHITELIST: |
165 return "Not allowed for specified extension ID."; | 185 return "Not allowed for specified extension ID."; |
166 case INVALID_TYPE: | 186 case INVALID_TYPE: |
167 return "Not allowed for specified package type (theme, app, etc.)."; | 187 return "Not allowed for specified package type (theme, app, etc.)."; |
168 case INVALID_CONTEXT: | 188 case INVALID_CONTEXT: |
169 return "Not allowed for specified context type content script, extension " | 189 return "Not allowed for specified context type content script, extension " |
170 "page, web page, etc.)."; | 190 "page, web page, etc.)."; |
171 case INVALID_LOCATION: | 191 case INVALID_LOCATION: |
172 return "Not allowed for specified install location."; | 192 return "Not allowed for specified install location."; |
173 case INVALID_PLATFORM: | 193 case INVALID_PLATFORM: |
174 return "Not allowed for specified platform."; | 194 return "Not allowed for specified platform."; |
175 case INVALID_MIN_MANIFEST_VERSION: | 195 case INVALID_MIN_MANIFEST_VERSION: |
176 return base::StringPrintf("Requires manifest version of at least %d.", | 196 return base::StringPrintf("Requires manifest version of at least %d.", |
177 min_manifest_version_); | 197 min_manifest_version_); |
178 case INVALID_MAX_MANIFEST_VERSION: | 198 case INVALID_MAX_MANIFEST_VERSION: |
179 return base::StringPrintf("Requires manifest version of %d or lower.", | 199 return base::StringPrintf("Requires manifest version of %d or lower.", |
180 max_manifest_version_); | 200 max_manifest_version_); |
181 default: | 201 default: |
182 CHECK(false); | 202 CHECK(false); |
183 return ""; | 203 return ""; |
184 } | 204 } |
185 } | 205 } |
186 | 206 |
187 Feature::Availability Feature::IsAvailable(const std::string& extension_id, | 207 Feature::Availability Feature::IsAvailableToManifest( |
188 Extension::Type type, | 208 const std::string& extension_id, |
189 Location location, | 209 Extension::Type type, |
190 Context context, | 210 Location location, |
191 Platform platform, | 211 int manifest_version, |
192 int manifest_version) { | 212 Platform platform) const { |
193 // Component extensions can access any feature. | 213 // Component extensions can access any feature. |
194 if (location == COMPONENT_LOCATION) | 214 if (location == COMPONENT_LOCATION) |
195 return IS_AVAILABLE; | 215 return IS_AVAILABLE; |
196 | 216 |
197 if (!whitelist_.empty()) { | 217 if (!whitelist_.empty()) { |
198 if (whitelist_.find(extension_id) == whitelist_.end()) { | 218 if (whitelist_.find(extension_id) == whitelist_.end()) { |
199 // TODO(aa): This is gross. There should be a better way to test the | 219 // TODO(aa): This is gross. There should be a better way to test the |
200 // whitelist. | 220 // whitelist. |
201 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 221 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
202 if (!command_line->HasSwitch(switches::kWhitelistedExtensionID)) | 222 if (!command_line->HasSwitch(switches::kWhitelistedExtensionID)) |
203 return NOT_FOUND_IN_WHITELIST; | 223 return NOT_FOUND_IN_WHITELIST; |
204 | 224 |
205 std::string whitelist_switch_value = | 225 std::string whitelist_switch_value = |
206 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 226 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
207 switches::kWhitelistedExtensionID); | 227 switches::kWhitelistedExtensionID); |
208 if (extension_id != whitelist_switch_value) | 228 if (extension_id != whitelist_switch_value) |
209 return NOT_FOUND_IN_WHITELIST; | 229 return NOT_FOUND_IN_WHITELIST; |
210 } | 230 } |
211 } | 231 } |
212 | 232 |
213 if (!extension_types_.empty() && | 233 if (!extension_types_.empty() && |
214 extension_types_.find(type) == extension_types_.end()) { | 234 extension_types_.find(type) == extension_types_.end()) { |
215 return INVALID_TYPE; | 235 return INVALID_TYPE; |
216 } | 236 } |
217 | 237 |
218 if (!contexts_.empty() && | |
219 contexts_.find(context) == contexts_.end()) { | |
220 return INVALID_CONTEXT; | |
221 } | |
222 | |
223 if (location_ != UNSPECIFIED_LOCATION && location_ != location) | 238 if (location_ != UNSPECIFIED_LOCATION && location_ != location) |
224 return INVALID_LOCATION; | 239 return INVALID_LOCATION; |
225 | 240 |
226 if (platform_ != UNSPECIFIED_PLATFORM && platform_ != platform) | 241 if (platform_ != UNSPECIFIED_PLATFORM && platform_ != platform) |
227 return INVALID_PLATFORM; | 242 return INVALID_PLATFORM; |
228 | 243 |
229 if (min_manifest_version_ != 0 && manifest_version < min_manifest_version_) | 244 if (min_manifest_version_ != 0 && manifest_version < min_manifest_version_) |
230 return INVALID_MIN_MANIFEST_VERSION; | 245 return INVALID_MIN_MANIFEST_VERSION; |
231 | 246 |
232 if (max_manifest_version_ != 0 && manifest_version > max_manifest_version_) | 247 if (max_manifest_version_ != 0 && manifest_version > max_manifest_version_) |
233 return INVALID_MAX_MANIFEST_VERSION; | 248 return INVALID_MAX_MANIFEST_VERSION; |
234 | 249 |
235 return IS_AVAILABLE; | 250 return IS_AVAILABLE; |
236 } | 251 } |
237 | 252 |
| 253 Feature::Availability Feature::IsAvailableToContext( |
| 254 const Extension* extension, |
| 255 Feature::Context context, |
| 256 Feature::Platform platform) const { |
| 257 Availability result = IsAvailableToManifest( |
| 258 extension->id(), |
| 259 extension->GetType(), |
| 260 ConvertLocation(extension->location()), |
| 261 extension->manifest_version(), |
| 262 platform); |
| 263 if (result != IS_AVAILABLE) |
| 264 return result; |
| 265 |
| 266 if (!contexts_.empty() && |
| 267 contexts_.find(context) == contexts_.end()) { |
| 268 return INVALID_CONTEXT; |
| 269 } |
| 270 |
| 271 return IS_AVAILABLE; |
| 272 } |
| 273 |
238 } // namespace | 274 } // namespace |
OLD | NEW |