Chromium Code Reviews| Index: chrome/common/extensions/manifest_value.cc |
| diff --git a/chrome/common/extensions/manifest_value.cc b/chrome/common/extensions/manifest_value.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..a3a24ce8f066d32761b344510f65f977fd562f8b |
| --- /dev/null |
| +++ b/chrome/common/extensions/manifest_value.cc |
| @@ -0,0 +1,203 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
|
Aaron Boodman
2011/11/23 01:45:25
Shame to pull out this nice, encapsulated class an
jstritar
2011/11/28 23:09:56
Done.
|
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/common/extensions/manifest_value.h" |
| + |
| +#include "base/basictypes.h" |
| +#include "base/logging.h" |
| +#include "base/string_split.h" |
| +#include "base/values.h" |
| +#include "chrome/common/extensions/extension_constants.h" |
| +#include "chrome/common/extensions/extension_error_utils.h" |
| + |
| +namespace errors = extension_manifest_errors; |
| +namespace keys = extension_manifest_keys; |
| + |
| +struct ManifestValue::FeatureRestriction { |
| + const char* key; |
| + const int restriction; |
| +}; |
| + |
| +const ManifestValue::FeatureRestriction |
| + ManifestValue::kFeatureRestrictions[] = { |
| + // Base keys that all manifests can specify. |
| + { keys::kName, kTypeAll }, |
| + { keys::kVersion, kTypeAll }, |
| + { keys::kManifestVersion, kTypeAll }, |
| + { keys::kDescription, kTypeAll }, |
| + { keys::kIcons, kTypeAll }, |
| + { keys::kCurrentLocale, kTypeAll }, |
| + { keys::kDefaultLocale, kTypeAll }, |
| + { keys::kSignature, kTypeAll }, |
| + { keys::kUpdateURL, kTypeAll }, |
| + { keys::kPublicKey, kTypeAll }, |
| + |
| + // Type specific. |
| + { keys::kApp, kTypeAllApps }, |
| + { keys::kTheme, kTypeTheme }, |
| + { keys::kPlatformApp, kTypePlatformApp }, |
| + |
| + // Extensions only. |
| + { keys::kBrowserAction, kTypeExtension }, |
| + { keys::kPageAction, kTypeExtension }, |
| + { keys::kPageActions, kTypeExtension }, |
| + { keys::kChromeURLOverrides, kTypeExtension }, |
| + |
| + // Hosted and packaged apps. |
| + { keys::kPermissions, kTypeAllButThemes }, |
| + { keys::kOptionalPermissions, kTypeAllButThemes }, |
| + { keys::kOptionsPage, kTypeAllButThemes }, |
| + { keys::kBackground, kTypeAllButThemes }, |
| + { keys::kOfflineEnabled, kTypeAllButThemes }, |
| + { keys::kMinimumChromeVersion, kTypeAllButThemes }, |
| + { keys::kRequirements, kTypeAllButThemes }, |
| + { keys::kConvertedFromUserScript, kTypeAllButThemes }, |
| + |
| + // Extensions and packaged apps. |
| + { keys::kContentScripts, kTypeExtension | kTypePackagedApp }, |
| + { keys::kOmnibox, kTypeExtension | kTypePackagedApp }, |
| + { keys::kDevToolsPage, kTypeExtension | kTypePackagedApp }, |
| + { keys::kSidebar, kTypeExtension | kTypePackagedApp }, |
| + { keys::kHomepageURL, kTypeExtension | kTypePackagedApp }, |
| + |
| + // Extensions, packaged apps and platform apps. |
| + { keys::kContentSecurityPolicy, kTypeAllApps | kTypeExtension }, |
| + { keys::kFileBrowserHandlers, kTypeAllApps | kTypeExtension }, |
| + { keys::kIncognito, kTypeAllApps | kTypeExtension }, |
| + { keys::kNaClModules, kTypeAllApps | kTypeExtension }, |
| + { keys::kPlugins, kTypeAllApps | kTypeExtension }, |
| + { keys::kInputComponents, kTypeAllApps | kTypeExtension }, |
| + { keys::kTtsEngine, kTypeAllApps | kTypeExtension }, |
| + { keys::kIntents, kTypeAllApps | kTypeExtension }, |
| +}; |
| + |
| +ManifestValue::ManifestValue(DictionaryValue* value) |
| + : value_(value) { |
| + // Read the feature restriction data. |
| + for (size_t i = 0; i < arraysize(kFeatureRestrictions); ++i) { |
| + restrictions_[kFeatureRestrictions[i].key] = |
|
Aaron Boodman
2011/11/23 01:45:25
Sucks to have a separate copy of this for every in
jstritar
2011/11/28 23:09:56
Done.. LazyInstance is sweet!
|
| + kFeatureRestrictions[i].restriction; |
| + } |
| + |
| + // Determine what type of extension the manifest represents. |
| + if (IsTheme()) |
|
Aaron Boodman
2011/11/23 01:45:25
Consider omitting the type_ member and instead hav
jstritar
2011/11/28 23:09:56
Done.
|
| + type_ = kTypeTheme; |
| + else if (IsPlatformApp()) |
| + type_ = kTypePlatformApp; |
| + else if (IsHostedApp()) |
| + type_ = kTypeHostedApp; |
| + else if (IsPackagedApp()) |
| + type_ = kTypePackagedApp; |
| + else |
| + type_ = kTypeExtension; |
| +} |
| + |
| +ManifestValue::~ManifestValue() {} |
| + |
| +bool ManifestValue::ValidateManifest(std::string* error) const { |
| + for (DictionaryValue::key_iterator key = value_->begin_keys(); |
| + key != value_->end_keys(); ++key) { |
| + // When validating the extension manifests, we ignore keys that are not |
| + // recognized for compatibility. |
|
Aaron Boodman
2011/11/23 01:45:25
For clarity: s/for compatibility/for forward compa
jstritar
2011/11/28 23:09:56
Done.
|
| + if (!IsKnownKey(*key)) |
|
Aaron Boodman
2011/11/23 01:45:25
Add:
TODO(aa): Consider having an error here in t
jstritar
2011/11/28 23:09:56
Done.
|
| + continue; |
| + |
| + if (!CanAccessKey(*key)) { |
|
Aaron Boodman
2011/11/23 01:45:25
I think that there will probably be legacy data he
jstritar
2011/11/28 23:09:56
I think we're okay here because we parsed hosted a
|
| + *error = ExtensionErrorUtils::FormatErrorMessage( |
| + errors::kFeatureNotAllowed, *key); |
| + return false; |
| + } |
| + } |
| + |
| + return true; |
| +} |
| + |
| +bool ManifestValue::HasKey(const std::string& key) const { |
| + // Return false instead of CHECKing, since we're just testing for existence. |
| + return CanAccessKey(key) && value_->HasKey(key); |
| +} |
| + |
| +bool ManifestValue::Get( |
| + const std::string& path, Value** out_value) const { |
| + CHECK(CanAccessPath(path)) << path; |
| + return value_->Get(path, out_value); |
| +} |
| + |
| +bool ManifestValue::GetBoolean( |
| + const std::string& path, bool* out_value) const { |
| + CHECK(CanAccessPath(path)) << path; |
| + return value_->GetBoolean(path, out_value); |
| +} |
| + |
| +bool ManifestValue::GetInteger( |
| + const std::string& path, int* out_value) const { |
| + CHECK(CanAccessPath(path)) << path; |
| + return value_->GetInteger(path, out_value); |
| +} |
| + |
| +bool ManifestValue::GetString( |
| + const std::string& path, std::string* out_value) const { |
| + CHECK(CanAccessPath(path)) << path; |
| + return value_->GetString(path, out_value); |
| +} |
| + |
| +bool ManifestValue::GetString( |
| + const std::string& path, string16* out_value) const { |
| + CHECK(CanAccessPath(path)) << path; |
| + return value_->GetString(path, out_value); |
| +} |
| + |
| +bool ManifestValue::GetDictionary( |
| + const std::string& path, DictionaryValue** out_value) const { |
| + CHECK(CanAccessPath(path)) << path; |
| + return value_->GetDictionary(path, out_value); |
| +} |
| + |
| +bool ManifestValue::GetList( |
| + const std::string& path, ListValue** out_value) const { |
| + CHECK(CanAccessPath(path)) << path; |
| + return value_->GetList(path, out_value); |
| +} |
| + |
| +ManifestValue* ManifestValue::DeepCopy() const { |
| + return new ManifestValue(value_->DeepCopy()); |
| +} |
| + |
| +bool ManifestValue::Equals(const ManifestValue* other) const { |
| + return other && value_->Equals(other->value()); |
| +} |
| + |
| +bool ManifestValue::IsTheme() const { |
| + DictionaryValue* dict_value = NULL; |
| + return value_->HasKey(keys::kTheme) && |
| + value_->GetDictionary(keys::kTheme, &dict_value); |
| +} |
| + |
| +bool ManifestValue::IsPlatformApp() const { |
| + return value_->HasKey(keys::kPlatformApp); |
| +} |
| + |
| +bool ManifestValue::IsPackagedApp() const { |
| + return value_->HasKey(keys::kApp) && !value_->HasKey(keys::kWebURLs); |
| +} |
| + |
| +bool ManifestValue::IsHostedApp() const { |
| + return value_->HasKey(keys::kApp) && value_->HasKey(keys::kWebURLs); |
| +} |
| + |
| +bool ManifestValue::IsKnownKey(const std::string& key) const { |
| + RestrictionMap::const_iterator i = restrictions_.find(key); |
| + return i != restrictions_.end(); |
| +} |
| + |
| +bool ManifestValue::CanAccessKey(const std::string& key) const { |
| + RestrictionMap::const_iterator i = restrictions_.find(key); |
| + return (i != restrictions_.end() && (type_ & i->second) != 0); |
| +} |
| + |
| +bool ManifestValue::CanAccessPath(const std::string& path) const { |
| + std::vector<std::string> components; |
| + base::SplitString(path, '.', &components); |
| + return CanAccessKey(components[0]); |
| +} |