Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // 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.
| |
| 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 "chrome/common/extensions/manifest_value.h" | |
| 6 | |
| 7 #include "base/basictypes.h" | |
| 8 #include "base/logging.h" | |
| 9 #include "base/string_split.h" | |
| 10 #include "base/values.h" | |
| 11 #include "chrome/common/extensions/extension_constants.h" | |
| 12 #include "chrome/common/extensions/extension_error_utils.h" | |
| 13 | |
| 14 namespace errors = extension_manifest_errors; | |
| 15 namespace keys = extension_manifest_keys; | |
| 16 | |
| 17 struct ManifestValue::FeatureRestriction { | |
| 18 const char* key; | |
| 19 const int restriction; | |
| 20 }; | |
| 21 | |
| 22 const ManifestValue::FeatureRestriction | |
| 23 ManifestValue::kFeatureRestrictions[] = { | |
| 24 // Base keys that all manifests can specify. | |
| 25 { keys::kName, kTypeAll }, | |
| 26 { keys::kVersion, kTypeAll }, | |
| 27 { keys::kManifestVersion, kTypeAll }, | |
| 28 { keys::kDescription, kTypeAll }, | |
| 29 { keys::kIcons, kTypeAll }, | |
| 30 { keys::kCurrentLocale, kTypeAll }, | |
| 31 { keys::kDefaultLocale, kTypeAll }, | |
| 32 { keys::kSignature, kTypeAll }, | |
| 33 { keys::kUpdateURL, kTypeAll }, | |
| 34 { keys::kPublicKey, kTypeAll }, | |
| 35 | |
| 36 // Type specific. | |
| 37 { keys::kApp, kTypeAllApps }, | |
| 38 { keys::kTheme, kTypeTheme }, | |
| 39 { keys::kPlatformApp, kTypePlatformApp }, | |
| 40 | |
| 41 // Extensions only. | |
| 42 { keys::kBrowserAction, kTypeExtension }, | |
| 43 { keys::kPageAction, kTypeExtension }, | |
| 44 { keys::kPageActions, kTypeExtension }, | |
| 45 { keys::kChromeURLOverrides, kTypeExtension }, | |
| 46 | |
| 47 // Hosted and packaged apps. | |
| 48 { keys::kPermissions, kTypeAllButThemes }, | |
| 49 { keys::kOptionalPermissions, kTypeAllButThemes }, | |
| 50 { keys::kOptionsPage, kTypeAllButThemes }, | |
| 51 { keys::kBackground, kTypeAllButThemes }, | |
| 52 { keys::kOfflineEnabled, kTypeAllButThemes }, | |
| 53 { keys::kMinimumChromeVersion, kTypeAllButThemes }, | |
| 54 { keys::kRequirements, kTypeAllButThemes }, | |
| 55 { keys::kConvertedFromUserScript, kTypeAllButThemes }, | |
| 56 | |
| 57 // Extensions and packaged apps. | |
| 58 { keys::kContentScripts, kTypeExtension | kTypePackagedApp }, | |
| 59 { keys::kOmnibox, kTypeExtension | kTypePackagedApp }, | |
| 60 { keys::kDevToolsPage, kTypeExtension | kTypePackagedApp }, | |
| 61 { keys::kSidebar, kTypeExtension | kTypePackagedApp }, | |
| 62 { keys::kHomepageURL, kTypeExtension | kTypePackagedApp }, | |
| 63 | |
| 64 // Extensions, packaged apps and platform apps. | |
| 65 { keys::kContentSecurityPolicy, kTypeAllApps | kTypeExtension }, | |
| 66 { keys::kFileBrowserHandlers, kTypeAllApps | kTypeExtension }, | |
| 67 { keys::kIncognito, kTypeAllApps | kTypeExtension }, | |
| 68 { keys::kNaClModules, kTypeAllApps | kTypeExtension }, | |
| 69 { keys::kPlugins, kTypeAllApps | kTypeExtension }, | |
| 70 { keys::kInputComponents, kTypeAllApps | kTypeExtension }, | |
| 71 { keys::kTtsEngine, kTypeAllApps | kTypeExtension }, | |
| 72 { keys::kIntents, kTypeAllApps | kTypeExtension }, | |
| 73 }; | |
| 74 | |
| 75 ManifestValue::ManifestValue(DictionaryValue* value) | |
| 76 : value_(value) { | |
| 77 // Read the feature restriction data. | |
| 78 for (size_t i = 0; i < arraysize(kFeatureRestrictions); ++i) { | |
| 79 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!
| |
| 80 kFeatureRestrictions[i].restriction; | |
| 81 } | |
| 82 | |
| 83 // Determine what type of extension the manifest represents. | |
| 84 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.
| |
| 85 type_ = kTypeTheme; | |
| 86 else if (IsPlatformApp()) | |
| 87 type_ = kTypePlatformApp; | |
| 88 else if (IsHostedApp()) | |
| 89 type_ = kTypeHostedApp; | |
| 90 else if (IsPackagedApp()) | |
| 91 type_ = kTypePackagedApp; | |
| 92 else | |
| 93 type_ = kTypeExtension; | |
| 94 } | |
| 95 | |
| 96 ManifestValue::~ManifestValue() {} | |
| 97 | |
| 98 bool ManifestValue::ValidateManifest(std::string* error) const { | |
| 99 for (DictionaryValue::key_iterator key = value_->begin_keys(); | |
| 100 key != value_->end_keys(); ++key) { | |
| 101 // When validating the extension manifests, we ignore keys that are not | |
| 102 // 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.
| |
| 103 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.
| |
| 104 continue; | |
| 105 | |
| 106 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
| |
| 107 *error = ExtensionErrorUtils::FormatErrorMessage( | |
| 108 errors::kFeatureNotAllowed, *key); | |
| 109 return false; | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 return true; | |
| 114 } | |
| 115 | |
| 116 bool ManifestValue::HasKey(const std::string& key) const { | |
| 117 // Return false instead of CHECKing, since we're just testing for existence. | |
| 118 return CanAccessKey(key) && value_->HasKey(key); | |
| 119 } | |
| 120 | |
| 121 bool ManifestValue::Get( | |
| 122 const std::string& path, Value** out_value) const { | |
| 123 CHECK(CanAccessPath(path)) << path; | |
| 124 return value_->Get(path, out_value); | |
| 125 } | |
| 126 | |
| 127 bool ManifestValue::GetBoolean( | |
| 128 const std::string& path, bool* out_value) const { | |
| 129 CHECK(CanAccessPath(path)) << path; | |
| 130 return value_->GetBoolean(path, out_value); | |
| 131 } | |
| 132 | |
| 133 bool ManifestValue::GetInteger( | |
| 134 const std::string& path, int* out_value) const { | |
| 135 CHECK(CanAccessPath(path)) << path; | |
| 136 return value_->GetInteger(path, out_value); | |
| 137 } | |
| 138 | |
| 139 bool ManifestValue::GetString( | |
| 140 const std::string& path, std::string* out_value) const { | |
| 141 CHECK(CanAccessPath(path)) << path; | |
| 142 return value_->GetString(path, out_value); | |
| 143 } | |
| 144 | |
| 145 bool ManifestValue::GetString( | |
| 146 const std::string& path, string16* out_value) const { | |
| 147 CHECK(CanAccessPath(path)) << path; | |
| 148 return value_->GetString(path, out_value); | |
| 149 } | |
| 150 | |
| 151 bool ManifestValue::GetDictionary( | |
| 152 const std::string& path, DictionaryValue** out_value) const { | |
| 153 CHECK(CanAccessPath(path)) << path; | |
| 154 return value_->GetDictionary(path, out_value); | |
| 155 } | |
| 156 | |
| 157 bool ManifestValue::GetList( | |
| 158 const std::string& path, ListValue** out_value) const { | |
| 159 CHECK(CanAccessPath(path)) << path; | |
| 160 return value_->GetList(path, out_value); | |
| 161 } | |
| 162 | |
| 163 ManifestValue* ManifestValue::DeepCopy() const { | |
| 164 return new ManifestValue(value_->DeepCopy()); | |
| 165 } | |
| 166 | |
| 167 bool ManifestValue::Equals(const ManifestValue* other) const { | |
| 168 return other && value_->Equals(other->value()); | |
| 169 } | |
| 170 | |
| 171 bool ManifestValue::IsTheme() const { | |
| 172 DictionaryValue* dict_value = NULL; | |
| 173 return value_->HasKey(keys::kTheme) && | |
| 174 value_->GetDictionary(keys::kTheme, &dict_value); | |
| 175 } | |
| 176 | |
| 177 bool ManifestValue::IsPlatformApp() const { | |
| 178 return value_->HasKey(keys::kPlatformApp); | |
| 179 } | |
| 180 | |
| 181 bool ManifestValue::IsPackagedApp() const { | |
| 182 return value_->HasKey(keys::kApp) && !value_->HasKey(keys::kWebURLs); | |
| 183 } | |
| 184 | |
| 185 bool ManifestValue::IsHostedApp() const { | |
| 186 return value_->HasKey(keys::kApp) && value_->HasKey(keys::kWebURLs); | |
| 187 } | |
| 188 | |
| 189 bool ManifestValue::IsKnownKey(const std::string& key) const { | |
| 190 RestrictionMap::const_iterator i = restrictions_.find(key); | |
| 191 return i != restrictions_.end(); | |
| 192 } | |
| 193 | |
| 194 bool ManifestValue::CanAccessKey(const std::string& key) const { | |
| 195 RestrictionMap::const_iterator i = restrictions_.find(key); | |
| 196 return (i != restrictions_.end() && (type_ & i->second) != 0); | |
| 197 } | |
| 198 | |
| 199 bool ManifestValue::CanAccessPath(const std::string& path) const { | |
| 200 std::vector<std::string> components; | |
| 201 base::SplitString(path, '.', &components); | |
| 202 return CanAccessKey(components[0]); | |
| 203 } | |
| OLD | NEW |