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 3 // found in the LICENSE file. 4 5 #include "extensions/common/features/complex_feature.h" 6 7 namespace extensions { 8 9 ComplexFeature::ComplexFeature(scoped_ptr<FeatureList> features) { 10 DCHECK_GT(features->size(), 0UL); 11 features_.swap(*features); 12 no_parent_ = features_[0]->no_parent(); 13 14 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) 15 // Verify GetContexts, IsInternal, & IsBlockedInServiceWorker are consistent 16 // across all features. 17 std::set<Feature::Context>* first_contexts = features_[0]->GetContexts(); 18 bool first_is_internal = features_[0]->IsInternal(); 19 bool first_blocked_in_service_worker = 20 features_[0]->IsBlockedInServiceWorker(); 21 for (FeatureList::const_iterator it = features_.begin() + 1; 22 it != features_.end(); 23 ++it) { 24 DCHECK(*first_contexts == *(*it)->GetContexts()) 25 << "Complex feature must have consistent values of " 26 "contexts across all sub features."; 27 DCHECK(first_is_internal == (*it)->IsInternal()) 28 << "Complex feature must have consistent values of " 29 "internal across all sub features."; 30 DCHECK(first_blocked_in_service_worker == (*it)->IsBlockedInServiceWorker()) 31 << "Complex feature must have consistent values of " 32 "blocked_in_service_worker across all sub features."; 33 DCHECK(no_parent_ == (*it)->no_parent()) 34 << "Complex feature must have consistent values of " 35 "no_parent across all sub features."; 36 } 37 #endif 38 } 39 40 ComplexFeature::~ComplexFeature() { 41 } 42 43 Feature::Availability ComplexFeature::IsAvailableToManifest( 44 const std::string& extension_id, 45 Manifest::Type type, 46 Manifest::Location location, 47 int manifest_version, 48 Platform platform) const { 49 Feature::Availability first_availability = 50 features_[0]->IsAvailableToManifest( 51 extension_id, type, location, manifest_version, platform); 52 if (first_availability.is_available()) 53 return first_availability; 54 55 for (FeatureList::const_iterator it = features_.begin() + 1; 56 it != features_.end(); ++it) { 57 Availability availability = (*it)->IsAvailableToManifest( 58 extension_id, type, location, manifest_version, platform); 59 if (availability.is_available()) 60 return availability; 61 } 62 // If none of the SimpleFeatures are available, we return the availability 63 // info of the first SimpleFeature that was not available. 64 return first_availability; 65 } 66 67 Feature::Availability ComplexFeature::IsAvailableToContext( 68 const Extension* extension, 69 Context context, 70 const GURL& url, 71 Platform platform) const { 72 Feature::Availability first_availability = 73 features_[0]->IsAvailableToContext(extension, context, url, platform); 74 if (first_availability.is_available()) 75 return first_availability; 76 77 for (FeatureList::const_iterator it = features_.begin() + 1; 78 it != features_.end(); ++it) { 79 Availability availability = 80 (*it)->IsAvailableToContext(extension, context, url, platform); 81 if (availability.is_available()) 82 return availability; 83 } 84 // If none of the SimpleFeatures are available, we return the availability 85 // info of the first SimpleFeature that was not available. 86 return first_availability; 87 } 88 89 bool ComplexFeature::IsIdInBlacklist(const std::string& extension_id) const { 90 for (FeatureList::const_iterator it = features_.begin(); 91 it != features_.end(); 92 ++it) { 93 if ((*it)->IsIdInBlacklist(extension_id)) 94 return true; 95 } 96 return false; 97 } 98 99 bool ComplexFeature::IsIdInWhitelist(const std::string& extension_id) const { 100 for (FeatureList::const_iterator it = features_.begin(); 101 it != features_.end(); 102 ++it) { 103 if ((*it)->IsIdInWhitelist(extension_id)) 104 return true; 105 } 106 return false; 107 } 108 109 bool ComplexFeature::IsBlockedInServiceWorker() const { 110 // Constructor verifies that composed features are consistent, thus we can 111 // return just the first feature's value. 112 return features_[0]->IsBlockedInServiceWorker(); 113 } 114 115 std::set<Feature::Context>* ComplexFeature::GetContexts() { 116 // TODO(justinlin): Current use cases for ComplexFeatures are simple (e.g. 117 // allow API in dev channel for everyone but stable channel for a whitelist), 118 // but if they get more complicated, we need to return some meaningful context 119 // set. Either that or remove this method from the Feature interface. 120 return features_[0]->GetContexts(); 121 } 122 123 bool ComplexFeature::IsInternal() const { 124 // TODO(justinlin): Same as the above TODO. 125 return features_[0]->IsInternal(); 126 } 127 128 std::string ComplexFeature::GetAvailabilityMessage(AvailabilityResult result, 129 Manifest::Type type, 130 const GURL& url, 131 Context context) const { 132 if (result == IS_AVAILABLE) 133 return std::string(); 134 135 // TODO(justinlin): Form some kind of combined availabilities/messages from 136 // SimpleFeatures. 137 return features_[0]->GetAvailabilityMessage(result, type, url, context); 138 } 139 140 } // namespace extensions 141