| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 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 "chrome/common/extensions/manifest.h" | |
| 6 | |
| 7 #include "base/basictypes.h" | |
| 8 #include "base/lazy_instance.h" | |
| 9 #include "base/logging.h" | |
| 10 #include "base/string_split.h" | |
| 11 #include "base/values.h" | |
| 12 #include "chrome/common/extensions/extension_constants.h" | |
| 13 #include "chrome/common/extensions/extension_error_utils.h" | |
| 14 | |
| 15 namespace errors = extension_manifest_errors; | |
| 16 namespace keys = extension_manifest_keys; | |
| 17 | |
| 18 namespace extensions { | |
| 19 | |
| 20 namespace { | |
| 21 | |
| 22 typedef std::map<std::string, int> RestrictionMap; | |
| 23 | |
| 24 struct Restrictions { | |
| 25 Restrictions() { | |
| 26 // Base keys that all manifests can specify. | |
| 27 map[keys::kName] = Manifest::kTypeAll; | |
| 28 map[keys::kVersion] = Manifest::kTypeAll; | |
| 29 map[keys::kManifestVersion] = Manifest::kTypeAll; | |
| 30 map[keys::kDescription] = Manifest::kTypeAll; | |
| 31 map[keys::kIcons] = Manifest::kTypeAll; | |
| 32 map[keys::kCurrentLocale] = Manifest::kTypeAll; | |
| 33 map[keys::kDefaultLocale] = Manifest::kTypeAll; | |
| 34 map[keys::kSignature] = Manifest::kTypeAll; | |
| 35 map[keys::kUpdateURL] = Manifest::kTypeAll; | |
| 36 map[keys::kPublicKey] = Manifest::kTypeAll; | |
| 37 | |
| 38 // Type specific. | |
| 39 map[keys::kApp] = Manifest::kTypeHostedApp | Manifest::kTypePackagedApp | | |
| 40 Manifest::kTypePlatformApp; | |
| 41 map[keys::kTheme] = Manifest::kTypeTheme; | |
| 42 | |
| 43 // keys::kPlatformApp holds a boolean, so all types can define it. | |
| 44 map[keys::kPlatformApp] = Manifest::kTypeAll; | |
| 45 | |
| 46 // Extensions only. | |
| 47 map[keys::kBrowserAction] = Manifest::kTypeExtension; | |
| 48 map[keys::kPageAction] = Manifest::kTypeExtension; | |
| 49 map[keys::kPageActions] = Manifest::kTypeExtension; | |
| 50 map[keys::kChromeURLOverrides] = Manifest::kTypeExtension; | |
| 51 | |
| 52 // Everything except themes. | |
| 53 int all_but_themes = Manifest::kTypeAll - Manifest::kTypeTheme; | |
| 54 map[keys::kPermissions] = all_but_themes; | |
| 55 map[keys::kOptionalPermissions] = all_but_themes; | |
| 56 map[keys::kOptionsPage] = all_but_themes; | |
| 57 map[keys::kBackground] = all_but_themes; | |
| 58 map[keys::kOfflineEnabled] = all_but_themes; | |
| 59 map[keys::kMinimumChromeVersion] = all_but_themes; | |
| 60 map[keys::kRequirements] = all_but_themes; | |
| 61 map[keys::kConvertedFromUserScript] = all_but_themes; | |
| 62 map[keys::kNaClModules] = all_but_themes; | |
| 63 map[keys::kPlugins] = all_but_themes; | |
| 64 | |
| 65 // Extensions and packaged apps. | |
| 66 int ext_and_packaged = | |
| 67 Manifest::kTypeExtension | Manifest::kTypePackagedApp; | |
| 68 map[keys::kContentScripts] = ext_and_packaged; | |
| 69 map[keys::kOmnibox] = ext_and_packaged; | |
| 70 map[keys::kDevToolsPage] = ext_and_packaged; | |
| 71 map[keys::kSidebar] = ext_and_packaged; | |
| 72 map[keys::kHomepageURL] = ext_and_packaged; | |
| 73 | |
| 74 // Extensions, packaged apps and platform apps. | |
| 75 int local_apps_and_ext = ext_and_packaged | Manifest::kTypePlatformApp; | |
| 76 map[keys::kContentSecurityPolicy] = local_apps_and_ext; | |
| 77 map[keys::kFileBrowserHandlers] = local_apps_and_ext; | |
| 78 map[keys::kIncognito] = local_apps_and_ext; | |
| 79 map[keys::kInputComponents] = local_apps_and_ext; | |
| 80 map[keys::kTtsEngine] = local_apps_and_ext; | |
| 81 map[keys::kIntents] = local_apps_and_ext; | |
| 82 } | |
| 83 | |
| 84 // Returns true if the |key| is recognized. | |
| 85 bool IsKnownKey(const std::string& key) const { | |
| 86 RestrictionMap::const_iterator i = map.find(key); | |
| 87 return i != map.end(); | |
| 88 } | |
| 89 | |
| 90 // Returns true if the given |key| can be specified by the manifest |type|. | |
| 91 bool CanAccessKey(const std::string& key, Manifest::Type type) const { | |
| 92 RestrictionMap::const_iterator i = map.find(key); | |
| 93 return (i != map.end() && (type & i->second) != 0); | |
| 94 } | |
| 95 | |
| 96 RestrictionMap map; | |
| 97 }; | |
| 98 | |
| 99 base::LazyInstance<Restrictions> g_restrictions; | |
| 100 | |
| 101 } // namespace | |
| 102 | |
| 103 // static | |
| 104 std::set<std::string> Manifest::GetAllKnownKeys() { | |
| 105 std::set<std::string> keys; | |
| 106 const RestrictionMap& map = g_restrictions.Get().map; | |
| 107 for (RestrictionMap::const_iterator i = map.begin(); i != map.end(); i++) | |
| 108 keys.insert(i->first); | |
| 109 return keys; | |
| 110 } | |
| 111 | |
| 112 Manifest::Manifest(DictionaryValue* value) : value_(value) {} | |
| 113 Manifest::~Manifest() {} | |
| 114 | |
| 115 bool Manifest::ValidateManifest(std::string* error) const { | |
| 116 Restrictions restrictions = g_restrictions.Get(); | |
| 117 Type type = GetType(); | |
| 118 | |
| 119 for (DictionaryValue::key_iterator key = value_->begin_keys(); | |
| 120 key != value_->end_keys(); ++key) { | |
| 121 // When validating the extension manifests, we ignore keys that are not | |
| 122 // recognized for forward compatibility. | |
| 123 if (!restrictions.IsKnownKey(*key)) { | |
| 124 // TODO(aa): Consider having an error here in the case of strict error | |
| 125 // checking to let developers know when they screw up. | |
| 126 continue; | |
| 127 } | |
| 128 | |
| 129 if (!restrictions.CanAccessKey(*key, type)) { | |
| 130 *error = ExtensionErrorUtils::FormatErrorMessage( | |
| 131 errors::kFeatureNotAllowed, *key); | |
| 132 return false; | |
| 133 } | |
| 134 } | |
| 135 | |
| 136 return true; | |
| 137 } | |
| 138 | |
| 139 bool Manifest::HasKey(const std::string& key) const { | |
| 140 Restrictions restrictions = g_restrictions.Get(); | |
| 141 return restrictions.CanAccessKey(key, GetType()) && value_->HasKey(key); | |
| 142 } | |
| 143 | |
| 144 bool Manifest::Get( | |
| 145 const std::string& path, Value** out_value) const { | |
| 146 return CanAccessPath(path) && value_->Get(path, out_value); | |
| 147 } | |
| 148 | |
| 149 bool Manifest::GetBoolean( | |
| 150 const std::string& path, bool* out_value) const { | |
| 151 return CanAccessPath(path) && value_->GetBoolean(path, out_value); | |
| 152 } | |
| 153 | |
| 154 bool Manifest::GetInteger( | |
| 155 const std::string& path, int* out_value) const { | |
| 156 return CanAccessPath(path) && value_->GetInteger(path, out_value); | |
| 157 } | |
| 158 | |
| 159 bool Manifest::GetString( | |
| 160 const std::string& path, std::string* out_value) const { | |
| 161 return CanAccessPath(path) && value_->GetString(path, out_value); | |
| 162 } | |
| 163 | |
| 164 bool Manifest::GetString( | |
| 165 const std::string& path, string16* out_value) const { | |
| 166 return CanAccessPath(path) && value_->GetString(path, out_value); | |
| 167 } | |
| 168 | |
| 169 bool Manifest::GetDictionary( | |
| 170 const std::string& path, DictionaryValue** out_value) const { | |
| 171 return CanAccessPath(path) && value_->GetDictionary(path, out_value); | |
| 172 } | |
| 173 | |
| 174 bool Manifest::GetList( | |
| 175 const std::string& path, ListValue** out_value) const { | |
| 176 return CanAccessPath(path) && value_->GetList(path, out_value); | |
| 177 } | |
| 178 | |
| 179 Manifest* Manifest::DeepCopy() const { | |
| 180 return new Manifest(value_->DeepCopy()); | |
| 181 } | |
| 182 | |
| 183 bool Manifest::Equals(const Manifest* other) const { | |
| 184 return other && value_->Equals(other->value()); | |
| 185 } | |
| 186 | |
| 187 Manifest::Type Manifest::GetType() const { | |
| 188 if (value_->HasKey(keys::kTheme)) | |
| 189 return kTypeTheme; | |
| 190 bool is_platform_app = false; | |
| 191 if (value_->GetBoolean(keys::kPlatformApp, &is_platform_app) && | |
| 192 is_platform_app) | |
| 193 return kTypePlatformApp; | |
| 194 if (value_->HasKey(keys::kApp)) { | |
| 195 if (value_->Get(keys::kWebURLs, NULL) || | |
| 196 value_->Get(keys::kLaunchWebURL, NULL)) | |
| 197 return kTypeHostedApp; | |
| 198 else | |
| 199 return kTypePackagedApp; | |
| 200 } else { | |
| 201 return kTypeExtension; | |
| 202 } | |
| 203 } | |
| 204 | |
| 205 bool Manifest::IsTheme() const { | |
| 206 return GetType() == kTypeTheme; | |
| 207 } | |
| 208 | |
| 209 bool Manifest::IsPlatformApp() const { | |
| 210 return GetType() == kTypePlatformApp; | |
| 211 } | |
| 212 | |
| 213 bool Manifest::IsPackagedApp() const { | |
| 214 return GetType() == kTypePackagedApp; | |
| 215 } | |
| 216 | |
| 217 bool Manifest::IsHostedApp() const { | |
| 218 return GetType() == kTypeHostedApp; | |
| 219 } | |
| 220 | |
| 221 bool Manifest::CanAccessPath(const std::string& path) const { | |
| 222 std::vector<std::string> components; | |
| 223 base::SplitString(path, '.', &components); | |
| 224 | |
| 225 Restrictions restrictions = g_restrictions.Get(); | |
| 226 return restrictions.CanAccessKey(components[0], GetType()); | |
| 227 } | |
| 228 | |
| 229 } // namespace extensions | |
| OLD | NEW |