1c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/features/complex_feature.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions {
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ComplexFeature::ComplexFeature(scoped_ptr<FeatureList> features) {
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_GT(features->size(), 0UL);
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  features_.swap(*features);
12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  no_parent_ = features_[0]->no_parent();
13e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
14e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Verify IsInternal and no_parent is consistent across all features.
16e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  bool first_is_internal = features_[0]->IsInternal();
17e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  for (FeatureList::const_iterator it = features_.begin() + 1;
18e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       it != features_.end();
19e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       ++it) {
20e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(first_is_internal == (*it)->IsInternal())
21e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        << "Complex feature must have consistent values of "
22e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch           "internal across all sub features.";
23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    DCHECK(no_parent_ == (*it)->no_parent())
24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        << "Complex feature must have consistent values of "
25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           "no_parent across all sub features.";
26e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
27e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#endif
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ComplexFeature::~ComplexFeature() {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Feature::Availability ComplexFeature::IsAvailableToManifest(
340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const std::string& extension_id,
350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    Manifest::Type type,
360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    Manifest::Location location,
370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    int manifest_version,
380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    Platform platform) const {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Feature::Availability first_availability =
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      features_[0]->IsAvailableToManifest(
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          extension_id, type, location, manifest_version, platform);
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (first_availability.is_available())
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return first_availability;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (FeatureList::const_iterator it = features_.begin() + 1;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != features_.end(); ++it) {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Availability availability = (*it)->IsAvailableToManifest(
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        extension_id, type, location, manifest_version, platform);
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (availability.is_available())
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return availability;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If none of the SimpleFeatures are available, we return the availability
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // info of the first SimpleFeature that was not available.
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return first_availability;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Feature::Availability ComplexFeature::IsAvailableToContext(
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Extension* extension,
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Context context,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& url,
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Platform platform) const {
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Feature::Availability first_availability =
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      features_[0]->IsAvailableToContext(extension, context, url, platform);
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (first_availability.is_available())
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return first_availability;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (FeatureList::const_iterator it = features_.begin() + 1;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != features_.end(); ++it) {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Availability availability =
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (*it)->IsAvailableToContext(extension, context, url, platform);
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (availability.is_available())
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return availability;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If none of the SimpleFeatures are available, we return the availability
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // info of the first SimpleFeature that was not available.
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return first_availability;
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool ComplexFeature::IsIdInBlacklist(const std::string& extension_id) const {
80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (FeatureList::const_iterator it = features_.begin();
81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       it != features_.end();
82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       ++it) {
83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if ((*it)->IsIdInBlacklist(extension_id))
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return true;
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return false;
87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
89e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbool ComplexFeature::IsIdInWhitelist(const std::string& extension_id) const {
90e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  for (FeatureList::const_iterator it = features_.begin();
91e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       it != features_.end();
92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       ++it) {
93e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if ((*it)->IsIdInWhitelist(extension_id))
94e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      return true;
95e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
96e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return false;
97e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
98e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ComplexFeature::IsInternal() const {
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Constructor verifies that composed features are consistent, thus we can
101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // return just the first feature's value.
1028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return features_[0]->IsInternal();
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string ComplexFeature::GetAvailabilityMessage(AvailabilityResult result,
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                   Manifest::Type type,
1078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                                   const GURL& url,
1088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                                   Context context) const {
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (result == IS_AVAILABLE)
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return std::string();
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(justinlin): Form some kind of combined availabilities/messages from
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // SimpleFeatures.
1148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return features_[0]->GetAvailabilityMessage(result, type, url, context);
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace extensions
118