Commit 953620b6 authored by jstritar@chromium.org's avatar jstritar@chromium.org

Reland restrict extension features based on the extension type.

The "chrome_url_overrides" manifest key is now accessible by packaged apps.

BUG=101992, 104103
TEST=existing, ManifestTest

Review URL: http://codereview.chromium.org/8654001

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112914 0039d316-1c4b-4281-b951-d872f2087c98
parent 10724810
......@@ -13,6 +13,7 @@
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/manifest.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "googleurl/src/gurl.h"
......@@ -98,10 +99,10 @@ IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, IsInstalled) {
scoped_ptr<DictionaryValue> app_details(
static_cast<DictionaryValue*>(
base::JSONReader::Read(result, false /* allow trailing comma */)));
// extension->manifest_value() does not contain the id.
// extension->manifest() does not contain the id.
app_details->Remove("id", NULL);
EXPECT_TRUE(app_details.get());
EXPECT_TRUE(app_details->Equals(extension->manifest_value()));
EXPECT_TRUE(app_details->Equals(extension->manifest()->value()));
// Try to change app.isInstalled. Should silently fail, so
// that isInstalled should have the initial value.
......@@ -177,8 +178,8 @@ IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, GetDetailsForFrame) {
scoped_ptr<DictionaryValue> app_details(
static_cast<DictionaryValue*>(
base::JSONReader::Read(json, false /* allow trailing comma */)));
// extension->manifest_value() does not contain the id.
// extension->manifest() does not contain the id.
app_details->Remove("id", NULL);
EXPECT_TRUE(app_details.get());
EXPECT_TRUE(app_details->Equals(extension->manifest_value()));
EXPECT_TRUE(app_details->Equals(extension->manifest()->value()));
}
......@@ -12,6 +12,7 @@
#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/manifest.h"
#include "chrome/common/extensions/url_pattern.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
......@@ -1106,7 +1107,7 @@ void ExtensionPrefs::OnExtensionInstalled(
// since it may change on disk.
if (extension->location() != Extension::LOAD) {
extension_dict->Set(kPrefManifest,
extension->manifest_value()->DeepCopy());
extension->manifest()->value()->DeepCopy());
}
if (extension->is_app()) {
......@@ -1196,10 +1197,10 @@ void ExtensionPrefs::UpdateManifest(const Extension* extension) {
DictionaryValue* old_manifest = NULL;
bool update_required =
!extension_dict->GetDictionary(kPrefManifest, &old_manifest) ||
!extension->manifest_value()->Equals(old_manifest);
!extension->manifest()->value()->Equals(old_manifest);
if (update_required) {
UpdateExtensionPref(extension->id(), kPrefManifest,
extension->manifest_value()->DeepCopy());
extension->manifest()->value()->DeepCopy());
}
}
}
......
......@@ -15,6 +15,7 @@
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_file_util.h"
#include "chrome/common/extensions/extension_l10n_util.h"
#include "chrome/common/extensions/manifest.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/notification_service.h"
#include "content/browser/user_metrics.h"
......@@ -141,7 +142,7 @@ void InstalledLoader::LoadAllExtensions() {
if (extension.get()) {
extensions_info->at(i)->extension_manifest.reset(
static_cast<DictionaryValue*>(
extension->manifest_value()->DeepCopy()));
extension->manifest()->value()->DeepCopy()));
should_write_prefs = true;
}
}
......
......@@ -138,6 +138,8 @@
'common/extensions/extension_unpacker.h',
'common/extensions/file_browser_handler.cc',
'common/extensions/file_browser_handler.h',
'common/extensions/manifest.cc',
'common/extensions/manifest.h',
'common/extensions/update_manifest.cc',
'common/extensions/update_manifest.h',
'common/extensions/url_pattern.cc',
......
......@@ -1959,6 +1959,7 @@
'common/extensions/extension_test_util.cc',
'common/extensions/extension_unittest.cc',
'common/extensions/extension_unpacker_unittest.cc',
'common/extensions/manifest_unittest.cc',
'common/extensions/update_manifest_unittest.cc',
'common/extensions/url_pattern_set_unittest.cc',
'common/extensions/url_pattern_unittest.cc',
......
This diff is collapsed.
......@@ -20,6 +20,7 @@
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_icon_set.h"
#include "chrome/common/extensions/extension_permission_set.h"
#include "chrome/common/extensions/manifest.h"
#include "chrome/common/extensions/user_script.h"
#include "chrome/common/extensions/url_pattern.h"
#include "chrome/common/extensions/url_pattern_set.h"
......@@ -374,7 +375,7 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// Parses the host and api permissions from the specified permission |key|
// in the manifest |source|.
bool ParsePermissions(const base::DictionaryValue* source,
bool ParsePermissions(const extensions::Manifest* source,
const char* key,
int flags,
std::string* error,
......@@ -531,8 +532,8 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
}
const GURL& update_url() const { return update_url_; }
const ExtensionIconSet& icons() const { return icons_; }
const base::DictionaryValue* manifest_value() const {
return manifest_value_.get();
const extensions::Manifest* manifest() const {
return manifest_.get();
}
const std::string default_locale() const { return default_locale_; }
const URLOverrideMap& GetChromeURLOverrides() const {
......@@ -557,12 +558,12 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
}
// App-related.
bool is_app() const { return is_app_; }
bool is_platform_app() const { return is_platform_app_; }
bool is_hosted_app() const { return is_app() && !web_extent().is_empty(); }
bool is_packaged_app() const {
return !is_platform_app() && is_app() && web_extent().is_empty();
bool is_app() const {
return is_packaged_app() || is_hosted_app() || is_platform_app();
}
bool is_platform_app() const { return manifest()->IsPlatformApp(); }
bool is_hosted_app() const { return manifest()->IsHostedApp(); }
bool is_packaged_app() const { return manifest()->IsPackagedApp(); }
bool is_storage_isolated() const { return is_app() && is_storage_isolated_; }
const URLPatternSet& web_extent() const { return extent_; }
const std::string& launch_local_path() const { return launch_local_path_; }
......@@ -574,7 +575,7 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
int launch_height() const { return launch_height_; }
// Theme-related.
bool is_theme() const { return is_theme_; }
bool is_theme() const { return manifest()->IsTheme(); }
base::DictionaryValue* GetThemeImages() const { return theme_images_.get(); }
base::DictionaryValue* GetThemeColors() const {return theme_colors_.get(); }
base::DictionaryValue* GetThemeTints() const { return theme_tints_.get(); }
......@@ -616,7 +617,8 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
~Extension();
// Initialize the extension from a parsed manifest.
bool InitFromValue(const base::DictionaryValue& value, int flags,
// Takes ownership of the manifest |value|.
bool InitFromValue(extensions::Manifest* value, int flags,
std::string* error);
// Helper function for implementing HasCachedImage/GetCachedImage. A return
......@@ -643,24 +645,21 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
UserScript *instance);
// Helpers to load various chunks of the manifest.
bool LoadIsApp(const base::DictionaryValue* manifest, std::string* error);
bool LoadExtent(const base::DictionaryValue* manifest,
bool LoadExtent(const extensions::Manifest* manifest,
const char* key,
URLPatternSet* extent,
const char* list_error,
const char* value_error,
URLPattern::ParseOption parse_strictness,
std::string* error);
bool LoadLaunchContainer(const base::DictionaryValue* manifest,
bool LoadLaunchContainer(const extensions::Manifest* manifest,
std::string* error);
bool LoadLaunchURL(const base::DictionaryValue* manifest,
bool LoadLaunchURL(const extensions::Manifest* manifest,
std::string* error);
bool LoadAppIsolation(const base::DictionaryValue* manifest,
bool LoadAppIsolation(const extensions::Manifest* manifest,
std::string* error);
bool LoadWebIntentServices(const base::DictionaryValue& manifest,
bool LoadWebIntentServices(const extensions::Manifest* manifest,
std::string* error);
bool EnsureNotHybridApp(const base::DictionaryValue* manifest,
std::string* error);
// Helper method to load an ExtensionAction from the page_action or
// browser_action entries in the manifest.
......@@ -683,10 +682,6 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// an extension that has a browser action and a page action.
bool HasMultipleUISurfaces() const;
// Figures out if a source contains keys not associated with themes - we
// don't want to allow scripts and such to be bundled with themes.
bool ContainsNonThemeKeys(const base::DictionaryValue& source) const;
// Updates the launch URL and extents for the extension using the given
// |override_url|.
void OverrideLaunchUrl(const GURL& override_url);
......@@ -820,9 +815,6 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// A map of display properties.
scoped_ptr<base::DictionaryValue> theme_display_properties_;
// Whether the extension is a theme.
bool is_theme_;
// The homepage for this extension. Useful if it is not hosted by Google and
// therefore does not have a Gallery URL.
GURL homepage_url_;
......@@ -830,19 +822,13 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// URL for fetching an update manifest
GURL update_url_;
// A copy of the manifest that this extension was created from.
scoped_ptr<base::DictionaryValue> manifest_value_;
// The manifest that this extension was created from.
scoped_ptr<extensions::Manifest> manifest_;
// A map of chrome:// hostnames (newtab, downloads, etc.) to Extension URLs
// which override the handling of those URLs. (see ExtensionOverrideUI).
URLOverrideMap chrome_url_overrides_;
// Whether this extension uses app features.
bool is_app_;
// Whether this app uses platform features.
bool is_platform_app_;
// Whether this extension requests isolated storage.
bool is_storage_isolated_;
......
......@@ -166,8 +166,8 @@ const char kExpectString[] = "Expect string value.";
const char kExperimentalFlagRequired[] =
"Loading extensions with 'experimental' permission requires"
" --enable-experimental-extension-apis command line flag.";
const char kHostedAppsCannotIncludeExtensionFeatures[] =
"Hosted apps cannot use the extension feature '*'.";
const char kFeatureNotAllowed[] =
"Feature '*' is not allowed in this type of manifest.";
const char kInvalidAllFrames[] =
"Invalid value for 'content_scripts[*].all_frames'.";
const char kInvalidBackground[] =
......@@ -429,8 +429,6 @@ const char kReservedMessageFound[] =
const char kSidebarExperimental[] =
"You must request the 'experimental' permission in order to use the"
" Sidebar API.";
const char kThemesCannotContainExtensions[] =
"A theme cannot contain extensions code.";
#if defined(OS_CHROMEOS)
const char kIllegalPlugins[] =
"Extensions cannot install plugins on Chrome OS";
......
......@@ -150,7 +150,7 @@ namespace extension_manifest_errors {
extern const char kDisabledByPolicy[];
extern const char kExperimentalFlagRequired[];
extern const char kExpectString[];
extern const char kHostedAppsCannotIncludeExtensionFeatures[];
extern const char kFeatureNotAllowed[];
extern const char kInvalidAllFrames[];
extern const char kInvalidBackground[];
extern const char kInvalidBackgroundInHostedApp[];
......@@ -280,7 +280,6 @@ namespace extension_manifest_errors {
extern const char kOneUISurfaceOnly[];
extern const char kReservedMessageFound[];
extern const char kSidebarExperimental[];
extern const char kThemesCannotContainExtensions[];
extern const char kWebContentMustBeEnabled[];
#if defined(OS_CHROMEOS)
extern const char kIllegalPlugins[];
......
......@@ -588,12 +588,8 @@ TEST_F(ExtensionManifestTest, Sidebar) {
extension->sidebar_defaults()->default_page().spec());
}
TEST_F(ExtensionManifestTest, DisallowHybridApps) {
LoadAndExpectError("disallow_hybrid_1.json",
ExtensionErrorUtils::FormatErrorMessage(
errors::kHostedAppsCannotIncludeExtensionFeatures,
keys::kBrowserAction));
LoadAndExpectError("disallow_hybrid_2.json",
TEST_F(ExtensionManifestTest, BackgroundPermission) {
LoadAndExpectError("background_permission.json",
errors::kBackgroundPermissionNeeded);
}
......@@ -742,9 +738,7 @@ TEST_F(ExtensionManifestTest, NormalizeIconPaths) {
}
TEST_F(ExtensionManifestTest, DisallowMultipleUISurfaces) {
LoadAndExpectError("multiple_ui_surfaces_1.json", errors::kOneUISurfaceOnly);
LoadAndExpectError("multiple_ui_surfaces_2.json", errors::kOneUISurfaceOnly);
LoadAndExpectError("multiple_ui_surfaces_3.json", errors::kOneUISurfaceOnly);
LoadAndExpectError("multiple_ui_surfaces.json", errors::kOneUISurfaceOnly);
}
TEST_F(ExtensionManifestTest, ParseHomepageURLs) {
......
......@@ -5,6 +5,7 @@
#include "chrome/common/extensions/extension_messages.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/manifest.h"
#include "content/public/common/common_param_traits.h"
ExtensionMsg_Loaded_Params::ExtensionMsg_Loaded_Params()
......@@ -49,10 +50,11 @@ ExtensionMsg_Loaded_Params::ExtensionMsg_Loaded_Params(
extension_manifest_keys::kVersion,
};
// Copy only the data we need.
// Copy only the data we need and bypass the manifest type checks.
DictionaryValue* source = extension->manifest()->value();
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRendererExtensionKeys); ++i) {
Value* temp = NULL;
if (extension->manifest_value()->Get(kRendererExtensionKeys[i], &temp))
if (source->Get(kRendererExtensionKeys[i], &temp))
manifest->Set(kRendererExtensionKeys[i], temp->DeepCopy());
}
}
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// 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.h"
#include "base/basictypes.h"
#include "base/lazy_instance.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;
namespace extensions {
namespace {
typedef std::map<std::string, int> RestrictionMap;
struct Restrictions {
Restrictions() {
// Base keys that all manifests can specify.
map[keys::kName] = Manifest::kTypeAll;
map[keys::kVersion] = Manifest::kTypeAll;
map[keys::kManifestVersion] = Manifest::kTypeAll;
map[keys::kDescription] = Manifest::kTypeAll;
map[keys::kIcons] = Manifest::kTypeAll;
map[keys::kCurrentLocale] = Manifest::kTypeAll;
map[keys::kDefaultLocale] = Manifest::kTypeAll;
map[keys::kSignature] = Manifest::kTypeAll;
map[keys::kUpdateURL] = Manifest::kTypeAll;
map[keys::kPublicKey] = Manifest::kTypeAll;
// Type specific.
map[keys::kApp] = Manifest::kTypeHostedApp | Manifest::kTypePackagedApp |
Manifest::kTypePlatformApp;
map[keys::kTheme] = Manifest::kTypeTheme;
// keys::kPlatformApp holds a boolean, so all types can define it.
map[keys::kPlatformApp] = Manifest::kTypeAll;
// Extensions only.
map[keys::kBrowserAction] = Manifest::kTypeExtension;
map[keys::kPageAction] = Manifest::kTypeExtension;
map[keys::kPageActions] = Manifest::kTypeExtension;
// Everything except themes.
int all_but_themes = Manifest::kTypeAll - Manifest::kTypeTheme;
map[keys::kPermissions] = all_but_themes;
map[keys::kOptionalPermissions] = all_but_themes;
map[keys::kOptionsPage] = all_but_themes;
map[keys::kBackground] = all_but_themes;
map[keys::kOfflineEnabled] = all_but_themes;
map[keys::kMinimumChromeVersion] = all_but_themes;
map[keys::kRequirements] = all_but_themes;
map[keys::kConvertedFromUserScript] = all_but_themes;
map[keys::kNaClModules] = all_but_themes;
map[keys::kPlugins] = all_but_themes;
// Extensions and packaged apps.
int ext_and_packaged =
Manifest::kTypeExtension | Manifest::kTypePackagedApp;
map[keys::kContentScripts] = ext_and_packaged;
map[keys::kOmnibox] = ext_and_packaged;
map[keys::kDevToolsPage] = ext_and_packaged;
map[keys::kSidebar] = ext_and_packaged;
map[keys::kHomepageURL] = ext_and_packaged;
map[keys::kChromeURLOverrides] = ext_and_packaged;
// Extensions, packaged apps and platform apps.
int local_apps_and_ext = ext_and_packaged | Manifest::kTypePlatformApp;
map[keys::kContentSecurityPolicy] = local_apps_and_ext;
map[keys::kFileBrowserHandlers] = local_apps_and_ext;
map[keys::kIncognito] = local_apps_and_ext;
map[keys::kInputComponents] = local_apps_and_ext;
map[keys::kTtsEngine] = local_apps_and_ext;
map[keys::kIntents] = local_apps_and_ext;
}
// Returns true if the |key| is recognized.
bool IsKnownKey(const std::string& key) const {
RestrictionMap::const_iterator i = map.find(key);
return i != map.end();
}
// Returns true if the given |key| can be specified by the manifest |type|.
bool CanAccessKey(const std::string& key, Manifest::Type type) const {
RestrictionMap::const_iterator i = map.find(key);
return (i != map.end() && (type & i->second) != 0);
}
RestrictionMap map;
};
base::LazyInstance<Restrictions> g_restrictions;
} // namespace
// static
std::set<std::string> Manifest::GetAllKnownKeys() {
std::set<std::string> keys;
const RestrictionMap& map = g_restrictions.Get().map;
for (RestrictionMap::const_iterator i = map.begin(); i != map.end(); i++)
keys.insert(i->first);
return keys;
}
Manifest::Manifest(DictionaryValue* value) : value_(value) {}
Manifest::~Manifest() {}
bool Manifest::ValidateManifest(std::string* error) const {
Restrictions restrictions = g_restrictions.Get();
Type type = GetType();
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 forward compatibility.
if (!restrictions.IsKnownKey(*key)) {
// TODO(aa): Consider having an error here in the case of strict error
// checking to let developers know when they screw up.
continue;
}
if (!restrictions.CanAccessKey(*key, type)) {
*error = ExtensionErrorUtils::FormatErrorMessage(
errors::kFeatureNotAllowed, *key);
return false;
}
}
return true;
}
bool Manifest::HasKey(const std::string& key) const {
Restrictions restrictions = g_restrictions.Get();
return restrictions.CanAccessKey(key, GetType()) && value_->HasKey(key);
}
bool Manifest::Get(
const std::string& path, Value** out_value) const {
return CanAccessPath(path) && value_->Get(path, out_value);
}
bool Manifest::GetBoolean(
const std::string& path, bool* out_value) const {
return CanAccessPath(path) && value_->GetBoolean(path, out_value);
}
bool Manifest::GetInteger(
const std::string& path, int* out_value) const {
return CanAccessPath(path) && value_->GetInteger(path, out_value);
}
bool Manifest::GetString(
const std::string& path, std::string* out_value) const {
return CanAccessPath(path) && value_->GetString(path, out_value);
}
bool Manifest::GetString(
const std::string& path, string16* out_value) const {
return CanAccessPath(path) && value_->GetString(path, out_value);
}
bool Manifest::GetDictionary(
const std::string& path, DictionaryValue** out_value) const {
return CanAccessPath(path) && value_->GetDictionary(path, out_value);
}
bool Manifest::GetList(
const std::string& path, ListValue** out_value) const {
return CanAccessPath(path) && value_->GetList(path, out_value);
}
Manifest* Manifest::DeepCopy() const {
return new Manifest(value_->DeepCopy());
}
bool Manifest::Equals(const Manifest* other) const {
return other && value_->Equals(other->value());
}
Manifest::Type Manifest::GetType() const {
if (value_->HasKey(keys::kTheme))
return kTypeTheme;
bool is_platform_app = false;
if (value_->GetBoolean(keys::kPlatformApp, &is_platform_app) &&
is_platform_app)
return kTypePlatformApp;
if (value_->HasKey(keys::kApp)) {
if (value_->Get(keys::kWebURLs, NULL) ||
value_->Get(keys::kLaunchWebURL, NULL))
return kTypeHostedApp;
else
return kTypePackagedApp;
} else {
return kTypeExtension;
}
}
bool Manifest::IsTheme() const {
return GetType() == kTypeTheme;
}
bool Manifest::IsPlatformApp() const {
return GetType() == kTypePlatformApp;
}
bool Manifest::IsPackagedApp() const {
return GetType() == kTypePackagedApp;
}
bool Manifest::IsHostedApp() const {
return GetType() == kTypeHostedApp;
}
bool Manifest::CanAccessPath(const std::string& path) const {
std::vector<std::string> components;
base::SplitString(path, '.', &components);
Restrictions restrictions = g_restrictions.Get();
return restrictions.CanAccessKey(components[0], GetType());
}
} // namespace extensions
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_COMMON_EXTENSIONS_MANIFEST_H_
#define CHROME_COMMON_EXTENSIONS_MANIFEST_H_
#pragma once
#include <map>
#include <string>
#include <set>
#include "base/memory/scoped_ptr.h"
#include "base/string16.h"
namespace base {
class DictionaryValue;
class ListValue;
class Value;
}
namespace extensions {
// Lightweight wrapper around a DictionaryValue representing an extension's
// manifest. Currently enforces access to properties of the manifest based
// on manifest type.
//
// TODO(aa): Move more smarts about mmanifest into this class over time.
class Manifest {
public:
// Flags for matching types of extension manifests.
enum Type {
kTypeNone = 0,
// Extension::TYPE_EXTENSION and Extension::TYPE_USER_SCRIPT
kTypeExtension = 1 << 0,
// Extension::TYPE_THEME
kTypeTheme = 1 << 1,
// Extension::TYPE_HOSTED_APP
kTypeHostedApp = 1 << 2,
// Extension::TYPE_PACKAGED_APP
kTypePackagedApp = 1 << 3,
// Extension::TYPE_PLATFORM_APP
kTypePlatformApp = 1 << 4,
// All types
kTypeAll = (1 << 5) - 1,
};
// Returns all known keys (this is used for testing).
static std::set<std::string> GetAllKnownKeys();
// Takes over ownership of |value|.
explicit Manifest(base::DictionaryValue* value);
virtual ~Manifest();
// Returns true if all keys in the manifest can be specified by
// the extension type.
bool ValidateManifest(std::string* error) const;
// Returns the manifest type.
Type GetType() const;
// Returns true if the manifest represents an Extension::TYPE_THEME.
bool IsTheme() const;
// Returns true for Extension::TYPE_PLATFORM_APP
bool IsPlatformApp() const;
// Returns true for Extension::TYPE_PACKAGED_APP.
bool IsPackagedApp() const;
// Returns true for Extension::TYPE_HOSTED_APP.
bool IsHostedApp() const;
// These access the wrapped manifest value, returning false when the property
// does not exist or if the manifest type can't access it.
bool HasKey(const std::string& key) const;
bool Get(const std::string& path, base::Value** out_value) const;
bool GetBoolean(const std::string& path, bool* out_value) const;
bool GetInteger(const std::string& path, int* out_value) const;
bool GetString(const std::string& path, std::string* out_value) const;
bool GetString(const std::string& path, string16* out_value) const;
bool GetDictionary(const std::string& path,
base::DictionaryValue** out_value) const;
bool GetList(const std::string& path, base::ListValue** out_value) const;
// Returns a new Manifest equal to this one, passing ownership to
// the caller.
Manifest* DeepCopy() const;
// Returns true if this equals the |other| manifest.
bool Equals(const Manifest* other) const;
// Gets the underlying DictionaryValue representing the manifest.
// Note: only know this when you KNOW you don't need the validation.
base::DictionaryValue* value() const { return value_.get(); }
private:
// Returns true if the extension can specify the given |path|.
bool CanAccessPath(const std::string& path) const;
scoped_ptr<base::DictionaryValue> value_;
};
} // namespace extensions
#endif // CHROME_COMMON_EXTENSIONS_MANIFEST_H_
This diff is collapsed.
......@@ -12,6 +12,7 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension_messages.h"
#include "chrome/common/extensions/extension_set.h"
#include "chrome/common/extensions/manifest.h"
#include "chrome/renderer/extensions/chrome_v8_context.h"
#include "chrome/renderer/extensions/extension_dispatcher.h"
#include "chrome/renderer/extensions/extension_helper.h"
......@@ -194,7 +195,7 @@ v8::Handle<v8::Value> AppBindingsHandler::GetDetailsForFrameImpl(
return v8::Null();
scoped_ptr<DictionaryValue> manifest_copy(
extension->manifest_value()->DeepCopy());
extension->manifest()->value()->DeepCopy());
manifest_copy->SetString("id", extension->id());
scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
return converter->ToV8Value(manifest_copy.get(),
......
{
"name": "test",
"version": "1",
"app": {
"urls": [
"http://www.google.com/mail/",
"http://www.google.com/foobar/"
],
"launch": {
"web_url": "http://www.google.com/mail/"
}
},
"permissions": [
"notifications"
],
"browser_action": {}
}
{
"name": "foo",
"version": "1",
"browser_action": {},
"app": {
"launch": {
"local_path": "foo.html"
}
}
}
{
"name": "foo",
"version": "1",
"browser_action": {},
"page_action": {},
"app": {
"launch": {
"local_path": "foo.html"
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment