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
7namespace extensions {
8
9ComplexFeature::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 IsInternal and no_parent is consistent across all features.
16  bool first_is_internal = features_[0]->IsInternal();
17  for (FeatureList::const_iterator it = features_.begin() + 1;
18       it != features_.end();
19       ++it) {
20    DCHECK(first_is_internal == (*it)->IsInternal())
21        << "Complex feature must have consistent values of "
22           "internal across all sub features.";
23    DCHECK(no_parent_ == (*it)->no_parent())
24        << "Complex feature must have consistent values of "
25           "no_parent across all sub features.";
26  }
27#endif
28}
29
30ComplexFeature::~ComplexFeature() {
31}
32
33Feature::Availability ComplexFeature::IsAvailableToManifest(
34    const std::string& extension_id,
35    Manifest::Type type,
36    Manifest::Location location,
37    int manifest_version,
38    Platform platform) const {
39  Feature::Availability first_availability =
40      features_[0]->IsAvailableToManifest(
41          extension_id, type, location, manifest_version, platform);
42  if (first_availability.is_available())
43    return first_availability;
44
45  for (FeatureList::const_iterator it = features_.begin() + 1;
46       it != features_.end(); ++it) {
47    Availability availability = (*it)->IsAvailableToManifest(
48        extension_id, type, location, manifest_version, platform);
49    if (availability.is_available())
50      return availability;
51  }
52  // If none of the SimpleFeatures are available, we return the availability
53  // info of the first SimpleFeature that was not available.
54  return first_availability;
55}
56
57Feature::Availability ComplexFeature::IsAvailableToContext(
58    const Extension* extension,
59    Context context,
60    const GURL& url,
61    Platform platform) const {
62  Feature::Availability first_availability =
63      features_[0]->IsAvailableToContext(extension, context, url, platform);
64  if (first_availability.is_available())
65    return first_availability;
66
67  for (FeatureList::const_iterator it = features_.begin() + 1;
68       it != features_.end(); ++it) {
69    Availability availability =
70        (*it)->IsAvailableToContext(extension, context, url, platform);
71    if (availability.is_available())
72      return availability;
73  }
74  // If none of the SimpleFeatures are available, we return the availability
75  // info of the first SimpleFeature that was not available.
76  return first_availability;
77}
78
79bool ComplexFeature::IsIdInBlacklist(const std::string& extension_id) const {
80  for (FeatureList::const_iterator it = features_.begin();
81       it != features_.end();
82       ++it) {
83    if ((*it)->IsIdInBlacklist(extension_id))
84      return true;
85  }
86  return false;
87}
88
89bool ComplexFeature::IsIdInWhitelist(const std::string& extension_id) const {
90  for (FeatureList::const_iterator it = features_.begin();
91       it != features_.end();
92       ++it) {
93    if ((*it)->IsIdInWhitelist(extension_id))
94      return true;
95  }
96  return false;
97}
98
99bool ComplexFeature::IsInternal() const {
100  // Constructor verifies that composed features are consistent, thus we can
101  // return just the first feature's value.
102  return features_[0]->IsInternal();
103}
104
105std::string ComplexFeature::GetAvailabilityMessage(AvailabilityResult result,
106                                                   Manifest::Type type,
107                                                   const GURL& url,
108                                                   Context context) const {
109  if (result == IS_AVAILABLE)
110    return std::string();
111
112  // TODO(justinlin): Form some kind of combined availabilities/messages from
113  // SimpleFeatures.
114  return features_[0]->GetAvailabilityMessage(result, type, url, context);
115}
116
117}  // namespace extensions
118