| Index: chrome/common/extensions/extension.cc | 
| diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc | 
| index c68280fab48b4709a801289d3bcb7728fd1ec8c7..1e84be7560bbf5313dc5b32322f2292a53eacef4 100644 | 
| --- a/chrome/common/extensions/extension.cc | 
| +++ b/chrome/common/extensions/extension.cc | 
| @@ -34,6 +34,7 @@ | 
| #include "chrome/common/extensions/extension_sidebar_defaults.h" | 
| #include "chrome/common/extensions/extension_sidebar_utils.h" | 
| #include "chrome/common/extensions/file_browser_handler.h" | 
| +#include "chrome/common/extensions/manifest.h" | 
| #include "chrome/common/extensions/user_script.h" | 
| #include "chrome/common/url_constants.h" | 
| #include "googleurl/src/url_util.h" | 
| @@ -85,29 +86,6 @@ static void ConvertHexadecimalToIDAlphabet(std::string* id) { | 
| } | 
| } | 
|  | 
| -// These keys are allowed by all crx files (apps, extensions, themes, etc). | 
| -static const char* kBaseCrxKeys[] = { | 
| -  keys::kCurrentLocale, | 
| -  keys::kDefaultLocale, | 
| -  keys::kDescription, | 
| -  keys::kIcons, | 
| -  keys::kManifestVersion, | 
| -  keys::kName, | 
| -  keys::kPublicKey, | 
| -  keys::kSignature, | 
| -  keys::kUpdateURL, | 
| -  keys::kVersion, | 
| -}; | 
| - | 
| -bool IsBaseCrxKey(const std::string& key) { | 
| -  for (size_t i = 0; i < arraysize(kBaseCrxKeys); ++i) { | 
| -    if (key == kBaseCrxKeys[i]) | 
| -      return true; | 
| -  } | 
| - | 
| -  return false; | 
| -} | 
| - | 
| // A singleton object containing global data needed by the extension objects. | 
| class ExtensionConfig { | 
| public: | 
| @@ -253,7 +231,8 @@ scoped_refptr<Extension> Extension::Create(const FilePath& path, | 
| DCHECK(error); | 
| scoped_refptr<Extension> extension = new Extension(path, location); | 
|  | 
| -  if (!extension->InitFromValue(value, flags, error)) | 
| +  if (!extension->InitFromValue(new extensions::Manifest(value.DeepCopy()), | 
| +                                flags, error)) | 
| return NULL; | 
| return extension; | 
| } | 
| @@ -900,31 +879,7 @@ ExtensionSidebarDefaults* Extension::LoadExtensionSidebarDefaults( | 
| return result.release(); | 
| } | 
|  | 
| -bool Extension::ContainsNonThemeKeys(const DictionaryValue& source) const { | 
| -  for (DictionaryValue::key_iterator key = source.begin_keys(); | 
| -       key != source.end_keys(); ++key) { | 
| -    if (!IsBaseCrxKey(*key) && *key != keys::kTheme) | 
| -      return true; | 
| -  } | 
| -  return false; | 
| -} | 
| - | 
| -bool Extension::LoadIsApp(const DictionaryValue* manifest, | 
| -                          std::string* error) { | 
| -  if (manifest->HasKey(keys::kApp)) | 
| -    is_app_ = true; | 
| - | 
| -  if (CommandLine::ForCurrentProcess()->HasSwitch( | 
| -          switches::kEnablePlatformApps)) { | 
| -    if (manifest->HasKey(keys::kPlatformApp)) { | 
| -      manifest->GetBoolean(keys::kPlatformApp, &is_platform_app_); | 
| -    } | 
| -  } | 
| - | 
| -  return true; | 
| -} | 
| - | 
| -bool Extension::LoadExtent(const DictionaryValue* manifest, | 
| +bool Extension::LoadExtent(const extensions::Manifest* manifest, | 
| const char* key, | 
| URLPatternSet* extent, | 
| const char* list_error, | 
| @@ -1001,7 +956,7 @@ bool Extension::LoadExtent(const DictionaryValue* manifest, | 
| return true; | 
| } | 
|  | 
| -bool Extension::LoadLaunchURL(const DictionaryValue* manifest, | 
| +bool Extension::LoadLaunchURL(const extensions::Manifest* manifest, | 
| std::string* error) { | 
| Value* temp = NULL; | 
|  | 
| @@ -1099,7 +1054,7 @@ bool Extension::LoadLaunchURL(const DictionaryValue* manifest, | 
| return true; | 
| } | 
|  | 
| -bool Extension::LoadLaunchContainer(const DictionaryValue* manifest, | 
| +bool Extension::LoadLaunchContainer(const extensions::Manifest* manifest, | 
| std::string* error) { | 
| Value* temp = NULL; | 
| if (!manifest->Get(keys::kLaunchContainer, &temp)) | 
| @@ -1154,7 +1109,7 @@ bool Extension::LoadLaunchContainer(const DictionaryValue* manifest, | 
| return true; | 
| } | 
|  | 
| -bool Extension::LoadAppIsolation(const DictionaryValue* manifest, | 
| +bool Extension::LoadAppIsolation(const extensions::Manifest* manifest, | 
| std::string* error) { | 
| Value* temp = NULL; | 
| if (!manifest->Get(keys::kIsolation, &temp)) | 
| @@ -1186,18 +1141,18 @@ bool Extension::LoadAppIsolation(const DictionaryValue* manifest, | 
| return true; | 
| } | 
|  | 
| -bool Extension::LoadWebIntentServices(const base::DictionaryValue& manifest, | 
| +bool Extension::LoadWebIntentServices(const extensions::Manifest* manifest, | 
| std::string* error) { | 
| DCHECK(error); | 
|  | 
| if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableWebIntents)) | 
| return true; | 
|  | 
| -  if (!manifest.HasKey(keys::kIntents)) | 
| +  if (!manifest->HasKey(keys::kIntents)) | 
| return true; | 
|  | 
| DictionaryValue* all_services = NULL; | 
| -  if (!manifest.GetDictionary(keys::kIntents, &all_services)) { | 
| +  if (!manifest->GetDictionary(keys::kIntents, &all_services)) { | 
| *error = errors::kInvalidIntents; | 
| return false; | 
| } | 
| @@ -1256,32 +1211,6 @@ bool Extension::LoadWebIntentServices(const base::DictionaryValue& manifest, | 
| return true; | 
| } | 
|  | 
| - | 
| -bool Extension::EnsureNotHybridApp(const DictionaryValue* manifest, | 
| -                                   std::string* error) { | 
| -  if (web_extent().is_empty()) | 
| -    return true; | 
| - | 
| -  for (DictionaryValue::key_iterator key = manifest->begin_keys(); | 
| -       key != manifest->end_keys(); ++key) { | 
| -    if (!IsBaseCrxKey(*key) && | 
| -        *key != keys::kApp && | 
| -        *key != keys::kPermissions && | 
| -        *key != keys::kOptionalPermissions && | 
| -        *key != keys::kOptionsPage && | 
| -        *key != keys::kBackground && | 
| -        *key != keys::kOfflineEnabled && | 
| -        *key != keys::kMinimumChromeVersion && | 
| -        *key != keys::kRequirements) { | 
| -      *error = ExtensionErrorUtils::FormatErrorMessage( | 
| -          errors::kHostedAppsCannotIncludeExtensionFeatures, *key); | 
| -      return false; | 
| -    } | 
| -  } | 
| - | 
| -  return true; | 
| -} | 
| - | 
| // static | 
| bool Extension::IsTrustedId(const std::string& id) { | 
| // See http://b/4946060 for more details. | 
| @@ -1294,9 +1223,6 @@ Extension::Extension(const FilePath& path, Location location) | 
| offline_enabled_(false), | 
| location_(location), | 
| converted_from_user_script_(false), | 
| -      is_theme_(false), | 
| -      is_app_(false), | 
| -      is_platform_app_(false), | 
| is_storage_isolated_(false), | 
| launch_container_(extension_misc::LAUNCH_TAB), | 
| launch_width_(0), | 
| @@ -1455,10 +1381,14 @@ GURL Extension::GetBaseURLFromExtensionId(const std::string& extension_id) { | 
| chrome::kStandardSchemeSeparator + extension_id + "/"); | 
| } | 
|  | 
| -bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| +bool Extension::InitFromValue(extensions::Manifest* manifest, int flags, | 
| std::string* error) { | 
| DCHECK(error); | 
| base::AutoLock auto_lock(runtime_data_lock_); | 
| + | 
| +  if (!manifest->ValidateManifest(error)) | 
| +    return false; | 
| + | 
| // When strict error checks are enabled, make URL pattern parsing strict. | 
| URLPattern::ParseOption parse_strictness = | 
| (flags & STRICT_ERROR_CHECKS ? URLPattern::ERROR_ON_PORTS | 
| @@ -1469,9 +1399,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| optional_permission_set_ = new ExtensionPermissionSet(); | 
| required_permission_set_ = new ExtensionPermissionSet(); | 
|  | 
| -  if (source.HasKey(keys::kManifestVersion)) { | 
| +  if (manifest->HasKey(keys::kManifestVersion)) { | 
| int manifest_version = 0; | 
| -    if (!source.GetInteger(keys::kManifestVersion, &manifest_version) || | 
| +    if (!manifest->GetInteger(keys::kManifestVersion, &manifest_version) || | 
| manifest_version < 1) { | 
| *error = errors::kInvalidManifestVersion; | 
| return false; | 
| @@ -1490,10 +1420,10 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| return false; | 
| } | 
|  | 
| -  if (source.HasKey(keys::kPublicKey)) { | 
| +  if (manifest->HasKey(keys::kPublicKey)) { | 
| std::string public_key_bytes; | 
| -    if (!source.GetString(keys::kPublicKey, | 
| -                          &public_key_) || | 
| +    if (!manifest->GetString(keys::kPublicKey, | 
| +                         &public_key_) || | 
| !ParsePEMKeyBytes(public_key_, | 
| &public_key_bytes) || | 
| !GenerateId(public_key_bytes, &id_)) { | 
| @@ -1516,15 +1446,14 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
|  | 
| creation_flags_ = flags; | 
|  | 
| -  // Make a copy of the manifest so we can store it in prefs. | 
| -  manifest_value_.reset(source.DeepCopy()); | 
| +  manifest_.reset(manifest); | 
|  | 
| // Initialize the URL. | 
| extension_url_ = Extension::GetBaseURLFromExtensionId(id()); | 
|  | 
| // Initialize version. | 
| std::string version_str; | 
| -  if (!source.GetString(keys::kVersion, &version_str)) { | 
| +  if (!manifest->GetString(keys::kVersion, &version_str)) { | 
| *error = errors::kInvalidVersion; | 
| return false; | 
| } | 
| @@ -1537,7 +1466,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
|  | 
| // Initialize name. | 
| string16 localized_name; | 
| -  if (!source.GetString(keys::kName, &localized_name)) { | 
| +  if (!manifest->GetString(keys::kName, &localized_name)) { | 
| *error = errors::kInvalidName; | 
| return false; | 
| } | 
| @@ -1547,18 +1476,17 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| // Load App settings. LoadExtent at least has to be done before | 
| // ParsePermissions(), because the valid permissions depend on what type of | 
| // package this is. | 
| -  if (!LoadIsApp(manifest_value_.get(), error) || | 
| -      !LoadExtent(manifest_value_.get(), keys::kWebURLs, | 
| -                  &extent_, | 
| -                  errors::kInvalidWebURLs, errors::kInvalidWebURL, | 
| -                  parse_strictness, error) || | 
| -      !EnsureNotHybridApp(manifest_value_.get(), error) || | 
| -      !LoadLaunchURL(manifest_value_.get(), error) || | 
| -      !LoadLaunchContainer(manifest_value_.get(), error)) { | 
| +  if (is_app() && | 
| +      (!LoadExtent(manifest_.get(), keys::kWebURLs, | 
| +                   &extent_, | 
| +                   errors::kInvalidWebURLs, errors::kInvalidWebURL, | 
| +                   parse_strictness, error) || | 
| +       !LoadLaunchURL(manifest_.get(), error) || | 
| +       !LoadLaunchContainer(manifest_.get(), error))) { | 
| return false; | 
| } | 
|  | 
| -  if (is_platform_app_) { | 
| +  if (is_platform_app()) { | 
| if (launch_container() != extension_misc::LAUNCH_SHELL) { | 
| *error = errors::kInvalidLaunchContainerForPlatform; | 
| return false; | 
| @@ -1571,7 +1499,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| // Initialize the permissions (optional). | 
| ExtensionAPIPermissionSet api_permissions; | 
| URLPatternSet host_permissions; | 
| -  if (!ParsePermissions(&source, | 
| +  if (!ParsePermissions(manifest_.get(), | 
| keys::kPermissions, | 
| flags, | 
| error, | 
| @@ -1583,7 +1511,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| // Initialize the optional permissions (optional). | 
| ExtensionAPIPermissionSet optional_api_permissions; | 
| URLPatternSet optional_host_permissions; | 
| -  if (!ParsePermissions(&source, | 
| +  if (!ParsePermissions(manifest_.get(), | 
| keys::kOptionalPermissions, | 
| flags, | 
| error, | 
| @@ -1593,8 +1521,8 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
|  | 
| // Initialize description (if present). | 
| -  if (source.HasKey(keys::kDescription)) { | 
| -    if (!source.GetString(keys::kDescription, | 
| +  if (manifest->HasKey(keys::kDescription)) { | 
| +    if (!manifest->GetString(keys::kDescription, | 
| &description_)) { | 
| *error = errors::kInvalidDescription; | 
| return false; | 
| @@ -1602,9 +1530,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
|  | 
| // Initialize homepage url (if present). | 
| -  if (source.HasKey(keys::kHomepageURL)) { | 
| +  if (manifest->HasKey(keys::kHomepageURL)) { | 
| std::string tmp; | 
| -    if (!source.GetString(keys::kHomepageURL, &tmp)) { | 
| +    if (!manifest->GetString(keys::kHomepageURL, &tmp)) { | 
| *error = ExtensionErrorUtils::FormatErrorMessage( | 
| errors::kInvalidHomepageURL, ""); | 
| return false; | 
| @@ -1620,9 +1548,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
|  | 
| // Initialize update url (if present). | 
| -  if (source.HasKey(keys::kUpdateURL)) { | 
| +  if (manifest->HasKey(keys::kUpdateURL)) { | 
| std::string tmp; | 
| -    if (!source.GetString(keys::kUpdateURL, &tmp)) { | 
| +    if (!manifest->GetString(keys::kUpdateURL, &tmp)) { | 
| *error = ExtensionErrorUtils::FormatErrorMessage( | 
| errors::kInvalidUpdateURL, ""); | 
| return false; | 
| @@ -1638,9 +1566,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
|  | 
| // Validate minimum Chrome version (if present). We don't need to store this, | 
| // since the extension is not valid if it is incorrect. | 
| -  if (source.HasKey(keys::kMinimumChromeVersion)) { | 
| +  if (manifest->HasKey(keys::kMinimumChromeVersion)) { | 
| std::string minimum_version_string; | 
| -    if (!source.GetString(keys::kMinimumChromeVersion, | 
| +    if (!manifest->GetString(keys::kMinimumChromeVersion, | 
| &minimum_version_string)) { | 
| *error = errors::kInvalidMinimumChromeVersion; | 
| return false; | 
| @@ -1676,13 +1604,14 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
|  | 
| // Initialize converted_from_user_script (if present) | 
| -  source.GetBoolean(keys::kConvertedFromUserScript, | 
| -                    &converted_from_user_script_); | 
| +  if (manifest->HasKey(keys::kConvertedFromUserScript)) | 
| +    manifest->GetBoolean(keys::kConvertedFromUserScript, | 
| +                        &converted_from_user_script_); | 
|  | 
| // Initialize icons (if present). | 
| -  if (source.HasKey(keys::kIcons)) { | 
| +  if (manifest->HasKey(keys::kIcons)) { | 
| DictionaryValue* icons_value = NULL; | 
| -    if (!source.GetDictionary(keys::kIcons, &icons_value)) { | 
| +    if (!manifest->GetDictionary(keys::kIcons, &icons_value)) { | 
| *error = errors::kInvalidIcons; | 
| return false; | 
| } | 
| @@ -1712,20 +1641,12 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
|  | 
| // Initialize themes (if present). | 
| -  is_theme_ = false; | 
| -  if (source.HasKey(keys::kTheme)) { | 
| -    // Themes cannot contain extension keys. | 
| -    if (ContainsNonThemeKeys(source)) { | 
| -      *error = errors::kThemesCannotContainExtensions; | 
| -      return false; | 
| -    } | 
| - | 
| +  if (manifest->HasKey(keys::kTheme)) { | 
| DictionaryValue* theme_value = NULL; | 
| -    if (!source.GetDictionary(keys::kTheme, &theme_value)) { | 
| +    if (!manifest->GetDictionary(keys::kTheme, &theme_value)) { | 
| *error = errors::kInvalidTheme; | 
| return false; | 
| } | 
| -    is_theme_ = true; | 
|  | 
| DictionaryValue* images_value = NULL; | 
| if (theme_value->GetDictionary(keys::kThemeImages, &images_value)) { | 
| @@ -1798,9 +1719,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
|  | 
| // Initialize plugins (optional). | 
| -  if (source.HasKey(keys::kPlugins)) { | 
| +  if (manifest->HasKey(keys::kPlugins)) { | 
| ListValue* list_value = NULL; | 
| -    if (!source.GetList(keys::kPlugins, &list_value)) { | 
| +    if (!manifest->GetList(keys::kPlugins, &list_value)) { | 
| *error = errors::kInvalidPlugins; | 
| return false; | 
| } | 
| @@ -1842,9 +1763,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
| } | 
|  | 
| -  if (source.HasKey(keys::kNaClModules)) { | 
| +  if (manifest->HasKey(keys::kNaClModules)) { | 
| ListValue* list_value = NULL; | 
| -    if (!source.GetList(keys::kNaClModules, &list_value)) { | 
| +    if (!manifest->GetList(keys::kNaClModules, &list_value)) { | 
| *error = errors::kInvalidNaClModules; | 
| return false; | 
| } | 
| @@ -1880,9 +1801,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
|  | 
| // Initialize content scripts (optional). | 
| -  if (source.HasKey(keys::kContentScripts)) { | 
| +  if (manifest->HasKey(keys::kContentScripts)) { | 
| ListValue* list_value; | 
| -    if (!source.GetList(keys::kContentScripts, &list_value)) { | 
| +    if (!manifest->GetList(keys::kContentScripts, &list_value)) { | 
| *error = errors::kInvalidContentScriptsList; | 
| return false; | 
| } | 
| @@ -1910,9 +1831,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| // Initialize page action (optional). | 
| DictionaryValue* page_action_value = NULL; | 
|  | 
| -  if (source.HasKey(keys::kPageActions)) { | 
| +  if (manifest->HasKey(keys::kPageActions)) { | 
| ListValue* list_value = NULL; | 
| -    if (!source.GetList(keys::kPageActions, &list_value)) { | 
| +    if (!manifest->GetList(keys::kPageActions, &list_value)) { | 
| *error = errors::kInvalidPageActionsList; | 
| return false; | 
| } | 
| @@ -1931,8 +1852,8 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| *error = errors::kInvalidPageActionsListSize; | 
| return false; | 
| } | 
| -  } else if (source.HasKey(keys::kPageAction)) { | 
| -    if (!source.GetDictionary(keys::kPageAction, &page_action_value)) { | 
| +  } else if (manifest->HasKey(keys::kPageAction)) { | 
| +    if (!manifest->GetDictionary(keys::kPageAction, &page_action_value)) { | 
| *error = errors::kInvalidPageAction; | 
| return false; | 
| } | 
| @@ -1947,9 +1868,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
|  | 
| // Initialize browser action (optional). | 
| -  if (source.HasKey(keys::kBrowserAction)) { | 
| +  if (manifest->HasKey(keys::kBrowserAction)) { | 
| DictionaryValue* browser_action_value = NULL; | 
| -    if (!source.GetDictionary(keys::kBrowserAction, &browser_action_value)) { | 
| +    if (!manifest->GetDictionary(keys::kBrowserAction, &browser_action_value)) { | 
| *error = errors::kInvalidBrowserAction; | 
| return false; | 
| } | 
| @@ -1961,9 +1882,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
|  | 
| // Initialize file browser actions (optional). | 
| -  if (source.HasKey(keys::kFileBrowserHandlers)) { | 
| +  if (manifest->HasKey(keys::kFileBrowserHandlers)) { | 
| ListValue* file_browser_handlers_value = NULL; | 
| -    if (!source.GetList(keys::kFileBrowserHandlers, | 
| +    if (!manifest->GetList(keys::kFileBrowserHandlers, | 
| &file_browser_handlers_value)) { | 
| *error = errors::kInvalidFileBrowserHandler; | 
| return false; | 
| @@ -1977,15 +1898,14 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
|  | 
| // App isolation. | 
| if (api_permissions.count(ExtensionAPIPermission::kExperimental)) { | 
| -    if (!LoadAppIsolation(manifest_value_.get(), error)) | 
| +    if (is_app() && !LoadAppIsolation(manifest_.get(), error)) | 
| return false; | 
| } | 
|  | 
| // Initialize options page url (optional). | 
| -  // Function LoadIsApp() set is_app_ above. | 
| -  if (source.HasKey(keys::kOptionsPage)) { | 
| +  if (manifest->HasKey(keys::kOptionsPage)) { | 
| std::string options_str; | 
| -    if (!source.GetString(keys::kOptionsPage, &options_str)) { | 
| +    if (!manifest->GetString(keys::kOptionsPage, &options_str)) { | 
| *error = errors::kInvalidOptionsPage; | 
| return false; | 
| } | 
| @@ -2014,9 +1934,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
|  | 
| // Initialize background url (optional). | 
| -  if (source.HasKey(keys::kBackground)) { | 
| +  if (manifest->HasKey(keys::kBackground)) { | 
| std::string background_str; | 
| -    if (!source.GetString(keys::kBackground, &background_str)) { | 
| +    if (!manifest->GetString(keys::kBackground, &background_str)) { | 
| *error = errors::kInvalidBackground; | 
| return false; | 
| } | 
| @@ -2047,8 +1967,8 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
| } | 
|  | 
| -  if (source.HasKey(keys::kDefaultLocale)) { | 
| -    if (!source.GetString(keys::kDefaultLocale, &default_locale_) || | 
| +  if (manifest->HasKey(keys::kDefaultLocale)) { | 
| +    if (!manifest->GetString(keys::kDefaultLocale, &default_locale_) || | 
| !l10n_util::IsValidLocaleSyntax(default_locale_)) { | 
| *error = errors::kInvalidDefaultLocale; | 
| return false; | 
| @@ -2056,9 +1976,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
|  | 
| // Chrome URL overrides (optional) | 
| -  if (source.HasKey(keys::kChromeURLOverrides)) { | 
| +  if (manifest->HasKey(keys::kChromeURLOverrides)) { | 
| DictionaryValue* overrides = NULL; | 
| -    if (!source.GetDictionary(keys::kChromeURLOverrides, &overrides)) { | 
| +    if (!manifest->GetDictionary(keys::kChromeURLOverrides, &overrides)) { | 
| *error = errors::kInvalidChromeURLOverrides; | 
| return false; | 
| } | 
| @@ -2100,9 +2020,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
|  | 
| if (api_permissions.count(ExtensionAPIPermission::kExperimental) && | 
| -      source.HasKey(keys::kInputComponents)) { | 
| +      manifest->HasKey(keys::kInputComponents)) { | 
| ListValue* list_value = NULL; | 
| -    if (!source.GetList(keys::kInputComponents, &list_value)) { | 
| +    if (!manifest->GetList(keys::kInputComponents, &list_value)) { | 
| *error = errors::kInvalidInputComponents; | 
| return false; | 
| } | 
| @@ -2231,17 +2151,17 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
| } | 
|  | 
| -  if (source.HasKey(keys::kOmnibox)) { | 
| -    if (!source.GetString(keys::kOmniboxKeyword, &omnibox_keyword_) || | 
| +  if (manifest->HasKey(keys::kOmnibox)) { | 
| +    if (!manifest->GetString(keys::kOmniboxKeyword, &omnibox_keyword_) || | 
| omnibox_keyword_.empty()) { | 
| *error = errors::kInvalidOmniboxKeyword; | 
| return false; | 
| } | 
| } | 
|  | 
| -  if (source.HasKey(keys::kContentSecurityPolicy)) { | 
| +  if (manifest->HasKey(keys::kContentSecurityPolicy)) { | 
| std::string content_security_policy; | 
| -    if (!source.GetString(keys::kContentSecurityPolicy, | 
| +    if (!manifest->GetString(keys::kContentSecurityPolicy, | 
| &content_security_policy)) { | 
| *error = errors::kInvalidContentSecurityPolicy; | 
| return false; | 
| @@ -2266,9 +2186,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
|  | 
| // Initialize devtools page url (optional). | 
| -  if (source.HasKey(keys::kDevToolsPage)) { | 
| +  if (manifest->HasKey(keys::kDevToolsPage)) { | 
| std::string devtools_str; | 
| -    if (!source.GetString(keys::kDevToolsPage, &devtools_str)) { | 
| +    if (!manifest->GetString(keys::kDevToolsPage, &devtools_str)) { | 
| *error = errors::kInvalidDevToolsPage; | 
| return false; | 
| } | 
| @@ -2280,9 +2200,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
|  | 
| // Initialize sidebar action (optional). | 
| -  if (source.HasKey(keys::kSidebar)) { | 
| +  if (manifest->HasKey(keys::kSidebar)) { | 
| DictionaryValue* sidebar_value = NULL; | 
| -    if (!source.GetDictionary(keys::kSidebar, &sidebar_value)) { | 
| +    if (!manifest->GetDictionary(keys::kSidebar, &sidebar_value)) { | 
| *error = errors::kInvalidSidebar; | 
| return false; | 
| } | 
| @@ -2296,9 +2216,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
|  | 
| // Initialize text-to-speech voices (optional). | 
| -  if (source.HasKey(keys::kTtsEngine)) { | 
| +  if (manifest->HasKey(keys::kTtsEngine)) { | 
| DictionaryValue* tts_dict = NULL; | 
| -    if (!source.GetDictionary(keys::kTtsEngine, &tts_dict)) { | 
| +    if (!manifest->GetDictionary(keys::kTtsEngine, &tts_dict)) { | 
| *error = errors::kInvalidTts; | 
| return false; | 
| } | 
| @@ -2379,15 +2299,15 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
|  | 
| // Initialize web intents (optional). | 
| -  if (!LoadWebIntentServices(source, error)) | 
| +  if (!LoadWebIntentServices(manifest, error)) | 
| return false; | 
|  | 
| // Initialize incognito behavior. Apps default to split mode, extensions | 
| // default to spanning. | 
| incognito_split_mode_ = is_app(); | 
| -  if (source.HasKey(keys::kIncognito)) { | 
| +  if (manifest->HasKey(keys::kIncognito)) { | 
| std::string value; | 
| -    if (!source.GetString(keys::kIncognito, &value)) { | 
| +    if (!manifest->GetString(keys::kIncognito, &value)) { | 
| *error = errors::kInvalidIncognitoBehavior; | 
| return false; | 
| } | 
| @@ -2402,8 +2322,8 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| } | 
|  | 
| // Initialize offline-enabled status. Defaults to false. | 
| -  if (source.HasKey(keys::kOfflineEnabled)) { | 
| -    if (!source.GetBoolean(keys::kOfflineEnabled, &offline_enabled_)) { | 
| +  if (manifest->HasKey(keys::kOfflineEnabled)) { | 
| +    if (!manifest->GetBoolean(keys::kOfflineEnabled, &offline_enabled_)) { | 
| *error = errors::kInvalidOfflineEnabled; | 
| return false; | 
| } | 
| @@ -2411,9 +2331,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
|  | 
| // Initialize requirements (optional). Not actually persisted (they're only | 
| // used by the store), but still validated. | 
| -  if (source.HasKey(keys::kRequirements)) { | 
| +  if (manifest->HasKey(keys::kRequirements)) { | 
| DictionaryValue* requirements_value = NULL; | 
| -    if (!source.GetDictionary(keys::kRequirements, &requirements_value)) { | 
| +    if (!manifest->GetDictionary(keys::kRequirements, &requirements_value)) { | 
| *error = errors::kInvalidRequirements; | 
| return false; | 
| } | 
| @@ -2442,13 +2362,6 @@ bool Extension::InitFromValue(const DictionaryValue& source, int flags, | 
| optional_permission_set_ = new ExtensionPermissionSet( | 
| optional_api_permissions, optional_host_permissions, URLPatternSet()); | 
|  | 
| -  // Although |source| is passed in as a const, it's still possible to modify | 
| -  // it.  This is dangerous since the utility process re-uses |source| after | 
| -  // it calls InitFromValue, passing it up to the browser process which calls | 
| -  // InitFromValue again.  As a result, we need to make sure that nobody | 
| -  // accidentally modifies it. | 
| -  DCHECK(source.Equals(manifest_value_.get())); | 
| - | 
| return true; | 
| } | 
|  | 
| @@ -2604,7 +2517,7 @@ GURL Extension::GetIconURL(int size, | 
| return GetResourceURL(path); | 
| } | 
|  | 
| -bool Extension::ParsePermissions(const DictionaryValue* source, | 
| +bool Extension::ParsePermissions(const extensions::Manifest* source, | 
| const char* key, | 
| int flags, | 
| std::string* error, | 
|  |