13551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/error_utils.h"
143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/features/feature.h"
15ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "extensions/common/features/feature_provider.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/install_warning.h"
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest_constants.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace keys = manifest_keys;
223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Rank extension locations in a way that allows
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Manifest::GetHigherPriorityLocation() to compare locations.
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// An extension installed from two locations will have the location
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// with the higher rank, as returned by this function. The actual
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// integer values may change, and should never be persisted.
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int GetLocationRank(Manifest::Location location) {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kInvalidRank = -1;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int rank = kInvalidRank;  // Will CHECK that rank is not kInvalidRank.
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (location) {
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Component extensions can not be overriden by any other type.
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case Manifest::COMPONENT:
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      rank = 9;
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      break;
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    case Manifest::EXTERNAL_COMPONENT:
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      rank = 8;
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Policy controlled extensions may not be overridden by any type
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // that is not part of chrome.
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    case Manifest::EXTERNAL_POLICY:
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      rank = 7;
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      break;
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case Manifest::EXTERNAL_POLICY_DOWNLOAD:
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rank = 6;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // A developer-loaded extension should override any installed type
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // that a user can disable. Anything specified on the command-line should
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // override one loaded via the extensions UI.
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case Manifest::COMMAND_LINE:
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rank = 5;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case Manifest::UNPACKED:
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rank = 4;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The relative priority of various external sources is not important,
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // but having some order ensures deterministic behavior.
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case Manifest::EXTERNAL_REGISTRY:
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rank = 3;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case Manifest::EXTERNAL_PREF:
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rank = 2;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case Manifest::EXTERNAL_PREF_DOWNLOAD:
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rank = 1;
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // User installed extensions are overridden by any external type.
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case Manifest::INTERNAL:
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rank = 0;
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED() << "Need to add new extension location " << location;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(rank != kInvalidRank);
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return rank;
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Manifest::Location Manifest::GetHigherPriorityLocation(
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Location loc1, Location loc2) {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (loc1 == loc2)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return loc1;
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int loc1_rank = GetLocationRank(loc1);
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int loc2_rank = GetLocationRank(loc2);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If two different locations have the same rank, then we can not
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // deterministicly choose a location.
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(loc1_rank != loc2_rank);
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Highest rank has highest priority.
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (loc1_rank > loc2_rank ? loc1 : loc2 );
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Manifest::Manifest(Location location, scoped_ptr<base::DictionaryValue> value)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : location_(location),
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value_(value.Pass()),
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      type_(TYPE_UNKNOWN) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (value_->HasKey(keys::kTheme)) {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    type_ = TYPE_THEME;
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (value_->HasKey(keys::kExport)) {
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    type_ = TYPE_SHARED_MODULE;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (value_->HasKey(keys::kApp)) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (value_->Get(keys::kWebURLs, NULL) ||
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value_->Get(keys::kLaunchWebURL, NULL)) {
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      type_ = TYPE_HOSTED_APP;
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    } else if (value_->Get(keys::kPlatformAppBackground, NULL) ||
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)               value_->Get(keys::kPlatformAppServiceWorker, NULL)) {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      type_ = TYPE_PLATFORM_APP;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      type_ = TYPE_LEGACY_PACKAGED_APP;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    type_ = TYPE_EXTENSION;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK_NE(type_, TYPE_UNKNOWN);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Manifest::~Manifest() {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Manifest::ValidateManifest(
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* error,
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::vector<InstallWarning>* warnings) const {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *error = "";
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check every feature to see if its in the manifest. Note that this means
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we will ignore keys that are not features; we do this for forward
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // compatibility.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(aa): Consider having an error here in the case of strict error
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // checking to let developers know when they screw up.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const FeatureProvider* manifest_feature_provider =
1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      FeatureProvider::GetManifestFeatures();
1517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const std::vector<std::string>& feature_names =
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      manifest_feature_provider->GetAllFeatureNames();
1537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for (std::vector<std::string>::const_iterator feature_name =
1547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)           feature_names.begin();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       feature_name != feature_names.end(); ++feature_name) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Use Get instead of HasKey because the former uses path expansion.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!value_->Get(*feature_name, NULL))
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    Feature* feature = manifest_feature_provider->GetFeature(*feature_name);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Feature::Availability result = feature->IsAvailableToManifest(
1620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        extension_id_, type_, location_, GetManifestVersion());
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!result.is_available())
1643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      warnings->push_back(InstallWarning(result.message(), *feature_name));
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Also generate warnings for keys that are not features.
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (base::DictionaryValue::Iterator it(*value_); !it.IsAtEnd();
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it.Advance()) {
1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (!manifest_feature_provider->GetFeature(it.key())) {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      warnings->push_back(InstallWarning(
17258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          ErrorUtils::FormatErrorMessage(
17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)              manifest_errors::kUnrecognizedManifestKey, it.key()),
1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          it.key()));
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Manifest::HasKey(const std::string& key) const {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CanAccessKey(key) && value_->HasKey(key);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Manifest::HasPath(const std::string& path) const {
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Value* ignored = NULL;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CanAccessPath(path) && value_->Get(path, &ignored);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Manifest::Get(
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& path, const base::Value** out_value) const {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CanAccessPath(path) && value_->Get(path, out_value);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Manifest::GetBoolean(
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& path, bool* out_value) const {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CanAccessPath(path) && value_->GetBoolean(path, out_value);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Manifest::GetInteger(
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& path, int* out_value) const {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CanAccessPath(path) && value_->GetInteger(path, out_value);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Manifest::GetString(
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& path, std::string* out_value) const {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CanAccessPath(path) && value_->GetString(path, out_value);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Manifest::GetString(
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& path, base::string16* out_value) const {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CanAccessPath(path) && value_->GetString(path, out_value);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Manifest::GetDictionary(
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& path, const base::DictionaryValue** out_value) const {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CanAccessPath(path) && value_->GetDictionary(path, out_value);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Manifest::GetList(
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& path, const base::ListValue** out_value) const {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CanAccessPath(path) && value_->GetList(path, out_value);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Manifest* Manifest::DeepCopy() const {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Manifest* manifest = new Manifest(
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      location_, scoped_ptr<base::DictionaryValue>(value_->DeepCopy()));
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manifest->set_extension_id(extension_id_);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return manifest;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Manifest::Equals(const Manifest* other) const {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return other && value_->Equals(other->value());
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int Manifest::GetManifestVersion() const {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Platform apps were launched after manifest version 2 was the preferred
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // version, so they default to that.
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int manifest_version = type_ == TYPE_PLATFORM_APP ? 2 : 1;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value_->GetInteger(keys::kManifestVersion, &manifest_version);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return manifest_version;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Manifest::CanAccessPath(const std::string& path) const {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> components;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SplitString(path, '.', &components);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string key;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < components.size(); ++i) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    key += components[i];
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!CanAccessKey(key))
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    key += '.';
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Manifest::CanAccessKey(const std::string& key) const {
2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Feature* feature = FeatureProvider::GetManifestFeatures()->GetFeature(key);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!feature)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return feature->IsAvailableToManifest(
2620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                      extension_id_, type_, location_, GetManifestVersion())
2630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      .is_available();
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
267