Home | History | Annotate | Download | only in features
      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