OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "extensions/common/features/simple_feature.h" | 5 #include "extensions/common/features/simple_feature.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/lazy_instance.h" | |
12 #include "base/sha1.h" | 11 #include "base/sha1.h" |
13 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
14 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
15 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
16 #include "extensions/common/switches.h" | 15 #include "extensions/common/switches.h" |
17 | 16 |
18 namespace extensions { | 17 namespace extensions { |
19 | 18 |
20 namespace { | 19 namespace { |
21 | 20 |
22 struct Mappings { | |
23 Mappings() { | |
24 extension_types["extension"] = Manifest::TYPE_EXTENSION; | |
25 extension_types["theme"] = Manifest::TYPE_THEME; | |
26 extension_types["legacy_packaged_app"] = Manifest::TYPE_LEGACY_PACKAGED_APP; | |
27 extension_types["hosted_app"] = Manifest::TYPE_HOSTED_APP; | |
28 extension_types["platform_app"] = Manifest::TYPE_PLATFORM_APP; | |
29 extension_types["shared_module"] = Manifest::TYPE_SHARED_MODULE; | |
30 | |
31 contexts["blessed_extension"] = Feature::BLESSED_EXTENSION_CONTEXT; | |
32 contexts["unblessed_extension"] = Feature::UNBLESSED_EXTENSION_CONTEXT; | |
33 contexts["content_script"] = Feature::CONTENT_SCRIPT_CONTEXT; | |
34 contexts["web_page"] = Feature::WEB_PAGE_CONTEXT; | |
35 contexts["blessed_web_page"] = Feature::BLESSED_WEB_PAGE_CONTEXT; | |
36 | |
37 locations["component"] = Feature::COMPONENT_LOCATION; | |
38 | |
39 platforms["chromeos"] = Feature::CHROMEOS_PLATFORM; | |
40 platforms["linux"] = Feature::LINUX_PLATFORM; | |
41 platforms["mac"] = Feature::MACOSX_PLATFORM; | |
42 platforms["win"] = Feature::WIN_PLATFORM; | |
43 } | |
44 | |
45 std::map<std::string, Manifest::Type> extension_types; | |
46 std::map<std::string, Feature::Context> contexts; | |
47 std::map<std::string, Feature::Location> locations; | |
48 std::map<std::string, Feature::Platform> platforms; | |
49 }; | |
50 | |
51 base::LazyInstance<Mappings> g_mappings = LAZY_INSTANCE_INITIALIZER; | |
52 | |
53 // TODO(aa): Can we replace all this manual parsing with JSON schema stuff? | 21 // TODO(aa): Can we replace all this manual parsing with JSON schema stuff? |
54 | 22 |
55 void ParseSet(const base::DictionaryValue* value, | 23 void ParseSet(const base::DictionaryValue* value, |
56 const std::string& property, | 24 const std::string& property, |
57 std::set<std::string>* set) { | 25 std::set<std::string>* set) { |
58 const base::ListValue* list_value = NULL; | 26 const base::ListValue* list_value = NULL; |
59 if (!value->GetList(property, &list_value)) | 27 if (!value->GetList(property, &list_value)) |
60 return; | 28 return; |
61 | 29 |
62 set->clear(); | 30 set->clear(); |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 } | 175 } |
208 | 176 |
209 std::string HashExtensionId(const std::string& extension_id) { | 177 std::string HashExtensionId(const std::string& extension_id) { |
210 const std::string id_hash = base::SHA1HashString(extension_id); | 178 const std::string id_hash = base::SHA1HashString(extension_id); |
211 DCHECK(id_hash.length() == base::kSHA1Length); | 179 DCHECK(id_hash.length() == base::kSHA1Length); |
212 return base::HexEncode(id_hash.c_str(), id_hash.length()); | 180 return base::HexEncode(id_hash.c_str(), id_hash.length()); |
213 } | 181 } |
214 | 182 |
215 } // namespace | 183 } // namespace |
216 | 184 |
| 185 struct SimpleFeature::Mappings { |
| 186 Mappings() { |
| 187 extension_types["extension"] = Manifest::TYPE_EXTENSION; |
| 188 extension_types["theme"] = Manifest::TYPE_THEME; |
| 189 extension_types["legacy_packaged_app"] = Manifest::TYPE_LEGACY_PACKAGED_APP; |
| 190 extension_types["hosted_app"] = Manifest::TYPE_HOSTED_APP; |
| 191 extension_types["platform_app"] = Manifest::TYPE_PLATFORM_APP; |
| 192 extension_types["shared_module"] = Manifest::TYPE_SHARED_MODULE; |
| 193 |
| 194 contexts["blessed_extension"] = Feature::BLESSED_EXTENSION_CONTEXT; |
| 195 contexts["unblessed_extension"] = Feature::UNBLESSED_EXTENSION_CONTEXT; |
| 196 contexts["content_script"] = Feature::CONTENT_SCRIPT_CONTEXT; |
| 197 contexts["web_page"] = Feature::WEB_PAGE_CONTEXT; |
| 198 contexts["blessed_web_page"] = Feature::BLESSED_WEB_PAGE_CONTEXT; |
| 199 |
| 200 locations["component"] = SimpleFeature::COMPONENT_LOCATION; |
| 201 locations["policy"] = SimpleFeature::POLICY_LOCATION; |
| 202 |
| 203 platforms["chromeos"] = Feature::CHROMEOS_PLATFORM; |
| 204 platforms["linux"] = Feature::LINUX_PLATFORM; |
| 205 platforms["mac"] = Feature::MACOSX_PLATFORM; |
| 206 platforms["win"] = Feature::WIN_PLATFORM; |
| 207 } |
| 208 |
| 209 std::map<std::string, Manifest::Type> extension_types; |
| 210 std::map<std::string, Feature::Context> contexts; |
| 211 std::map<std::string, SimpleFeature::Location> locations; |
| 212 std::map<std::string, Feature::Platform> platforms; |
| 213 }; |
| 214 |
| 215 // static |
| 216 base::LazyInstance<SimpleFeature::Mappings> SimpleFeature::g_mappings = |
| 217 LAZY_INSTANCE_INITIALIZER; |
| 218 |
217 SimpleFeature::SimpleFeature() | 219 SimpleFeature::SimpleFeature() |
218 : location_(UNSPECIFIED_LOCATION), | 220 : location_(UNSPECIFIED_LOCATION), |
219 min_manifest_version_(0), | 221 min_manifest_version_(0), |
220 max_manifest_version_(0), | 222 max_manifest_version_(0), |
221 has_parent_(false) {} | 223 has_parent_(false) {} |
222 | 224 |
223 SimpleFeature::~SimpleFeature() {} | 225 SimpleFeature::~SimpleFeature() {} |
224 | 226 |
225 void SimpleFeature::AddFilter(scoped_ptr<SimpleFeatureFilter> filter) { | 227 void SimpleFeature::AddFilter(scoped_ptr<SimpleFeatureFilter> filter) { |
226 filters_.push_back(make_linked_ptr(filter.release())); | 228 filters_.push_back(make_linked_ptr(filter.release())); |
(...skipping 30 matching lines...) Expand all Loading... |
257 return result; | 259 return result; |
258 } | 260 } |
259 } | 261 } |
260 | 262 |
261 return std::string(); | 263 return std::string(); |
262 } | 264 } |
263 | 265 |
264 Feature::Availability SimpleFeature::IsAvailableToManifest( | 266 Feature::Availability SimpleFeature::IsAvailableToManifest( |
265 const std::string& extension_id, | 267 const std::string& extension_id, |
266 Manifest::Type type, | 268 Manifest::Type type, |
267 Location location, | 269 Manifest::Location location, |
268 int manifest_version, | 270 int manifest_version, |
269 Platform platform) const { | 271 Platform platform) const { |
270 // Check extension type first to avoid granting platform app permissions | 272 // Check extension type first to avoid granting platform app permissions |
271 // to component extensions. | 273 // to component extensions. |
272 // HACK(kalman): user script -> extension. Solve this in a more generic way | 274 // HACK(kalman): user script -> extension. Solve this in a more generic way |
273 // when we compile feature files. | 275 // when we compile feature files. |
274 Manifest::Type type_to_check = (type == Manifest::TYPE_USER_SCRIPT) ? | 276 Manifest::Type type_to_check = (type == Manifest::TYPE_USER_SCRIPT) ? |
275 Manifest::TYPE_EXTENSION : type; | 277 Manifest::TYPE_EXTENSION : type; |
276 if (!extension_types_.empty() && | 278 if (!extension_types_.empty() && |
277 extension_types_.find(type_to_check) == extension_types_.end()) { | 279 extension_types_.find(type_to_check) == extension_types_.end()) { |
278 return CreateAvailability(INVALID_TYPE, type); | 280 return CreateAvailability(INVALID_TYPE, type); |
279 } | 281 } |
280 | 282 |
281 // Component extensions can access any feature. | 283 // Component extensions can access any feature. |
282 if (location == COMPONENT_LOCATION) | 284 // TODO(kalman/asargent): Should this match EXTERNAL_COMPONENT too? |
| 285 if (location == Manifest::COMPONENT) |
283 return CreateAvailability(IS_AVAILABLE, type); | 286 return CreateAvailability(IS_AVAILABLE, type); |
284 | 287 |
285 if (!whitelist_.empty()) { | 288 if (!whitelist_.empty()) { |
286 if (!IsIdInWhitelist(extension_id)) { | 289 if (!IsIdInWhitelist(extension_id)) { |
287 // TODO(aa): This is gross. There should be a better way to test the | 290 // TODO(aa): This is gross. There should be a better way to test the |
288 // whitelist. | 291 // whitelist. |
289 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 292 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
290 if (!command_line->HasSwitch(switches::kWhitelistedExtensionID)) | 293 if (!command_line->HasSwitch(switches::kWhitelistedExtensionID)) |
291 return CreateAvailability(NOT_FOUND_IN_WHITELIST, type); | 294 return CreateAvailability(NOT_FOUND_IN_WHITELIST, type); |
292 | 295 |
293 std::string whitelist_switch_value = | 296 std::string whitelist_switch_value = |
294 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 297 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
295 switches::kWhitelistedExtensionID); | 298 switches::kWhitelistedExtensionID); |
296 if (extension_id != whitelist_switch_value) | 299 if (extension_id != whitelist_switch_value) |
297 return CreateAvailability(NOT_FOUND_IN_WHITELIST, type); | 300 return CreateAvailability(NOT_FOUND_IN_WHITELIST, type); |
298 } | 301 } |
299 } | 302 } |
300 | 303 |
301 if (location_ != UNSPECIFIED_LOCATION && location_ != location) | 304 if (!MatchesManifestLocation(location)) |
302 return CreateAvailability(INVALID_LOCATION, type); | 305 return CreateAvailability(INVALID_LOCATION, type); |
303 | 306 |
304 if (!platforms_.empty() && | 307 if (!platforms_.empty() && |
305 platforms_.find(platform) == platforms_.end()) | 308 platforms_.find(platform) == platforms_.end()) |
306 return CreateAvailability(INVALID_PLATFORM, type); | 309 return CreateAvailability(INVALID_PLATFORM, type); |
307 | 310 |
308 if (min_manifest_version_ != 0 && manifest_version < min_manifest_version_) | 311 if (min_manifest_version_ != 0 && manifest_version < min_manifest_version_) |
309 return CreateAvailability(INVALID_MIN_MANIFEST_VERSION, type); | 312 return CreateAvailability(INVALID_MIN_MANIFEST_VERSION, type); |
310 | 313 |
311 if (max_manifest_version_ != 0 && manifest_version > max_manifest_version_) | 314 if (max_manifest_version_ != 0 && manifest_version > max_manifest_version_) |
(...skipping 10 matching lines...) Expand all Loading... |
322 | 325 |
323 return CreateAvailability(IS_AVAILABLE, type); | 326 return CreateAvailability(IS_AVAILABLE, type); |
324 } | 327 } |
325 | 328 |
326 Feature::Availability SimpleFeature::IsAvailableToContext( | 329 Feature::Availability SimpleFeature::IsAvailableToContext( |
327 const Extension* extension, | 330 const Extension* extension, |
328 SimpleFeature::Context context, | 331 SimpleFeature::Context context, |
329 const GURL& url, | 332 const GURL& url, |
330 SimpleFeature::Platform platform) const { | 333 SimpleFeature::Platform platform) const { |
331 if (extension) { | 334 if (extension) { |
332 Availability result = IsAvailableToManifest( | 335 Availability result = IsAvailableToManifest(extension->id(), |
333 extension->id(), | 336 extension->GetType(), |
334 extension->GetType(), | 337 extension->location(), |
335 ConvertLocation(extension->location()), | 338 extension->manifest_version(), |
336 extension->manifest_version(), | 339 platform); |
337 platform); | |
338 if (!result.is_available()) | 340 if (!result.is_available()) |
339 return result; | 341 return result; |
340 } | 342 } |
341 | 343 |
342 if (!contexts_.empty() && contexts_.find(context) == contexts_.end()) | 344 if (!contexts_.empty() && contexts_.find(context) == contexts_.end()) |
343 return CreateAvailability(INVALID_CONTEXT, context); | 345 return CreateAvailability(INVALID_CONTEXT, context); |
344 | 346 |
345 if (!matches_.is_empty() && !matches_.MatchesURL(url)) | 347 if (!matches_.is_empty() && !matches_.MatchesURL(url)) |
346 return CreateAvailability(INVALID_URL, url); | 348 return CreateAvailability(INVALID_URL, url); |
347 | 349 |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
472 return false; | 474 return false; |
473 | 475 |
474 if (whitelist.find(extension_id) != whitelist.end() || | 476 if (whitelist.find(extension_id) != whitelist.end() || |
475 whitelist.find(HashExtensionId(extension_id)) != whitelist.end()) { | 477 whitelist.find(HashExtensionId(extension_id)) != whitelist.end()) { |
476 return true; | 478 return true; |
477 } | 479 } |
478 | 480 |
479 return false; | 481 return false; |
480 } | 482 } |
481 | 483 |
| 484 bool SimpleFeature::MatchesManifestLocation( |
| 485 Manifest::Location manifest_location) const { |
| 486 switch (location_) { |
| 487 case SimpleFeature::UNSPECIFIED_LOCATION: |
| 488 return true; |
| 489 case SimpleFeature::COMPONENT_LOCATION: |
| 490 return manifest_location == Manifest::COMPONENT || |
| 491 manifest_location == Manifest::EXTERNAL_COMPONENT; |
| 492 case SimpleFeature::POLICY_LOCATION: |
| 493 return manifest_location == Manifest::EXTERNAL_POLICY || |
| 494 manifest_location == Manifest::EXTERNAL_POLICY_DOWNLOAD; |
| 495 } |
| 496 NOTREACHED(); |
| 497 return false; |
| 498 } |
| 499 |
482 } // namespace extensions | 500 } // namespace extensions |
OLD | NEW |