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" |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 DCHECK(id_hash.length() == base::kSHA1Length); | 220 DCHECK(id_hash.length() == base::kSHA1Length); |
221 return base::HexEncode(id_hash.c_str(), id_hash.length()); | 221 return base::HexEncode(id_hash.c_str(), id_hash.length()); |
222 } | 222 } |
223 | 223 |
224 } // namespace | 224 } // namespace |
225 | 225 |
226 SimpleFeature::SimpleFeature() | 226 SimpleFeature::SimpleFeature() |
227 : location_(UNSPECIFIED_LOCATION), | 227 : location_(UNSPECIFIED_LOCATION), |
228 min_manifest_version_(0), | 228 min_manifest_version_(0), |
229 max_manifest_version_(0), | 229 max_manifest_version_(0), |
230 has_parent_(false) {} | 230 has_parent_(false), |
| 231 component_extensions_auto_granted_(true) {} |
231 | 232 |
232 SimpleFeature::~SimpleFeature() {} | 233 SimpleFeature::~SimpleFeature() {} |
233 | 234 |
234 void SimpleFeature::AddFilter(scoped_ptr<SimpleFeatureFilter> filter) { | 235 void SimpleFeature::AddFilter(scoped_ptr<SimpleFeatureFilter> filter) { |
235 filters_.push_back(make_linked_ptr(filter.release())); | 236 filters_.push_back(make_linked_ptr(filter.release())); |
236 } | 237 } |
237 | 238 |
238 std::string SimpleFeature::Parse(const base::DictionaryValue* value) { | 239 std::string SimpleFeature::Parse(const base::DictionaryValue* value) { |
239 ParseURLPatterns(value, "matches", &matches_); | 240 ParseURLPatterns(value, "matches", &matches_); |
| 241 ParseSet(value, "blacklist", &blacklist_); |
240 ParseSet(value, "whitelist", &whitelist_); | 242 ParseSet(value, "whitelist", &whitelist_); |
241 ParseSet(value, "dependencies", &dependencies_); | 243 ParseSet(value, "dependencies", &dependencies_); |
242 ParseEnumSet<Manifest::Type>(value, "extension_types", &extension_types_, | 244 ParseEnumSet<Manifest::Type>(value, "extension_types", &extension_types_, |
243 g_mappings.Get().extension_types); | 245 g_mappings.Get().extension_types); |
244 ParseEnumSet<Context>(value, "contexts", &contexts_, | 246 ParseEnumSet<Context>(value, "contexts", &contexts_, |
245 g_mappings.Get().contexts); | 247 g_mappings.Get().contexts); |
246 ParseEnum<Location>(value, "location", &location_, | 248 ParseEnum<Location>(value, "location", &location_, |
247 g_mappings.Get().locations); | 249 g_mappings.Get().locations); |
248 ParseEnumSet<Platform>(value, "platforms", &platforms_, | 250 ParseEnumSet<Platform>(value, "platforms", &platforms_, |
249 g_mappings.Get().platforms); | 251 g_mappings.Get().platforms); |
250 value->GetInteger("min_manifest_version", &min_manifest_version_); | 252 value->GetInteger("min_manifest_version", &min_manifest_version_); |
251 value->GetInteger("max_manifest_version", &max_manifest_version_); | 253 value->GetInteger("max_manifest_version", &max_manifest_version_); |
252 | 254 |
253 no_parent_ = false; | 255 no_parent_ = false; |
254 value->GetBoolean("noparent", &no_parent_); | 256 value->GetBoolean("noparent", &no_parent_); |
255 | 257 |
| 258 component_extensions_auto_granted_ = true; |
| 259 value->GetBoolean("component_extensions_auto_granted", |
| 260 &component_extensions_auto_granted_); |
| 261 |
256 if (matches_.is_empty() && contexts_.count(WEB_PAGE_CONTEXT) != 0) { | 262 if (matches_.is_empty() && contexts_.count(WEB_PAGE_CONTEXT) != 0) { |
257 return name() + ": Allowing web_page contexts requires supplying a value " + | 263 return name() + ": Allowing web_page contexts requires supplying a value " + |
258 "for matches."; | 264 "for matches."; |
259 } | 265 } |
260 | 266 |
261 for (FilterList::iterator filter_iter = filters_.begin(); | 267 for (FilterList::iterator filter_iter = filters_.begin(); |
262 filter_iter != filters_.end(); | 268 filter_iter != filters_.end(); |
263 ++filter_iter) { | 269 ++filter_iter) { |
264 std::string result = (*filter_iter)->Parse(value); | 270 std::string result = (*filter_iter)->Parse(value); |
265 if (!result.empty()) { | 271 if (!result.empty()) { |
(...skipping 14 matching lines...) Expand all Loading... |
280 // to component extensions. | 286 // to component extensions. |
281 // HACK(kalman): user script -> extension. Solve this in a more generic way | 287 // HACK(kalman): user script -> extension. Solve this in a more generic way |
282 // when we compile feature files. | 288 // when we compile feature files. |
283 Manifest::Type type_to_check = (type == Manifest::TYPE_USER_SCRIPT) ? | 289 Manifest::Type type_to_check = (type == Manifest::TYPE_USER_SCRIPT) ? |
284 Manifest::TYPE_EXTENSION : type; | 290 Manifest::TYPE_EXTENSION : type; |
285 if (!extension_types_.empty() && | 291 if (!extension_types_.empty() && |
286 extension_types_.find(type_to_check) == extension_types_.end()) { | 292 extension_types_.find(type_to_check) == extension_types_.end()) { |
287 return CreateAvailability(INVALID_TYPE, type); | 293 return CreateAvailability(INVALID_TYPE, type); |
288 } | 294 } |
289 | 295 |
| 296 if (IsIdInBlacklist(extension_id)) |
| 297 return CreateAvailability(FOUND_IN_BLACKLIST, type); |
| 298 |
| 299 // TODO(benwells): don't grant all component extensions. |
| 300 // See http://crbug.com/370375 for more details. |
290 // Component extensions can access any feature. | 301 // Component extensions can access any feature. |
291 // TODO(kalman/asargent): Should this match EXTERNAL_COMPONENT too? | 302 // NOTE: Deliberately does not match EXTERNAL_COMPONENT. |
292 if (location == Manifest::COMPONENT) | 303 if (component_extensions_auto_granted_ && location == Manifest::COMPONENT) |
293 return CreateAvailability(IS_AVAILABLE, type); | 304 return CreateAvailability(IS_AVAILABLE, type); |
294 | 305 |
295 if (!whitelist_.empty()) { | 306 if (!whitelist_.empty()) { |
296 if (!IsIdInWhitelist(extension_id)) { | 307 if (!IsIdInWhitelist(extension_id)) { |
297 // TODO(aa): This is gross. There should be a better way to test the | 308 // TODO(aa): This is gross. There should be a better way to test the |
298 // whitelist. | 309 // whitelist. |
299 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 310 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
300 if (!command_line->HasSwitch(switches::kWhitelistedExtensionID)) | 311 if (!command_line->HasSwitch(switches::kWhitelistedExtensionID)) |
301 return CreateAvailability(NOT_FOUND_IN_WHITELIST, type); | 312 return CreateAvailability(NOT_FOUND_IN_WHITELIST, type); |
302 | 313 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 | 379 |
369 std::string SimpleFeature::GetAvailabilityMessage( | 380 std::string SimpleFeature::GetAvailabilityMessage( |
370 AvailabilityResult result, | 381 AvailabilityResult result, |
371 Manifest::Type type, | 382 Manifest::Type type, |
372 const GURL& url, | 383 const GURL& url, |
373 Context context) const { | 384 Context context) const { |
374 switch (result) { | 385 switch (result) { |
375 case IS_AVAILABLE: | 386 case IS_AVAILABLE: |
376 return std::string(); | 387 return std::string(); |
377 case NOT_FOUND_IN_WHITELIST: | 388 case NOT_FOUND_IN_WHITELIST: |
| 389 case FOUND_IN_BLACKLIST: |
378 return base::StringPrintf( | 390 return base::StringPrintf( |
379 "'%s' is not allowed for specified extension ID.", | 391 "'%s' is not allowed for specified extension ID.", |
380 name().c_str()); | 392 name().c_str()); |
381 case INVALID_URL: | 393 case INVALID_URL: |
382 return base::StringPrintf("'%s' is not allowed on %s.", | 394 return base::StringPrintf("'%s' is not allowed on %s.", |
383 name().c_str(), url.spec().c_str()); | 395 name().c_str(), url.spec().c_str()); |
384 case INVALID_TYPE: | 396 case INVALID_TYPE: |
385 return base::StringPrintf( | 397 return base::StringPrintf( |
386 "'%s' is only allowed for %s, but this is a %s.", | 398 "'%s' is only allowed for %s, but this is a %s.", |
387 name().c_str(), | 399 name().c_str(), |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 std::set<Feature::Context>* SimpleFeature::GetContexts() { | 471 std::set<Feature::Context>* SimpleFeature::GetContexts() { |
460 return &contexts_; | 472 return &contexts_; |
461 } | 473 } |
462 | 474 |
463 bool SimpleFeature::IsInternal() const { | 475 bool SimpleFeature::IsInternal() const { |
464 return false; | 476 return false; |
465 } | 477 } |
466 | 478 |
467 bool SimpleFeature::IsBlockedInServiceWorker() const { return false; } | 479 bool SimpleFeature::IsBlockedInServiceWorker() const { return false; } |
468 | 480 |
| 481 bool SimpleFeature::IsIdInBlacklist(const std::string& extension_id) const { |
| 482 return IsIdInList(extension_id, blacklist_); |
| 483 } |
| 484 |
469 bool SimpleFeature::IsIdInWhitelist(const std::string& extension_id) const { | 485 bool SimpleFeature::IsIdInWhitelist(const std::string& extension_id) const { |
470 return IsIdInWhitelist(extension_id, whitelist_); | 486 return IsIdInList(extension_id, whitelist_); |
471 } | 487 } |
472 | 488 |
473 // static | 489 // static |
474 bool SimpleFeature::IsIdInWhitelist(const std::string& extension_id, | 490 bool SimpleFeature::IsIdInList(const std::string& extension_id, |
475 const std::set<std::string>& whitelist) { | 491 const std::set<std::string>& list) { |
476 // Belt-and-suspenders philosophy here. We should be pretty confident by this | 492 // Belt-and-suspenders philosophy here. We should be pretty confident by this |
477 // point that we've validated the extension ID format, but in case something | 493 // point that we've validated the extension ID format, but in case something |
478 // slips through, we avoid a class of attack where creative ID manipulation | 494 // slips through, we avoid a class of attack where creative ID manipulation |
479 // leads to hash collisions. | 495 // leads to hash collisions. |
480 if (extension_id.length() != 32) // 128 bits / 4 = 32 mpdecimal characters | 496 if (extension_id.length() != 32) // 128 bits / 4 = 32 mpdecimal characters |
481 return false; | 497 return false; |
482 | 498 |
483 if (whitelist.find(extension_id) != whitelist.end() || | 499 if (list.find(extension_id) != list.end() || |
484 whitelist.find(HashExtensionId(extension_id)) != whitelist.end()) { | 500 list.find(HashExtensionId(extension_id)) != list.end()) { |
485 return true; | 501 return true; |
486 } | 502 } |
487 | 503 |
488 return false; | 504 return false; |
489 } | 505 } |
490 | 506 |
491 bool SimpleFeature::MatchesManifestLocation( | 507 bool SimpleFeature::MatchesManifestLocation( |
492 Manifest::Location manifest_location) const { | 508 Manifest::Location manifest_location) const { |
493 switch (location_) { | 509 switch (location_) { |
494 case SimpleFeature::UNSPECIFIED_LOCATION: | 510 case SimpleFeature::UNSPECIFIED_LOCATION: |
495 return true; | 511 return true; |
496 case SimpleFeature::COMPONENT_LOCATION: | 512 case SimpleFeature::COMPONENT_LOCATION: |
497 // TODO(kalman/asargent): Should this include EXTERNAL_COMPONENT too? | 513 // TODO(kalman/asargent): Should this include EXTERNAL_COMPONENT too? |
498 return manifest_location == Manifest::COMPONENT; | 514 return manifest_location == Manifest::COMPONENT; |
499 case SimpleFeature::POLICY_LOCATION: | 515 case SimpleFeature::POLICY_LOCATION: |
500 return manifest_location == Manifest::EXTERNAL_POLICY || | 516 return manifest_location == Manifest::EXTERNAL_POLICY || |
501 manifest_location == Manifest::EXTERNAL_POLICY_DOWNLOAD; | 517 manifest_location == Manifest::EXTERNAL_POLICY_DOWNLOAD; |
502 } | 518 } |
503 NOTREACHED(); | 519 NOTREACHED(); |
504 return false; | 520 return false; |
505 } | 521 } |
506 | 522 |
507 } // namespace extensions | 523 } // namespace extensions |
OLD | NEW |