summaryrefslogtreecommitdiffstats
path: root/chrome/common
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/common')
-rw-r--r--chrome/common/extensions/extension.cc299
-rw-r--r--chrome/common/extensions/extension.h30
-rw-r--r--chrome/common/extensions/extension_file_util.cc64
-rw-r--r--chrome/common/extensions/extension_file_util_unittest.cc2
-rw-r--r--chrome/common/extensions/extension_unittest.cc38
-rw-r--r--chrome/common/extensions/manifest_handlers/content_scripts_handler.cc446
-rw-r--r--chrome/common/extensions/manifest_handlers/content_scripts_handler.h51
-rw-r--r--chrome/common/extensions/manifest_handlers/content_scripts_manifest_unittest.cc (renamed from chrome/common/extensions/manifest_tests/extension_manifests_contentscript_unittest.cc)32
-rw-r--r--chrome/common/extensions/manifest_handlers/exclude_matches_manifest_unittest.cc (renamed from chrome/common/extensions/manifest_tests/extension_manifests_excludematches_unittest.cc)19
-rw-r--r--chrome/common/extensions/manifest_tests/extension_manifests_initvalue_unittest.cc2
-rw-r--r--chrome/common/extensions/permissions/permission_set.cc6
-rw-r--r--chrome/common/extensions/permissions/permission_set_unittest.cc4
12 files changed, 586 insertions, 407 deletions
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index fe25d22..a83392e 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -979,15 +979,6 @@ bool Extension::ShouldDisplayInExtensionSettings() const {
return true;
}
-bool Extension::HasContentScriptAtURL(const GURL& url) const {
- for (UserScriptList::const_iterator it = content_scripts_.begin();
- it != content_scripts_.end(); ++it) {
- if (it->MatchesURL(url))
- return true;
- }
- return false;
-}
-
scoped_refptr<const PermissionSet> Extension::GetTabSpecificPermissions(
int tab_id) const {
base::AutoLock auto_lock(runtime_data_lock_);
@@ -1927,46 +1918,13 @@ bool Extension::LoadExtensionFeatures(string16* error) {
manifest_->GetBoolean(keys::kConvertedFromUserScript,
&converted_from_user_script_);
- if (!LoadContentScripts(error) ||
- !LoadSystemIndicator(error) ||
+ if (!LoadSystemIndicator(error) ||
!LoadIncognitoMode(error))
return false;
return true;
}
-bool Extension::LoadContentScripts(string16* error) {
- if (!manifest_->HasKey(keys::kContentScripts))
- return true;
-
- const ListValue* list_value;
- if (!manifest_->GetList(keys::kContentScripts, &list_value)) {
- *error = ASCIIToUTF16(errors::kInvalidContentScriptsList);
- return false;
- }
-
- for (size_t i = 0; i < list_value->GetSize(); ++i) {
- const DictionaryValue* content_script = NULL;
- if (!list_value->GetDictionary(i, &content_script)) {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidContentScript, base::IntToString(i));
- return false;
- }
-
- UserScript script;
- if (!LoadUserScriptHelper(content_script, i, error, &script))
- return false; // Failed to parse script context definition.
-
- script.set_extension_id(id());
- if (converted_from_user_script_) {
- script.set_emulate_greasemonkey(true);
- script.set_match_all_frames(true); // Greasemonkey matches all frames.
- }
- content_scripts_.push_back(script);
- }
- return true;
-}
-
bool Extension::LoadSystemIndicator(string16* error) {
if (!manifest_->HasKey(keys::kSystemIndicator)) {
// There was no manifest entry for the system indicator.
@@ -2015,261 +1973,6 @@ bool Extension::LoadIncognitoMode(string16* error) {
return true;
}
-// Helper method that loads a UserScript object from a dictionary in the
-// content_script list of the manifest.
-bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script,
- int definition_index,
- string16* error,
- UserScript* result) {
- // run_at
- if (content_script->HasKey(keys::kRunAt)) {
- std::string run_location;
- if (!content_script->GetString(keys::kRunAt, &run_location)) {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidRunAt,
- base::IntToString(definition_index));
- return false;
- }
-
- if (run_location == values::kRunAtDocumentStart) {
- result->set_run_location(UserScript::DOCUMENT_START);
- } else if (run_location == values::kRunAtDocumentEnd) {
- result->set_run_location(UserScript::DOCUMENT_END);
- } else if (run_location == values::kRunAtDocumentIdle) {
- result->set_run_location(UserScript::DOCUMENT_IDLE);
- } else {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidRunAt,
- base::IntToString(definition_index));
- return false;
- }
- }
-
- // all frames
- if (content_script->HasKey(keys::kAllFrames)) {
- bool all_frames = false;
- if (!content_script->GetBoolean(keys::kAllFrames, &all_frames)) {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidAllFrames, base::IntToString(definition_index));
- return false;
- }
- result->set_match_all_frames(all_frames);
- }
-
- // matches (required)
- const ListValue* matches = NULL;
- if (!content_script->GetList(keys::kMatches, &matches)) {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidMatches,
- base::IntToString(definition_index));
- return false;
- }
-
- if (matches->GetSize() == 0) {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidMatchCount,
- base::IntToString(definition_index));
- return false;
- }
- for (size_t j = 0; j < matches->GetSize(); ++j) {
- std::string match_str;
- if (!matches->GetString(j, &match_str)) {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidMatch,
- base::IntToString(definition_index),
- base::IntToString(j),
- errors::kExpectString);
- return false;
- }
-
- URLPattern pattern(
- UserScript::ValidUserScriptSchemes(CanExecuteScriptEverywhere()));
-
- URLPattern::ParseResult parse_result = pattern.Parse(match_str);
- if (parse_result != URLPattern::PARSE_SUCCESS) {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidMatch,
- base::IntToString(definition_index),
- base::IntToString(j),
- URLPattern::GetParseResultString(parse_result));
- return false;
- }
-
- // TODO(aboxhall): check for webstore
- if (!CanExecuteScriptEverywhere() &&
- pattern.scheme() != chrome::kChromeUIScheme) {
- // Exclude SCHEME_CHROMEUI unless it's been explicitly requested.
- // If the --extensions-on-chrome-urls flag has not been passed, requesting
- // a chrome:// url will cause a parse failure above, so there's no need to
- // check the flag here.
- pattern.SetValidSchemes(
- pattern.valid_schemes() & ~URLPattern::SCHEME_CHROMEUI);
- }
-
- if (pattern.MatchesScheme(chrome::kFileScheme) &&
- !CanExecuteScriptEverywhere()) {
- wants_file_access_ = true;
- if (!(creation_flags_ & ALLOW_FILE_ACCESS)) {
- pattern.SetValidSchemes(
- pattern.valid_schemes() & ~URLPattern::SCHEME_FILE);
- }
- }
-
- result->add_url_pattern(pattern);
- }
-
- // exclude_matches
- if (content_script->HasKey(keys::kExcludeMatches)) { // optional
- const ListValue* exclude_matches = NULL;
- if (!content_script->GetList(keys::kExcludeMatches, &exclude_matches)) {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidExcludeMatches,
- base::IntToString(definition_index));
- return false;
- }
-
- for (size_t j = 0; j < exclude_matches->GetSize(); ++j) {
- std::string match_str;
- if (!exclude_matches->GetString(j, &match_str)) {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidExcludeMatch,
- base::IntToString(definition_index),
- base::IntToString(j),
- errors::kExpectString);
- return false;
- }
-
- int valid_schemes =
- UserScript::ValidUserScriptSchemes(CanExecuteScriptEverywhere());
- URLPattern pattern(valid_schemes);
- URLPattern::ParseResult parse_result = pattern.Parse(match_str);
- if (parse_result != URLPattern::PARSE_SUCCESS) {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidExcludeMatch,
- base::IntToString(definition_index), base::IntToString(j),
- URLPattern::GetParseResultString(parse_result));
- return false;
- }
-
- result->add_exclude_url_pattern(pattern);
- }
- }
-
- // include/exclude globs (mostly for Greasemonkey compatibility)
- if (!LoadGlobsHelper(content_script, definition_index, keys::kIncludeGlobs,
- error, &UserScript::add_glob, result)) {
- return false;
- }
-
- if (!LoadGlobsHelper(content_script, definition_index, keys::kExcludeGlobs,
- error, &UserScript::add_exclude_glob, result)) {
- return false;
- }
-
- // js and css keys
- const ListValue* js = NULL;
- if (content_script->HasKey(keys::kJs) &&
- !content_script->GetList(keys::kJs, &js)) {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidJsList,
- base::IntToString(definition_index));
- return false;
- }
-
- const ListValue* css = NULL;
- if (content_script->HasKey(keys::kCss) &&
- !content_script->GetList(keys::kCss, &css)) {
- *error = ErrorUtils::
- FormatErrorMessageUTF16(errors::kInvalidCssList,
- base::IntToString(definition_index));
- return false;
- }
-
- // The manifest needs to have at least one js or css user script definition.
- if (((js ? js->GetSize() : 0) + (css ? css->GetSize() : 0)) == 0) {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kMissingFile,
- base::IntToString(definition_index));
- return false;
- }
-
- if (js) {
- for (size_t script_index = 0; script_index < js->GetSize();
- ++script_index) {
- const Value* value;
- std::string relative;
- if (!js->Get(script_index, &value) || !value->GetAsString(&relative)) {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidJs,
- base::IntToString(definition_index),
- base::IntToString(script_index));
- return false;
- }
- GURL url = GetResourceURL(relative);
- ExtensionResource resource = GetResource(relative);
- result->js_scripts().push_back(UserScript::File(
- resource.extension_root(), resource.relative_path(), url));
- }
- }
-
- if (css) {
- for (size_t script_index = 0; script_index < css->GetSize();
- ++script_index) {
- const Value* value;
- std::string relative;
- if (!css->Get(script_index, &value) || !value->GetAsString(&relative)) {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidCss,
- base::IntToString(definition_index),
- base::IntToString(script_index));
- return false;
- }
- GURL url = GetResourceURL(relative);
- ExtensionResource resource = GetResource(relative);
- result->css_scripts().push_back(UserScript::File(
- resource.extension_root(), resource.relative_path(), url));
- }
- }
-
- return true;
-}
-
-bool Extension::LoadGlobsHelper(
- const DictionaryValue* content_script,
- int content_script_index,
- const char* globs_property_name,
- string16* error,
- void(UserScript::*add_method)(const std::string& glob),
- UserScript* instance) {
- if (!content_script->HasKey(globs_property_name))
- return true; // they are optional
-
- const ListValue* list = NULL;
- if (!content_script->GetList(globs_property_name, &list)) {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidGlobList,
- base::IntToString(content_script_index),
- globs_property_name);
- return false;
- }
-
- for (size_t i = 0; i < list->GetSize(); ++i) {
- std::string glob;
- if (!list->GetString(i, &glob)) {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidGlob,
- base::IntToString(content_script_index),
- globs_property_name,
- base::IntToString(i));
- return false;
- }
-
- (instance->*add_method)(glob);
- }
-
- return true;
-}
-
bool Extension::HasMultipleUISurfaces() const {
int num_surfaces = 0;
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index 53e3a8f..86f7f96 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -386,9 +386,6 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// settings page (i.e. chrome://extensions).
bool ShouldDisplayInExtensionSettings() const;
- // Returns true if the extension has a content script declared at |url|.
- bool HasContentScriptAtURL(const GURL& url) const;
-
// Gets the tab-specific host permissions of |tab_id|, or NULL if there
// aren't any.
scoped_refptr<const PermissionSet> GetTabSpecificPermissions(int tab_id)
@@ -432,7 +429,6 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
bool converted_from_user_script() const {
return converted_from_user_script_;
}
- const UserScriptList& content_scripts() const { return content_scripts_; }
const ActionInfo* system_indicator_info() const {
return system_indicator_info_.get();
}
@@ -466,6 +462,12 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
bool kiosk_enabled() const { return kiosk_enabled_; }
bool offline_enabled() const { return offline_enabled_; }
bool wants_file_access() const { return wants_file_access_; }
+ // TODO(rdevlin.cronin): This is needed for ContentScriptsHandler, and should
+ // be moved out as part of crbug.com/159265. This should not be used anywhere
+ // else.
+ void set_wants_file_access(bool wants_file_access) {
+ wants_file_access_ = wants_file_access;
+ }
int creation_flags() const { return creation_flags_; }
bool from_webstore() const { return (creation_flags_ & FROM_WEBSTORE) != 0; }
bool from_bookmark() const { return (creation_flags_ & FROM_BOOKMARK) != 0; }
@@ -578,7 +580,6 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
bool LoadKioskEnabled(string16* error);
bool LoadOfflineEnabled(string16* error);
bool LoadExtensionFeatures(string16* error);
- bool LoadContentScripts(string16* error);
bool LoadBrowserAction(string16* error);
bool LoadSystemIndicator(string16* error);
bool LoadTextToSpeechVoices(string16* error);
@@ -591,22 +592,6 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
const base::DictionaryValue* content_pack_value,
string16* error);
- // Helper method that loads a UserScript object from a
- // dictionary in the content_script list of the manifest.
- bool LoadUserScriptHelper(const base::DictionaryValue* content_script,
- int definition_index,
- string16* error,
- UserScript* result);
-
- // Helper method that loads either the include_globs or exclude_globs list
- // from an entry in the content_script lists of the manifest.
- bool LoadGlobsHelper(const base::DictionaryValue* content_script,
- int content_script_index,
- const char* globs_property_name,
- string16* error,
- void(UserScript::*add_method)(const std::string& glob),
- UserScript* instance);
-
// Returns true if the extension has more than one "UI surface". For example,
// an extension that has a browser action and a page action.
bool HasMultipleUISurfaces() const;
@@ -699,9 +684,6 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// different UI if so).
bool converted_from_user_script_;
- // Paths to the content scripts the extension contains.
- UserScriptList content_scripts_;
-
// The extension's system indicator, if any.
scoped_ptr<ActionInfo> system_indicator_info_;
diff --git a/chrome/common/extensions/extension_file_util.cc b/chrome/common/extensions/extension_file_util.cc
index 1ed7356..4c2fbb0 100644
--- a/chrome/common/extensions/extension_file_util.cc
+++ b/chrome/common/extensions/extension_file_util.cc
@@ -49,12 +49,6 @@ const base::FilePath::CharType kTempDirectoryName[] = FILE_PATH_LITERAL("Temp");
namespace extension_file_util {
-// Returns false and sets the error if script file can't be loaded,
-// or if it's not UTF-8 encoded.
-static bool IsScriptValid(const base::FilePath& path,
- const base::FilePath& relative_path,
- int message_id, std::string* error);
-
base::FilePath InstallExtension(const base::FilePath& unpacked_source_dir,
const std::string& id,
const std::string& version,
@@ -254,41 +248,6 @@ bool ValidateExtension(const Extension* extension,
extension, error, warnings))
return false;
- // TODO(yoz): Move this to content scripts manifest handler.
- // Validate that claimed script resources actually exist,
- // and are UTF-8 encoded.
- ExtensionResource::SymlinkPolicy symlink_policy;
- if ((extension->creation_flags() &
- Extension::FOLLOW_SYMLINKS_ANYWHERE) != 0) {
- symlink_policy = ExtensionResource::FOLLOW_SYMLINKS_ANYWHERE;
- } else {
- symlink_policy = ExtensionResource::SYMLINKS_MUST_RESOLVE_WITHIN_ROOT;
- }
-
- for (size_t i = 0; i < extension->content_scripts().size(); ++i) {
- const extensions::UserScript& script = extension->content_scripts()[i];
-
- for (size_t j = 0; j < script.js_scripts().size(); j++) {
- const extensions::UserScript::File& js_script = script.js_scripts()[j];
- const base::FilePath& path = ExtensionResource::GetFilePath(
- js_script.extension_root(), js_script.relative_path(),
- symlink_policy);
- if (!IsScriptValid(path, js_script.relative_path(),
- IDS_EXTENSION_LOAD_JAVASCRIPT_FAILED, error))
- return false;
- }
-
- for (size_t j = 0; j < script.css_scripts().size(); j++) {
- const extensions::UserScript::File& css_script = script.css_scripts()[j];
- const base::FilePath& path = ExtensionResource::GetFilePath(
- css_script.extension_root(), css_script.relative_path(),
- symlink_policy);
- if (!IsScriptValid(path, css_script.relative_path(),
- IDS_EXTENSION_LOAD_CSS_FAILED, error))
- return false;
- }
- }
-
// Check children of extension root to see if any of them start with _ and is
// not on the reserved list.
if (!CheckForIllegalFilenames(extension->path(), error)) {
@@ -452,29 +411,6 @@ SubstitutionMap* LoadMessageBundleSubstitutionMap(
return returnValue;
}
-static bool IsScriptValid(const base::FilePath& path,
- const base::FilePath& relative_path,
- int message_id,
- std::string* error) {
- std::string content;
- if (!file_util::PathExists(path) ||
- !file_util::ReadFileToString(path, &content)) {
- *error = l10n_util::GetStringFUTF8(
- message_id,
- relative_path.LossyDisplayName());
- return false;
- }
-
- if (!IsStringUTF8(content)) {
- *error = l10n_util::GetStringFUTF8(
- IDS_EXTENSION_BAD_FILE_ENCODING,
- relative_path.LossyDisplayName());
- return false;
- }
-
- return true;
-}
-
bool CheckForIllegalFilenames(const base::FilePath& extension_path,
std::string* error) {
// Reserved underscore names.
diff --git a/chrome/common/extensions/extension_file_util_unittest.cc b/chrome/common/extensions/extension_file_util_unittest.cc
index db0e38b..cb9260f 100644
--- a/chrome/common/extensions/extension_file_util_unittest.cc
+++ b/chrome/common/extensions/extension_file_util_unittest.cc
@@ -20,6 +20,7 @@
#include "chrome/common/extensions/extension_manifest_constants.h"
#include "chrome/common/extensions/manifest.h"
#include "chrome/common/extensions/manifest_handler.h"
+#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
#include "extensions/common/constants.h"
#include "grit/generated_resources.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -40,6 +41,7 @@ class ExtensionFileUtilTest : public testing::Test {
(new extensions::DefaultLocaleHandler)->Register();
(new extensions::IconsHandler)->Register();
(new extensions::PageActionHandler)->Register();
+ (new extensions::ContentScriptsHandler)->Register();
}
virtual void TearDown() OVERRIDE {
diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc
index 8f01536..696de8b 100644
--- a/chrome/common/extensions/extension_unittest.cc
+++ b/chrome/common/extensions/extension_unittest.cc
@@ -24,6 +24,7 @@
#include "chrome/common/extensions/features/feature.h"
#include "chrome/common/extensions/manifest.h"
#include "chrome/common/extensions/manifest_handler.h"
+#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
#include "chrome/common/extensions/permissions/api_permission.h"
#include "chrome/common/extensions/permissions/permission_set.h"
#include "chrome/common/extensions/permissions/socket_permission.h"
@@ -109,6 +110,7 @@ class ExtensionTest : public testing::Test {
testing::Test::SetUp();
(new BackgroundManifestHandler)->Register();
(new CommandsHandler)->Register();
+ (new ContentScriptsHandler)->Register();
(new PluginsHandler)->Register();
}
@@ -479,34 +481,58 @@ TEST_F(ExtensionTest, WantsFileAccess) {
extension = LoadManifest("permissions", "content_script_all_urls.json");
EXPECT_TRUE(extension->wants_file_access());
EXPECT_FALSE(extension->CanExecuteScriptOnPage(
- file_url, file_url, -1, &extension->content_scripts()[0], NULL));
+ file_url,
+ file_url,
+ -1,
+ &ContentScriptsInfo::GetContentScripts(extension)[0],
+ NULL));
extension = LoadManifest("permissions", "content_script_all_urls.json",
Extension::ALLOW_FILE_ACCESS);
EXPECT_TRUE(extension->wants_file_access());
EXPECT_TRUE(extension->CanExecuteScriptOnPage(
- file_url, file_url, -1, &extension->content_scripts()[0], NULL));
+ file_url,
+ file_url,
+ -1,
+ &ContentScriptsInfo::GetContentScripts(extension)[0],
+ NULL));
// file:///* content script match
extension = LoadManifest("permissions", "content_script_file_scheme.json");
EXPECT_TRUE(extension->wants_file_access());
EXPECT_FALSE(extension->CanExecuteScriptOnPage(
- file_url, file_url, -1, &extension->content_scripts()[0], NULL));
+ file_url,
+ file_url,
+ -1,
+ &ContentScriptsInfo::GetContentScripts(extension)[0],
+ NULL));
extension = LoadManifest("permissions", "content_script_file_scheme.json",
Extension::ALLOW_FILE_ACCESS);
EXPECT_TRUE(extension->wants_file_access());
EXPECT_TRUE(extension->CanExecuteScriptOnPage(
- file_url, file_url, -1, &extension->content_scripts()[0], NULL));
+ file_url,
+ file_url,
+ -1,
+ &ContentScriptsInfo::GetContentScripts(extension)[0],
+ NULL));
// http://* content script match
extension = LoadManifest("permissions", "content_script_http_scheme.json");
EXPECT_FALSE(extension->wants_file_access());
EXPECT_FALSE(extension->CanExecuteScriptOnPage(
- file_url, file_url, -1, &extension->content_scripts()[0], NULL));
+ file_url,
+ file_url,
+ -1,
+ &ContentScriptsInfo::GetContentScripts(extension)[0],
+ NULL));
extension = LoadManifest("permissions", "content_script_http_scheme.json",
Extension::ALLOW_FILE_ACCESS);
EXPECT_FALSE(extension->wants_file_access());
EXPECT_FALSE(extension->CanExecuteScriptOnPage(
- file_url, file_url, -1, &extension->content_scripts()[0], NULL));
+ file_url,
+ file_url,
+ -1,
+ &ContentScriptsInfo::GetContentScripts(extension)[0],
+ NULL));
}
TEST_F(ExtensionTest, ExtraFlags) {
diff --git a/chrome/common/extensions/manifest_handlers/content_scripts_handler.cc b/chrome/common/extensions/manifest_handlers/content_scripts_handler.cc
new file mode 100644
index 0000000..a2edb9a
--- /dev/null
+++ b/chrome/common/extensions/manifest_handlers/content_scripts_handler.cc
@@ -0,0 +1,446 @@
+// Copyright (c) 2013 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_handlers/content_scripts_handler.h"
+
+#include "base/file_util.h"
+#include "base/lazy_instance.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_manifest_constants.h"
+#include "content/public/common/url_constants.h"
+#include "extensions/common/error_utils.h"
+#include "extensions/common/extension_resource.h"
+#include "extensions/common/url_pattern.h"
+#include "googleurl/src/gurl.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace extensions {
+
+namespace keys = extension_manifest_keys;
+namespace values = extension_manifest_values;
+namespace errors = extension_manifest_errors;
+
+namespace {
+
+// Helper method that loads either the include_globs or exclude_globs list
+// from an entry in the content_script lists of the manifest.
+bool LoadGlobsHelper(const DictionaryValue* content_script,
+ int content_script_index,
+ const char* globs_property_name,
+ string16* error,
+ void(UserScript::*add_method)(const std::string& glob),
+ UserScript* instance) {
+ if (!content_script->HasKey(globs_property_name))
+ return true; // they are optional
+
+ const ListValue* list = NULL;
+ if (!content_script->GetList(globs_property_name, &list)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidGlobList,
+ base::IntToString(content_script_index),
+ globs_property_name);
+ return false;
+ }
+
+ for (size_t i = 0; i < list->GetSize(); ++i) {
+ std::string glob;
+ if (!list->GetString(i, &glob)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidGlob,
+ base::IntToString(content_script_index),
+ globs_property_name,
+ base::IntToString(i));
+ return false;
+ }
+
+ (instance->*add_method)(glob);
+ }
+
+ return true;
+}
+
+// Helper method that loads a UserScript object from a dictionary in the
+// content_script list of the manifest.
+bool LoadUserScriptFromDictionary(const DictionaryValue* content_script,
+ int definition_index,
+ Extension* extension,
+ string16* error,
+ UserScript* result) {
+ // run_at
+ if (content_script->HasKey(keys::kRunAt)) {
+ std::string run_location;
+ if (!content_script->GetString(keys::kRunAt, &run_location)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidRunAt,
+ base::IntToString(definition_index));
+ return false;
+ }
+
+ if (run_location == values::kRunAtDocumentStart) {
+ result->set_run_location(UserScript::DOCUMENT_START);
+ } else if (run_location == values::kRunAtDocumentEnd) {
+ result->set_run_location(UserScript::DOCUMENT_END);
+ } else if (run_location == values::kRunAtDocumentIdle) {
+ result->set_run_location(UserScript::DOCUMENT_IDLE);
+ } else {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidRunAt,
+ base::IntToString(definition_index));
+ return false;
+ }
+ }
+
+ // all frames
+ if (content_script->HasKey(keys::kAllFrames)) {
+ bool all_frames = false;
+ if (!content_script->GetBoolean(keys::kAllFrames, &all_frames)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidAllFrames, base::IntToString(definition_index));
+ return false;
+ }
+ result->set_match_all_frames(all_frames);
+ }
+
+ // matches (required)
+ const ListValue* matches = NULL;
+ if (!content_script->GetList(keys::kMatches, &matches)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidMatches,
+ base::IntToString(definition_index));
+ return false;
+ }
+
+ if (matches->GetSize() == 0) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidMatchCount,
+ base::IntToString(definition_index));
+ return false;
+ }
+ for (size_t j = 0; j < matches->GetSize(); ++j) {
+ std::string match_str;
+ if (!matches->GetString(j, &match_str)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidMatch,
+ base::IntToString(definition_index),
+ base::IntToString(j),
+ errors::kExpectString);
+ return false;
+ }
+
+ URLPattern pattern(UserScript::ValidUserScriptSchemes(
+ extension->CanExecuteScriptEverywhere()));
+
+ URLPattern::ParseResult parse_result = pattern.Parse(match_str);
+ if (parse_result != URLPattern::PARSE_SUCCESS) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidMatch,
+ base::IntToString(definition_index),
+ base::IntToString(j),
+ URLPattern::GetParseResultString(parse_result));
+ return false;
+ }
+
+ // TODO(aboxhall): check for webstore
+ if (!extension->CanExecuteScriptEverywhere() &&
+ pattern.scheme() != chrome::kChromeUIScheme) {
+ // Exclude SCHEME_CHROMEUI unless it's been explicitly requested.
+ // If the --extensions-on-chrome-urls flag has not been passed, requesting
+ // a chrome:// url will cause a parse failure above, so there's no need to
+ // check the flag here.
+ pattern.SetValidSchemes(
+ pattern.valid_schemes() & ~URLPattern::SCHEME_CHROMEUI);
+ }
+
+ if (pattern.MatchesScheme(chrome::kFileScheme) &&
+ !extension->CanExecuteScriptEverywhere()) {
+ extension->set_wants_file_access(true);
+ if (!(extension->creation_flags() & Extension::ALLOW_FILE_ACCESS)) {
+ pattern.SetValidSchemes(
+ pattern.valid_schemes() & ~URLPattern::SCHEME_FILE);
+ }
+ }
+
+ result->add_url_pattern(pattern);
+ }
+
+ // exclude_matches
+ if (content_script->HasKey(keys::kExcludeMatches)) { // optional
+ const ListValue* exclude_matches = NULL;
+ if (!content_script->GetList(keys::kExcludeMatches, &exclude_matches)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidExcludeMatches,
+ base::IntToString(definition_index));
+ return false;
+ }
+
+ for (size_t j = 0; j < exclude_matches->GetSize(); ++j) {
+ std::string match_str;
+ if (!exclude_matches->GetString(j, &match_str)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidExcludeMatch,
+ base::IntToString(definition_index),
+ base::IntToString(j),
+ errors::kExpectString);
+ return false;
+ }
+
+ int valid_schemes = UserScript::ValidUserScriptSchemes(
+ extension->CanExecuteScriptEverywhere());
+ URLPattern pattern(valid_schemes);
+
+ URLPattern::ParseResult parse_result = pattern.Parse(match_str);
+ if (parse_result != URLPattern::PARSE_SUCCESS) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidExcludeMatch,
+ base::IntToString(definition_index), base::IntToString(j),
+ URLPattern::GetParseResultString(parse_result));
+ return false;
+ }
+
+ result->add_exclude_url_pattern(pattern);
+ }
+ }
+
+ // include/exclude globs (mostly for Greasemonkey compatibility)
+ if (!LoadGlobsHelper(content_script, definition_index, keys::kIncludeGlobs,
+ error, &UserScript::add_glob, result)) {
+ return false;
+ }
+
+ if (!LoadGlobsHelper(content_script, definition_index, keys::kExcludeGlobs,
+ error, &UserScript::add_exclude_glob, result)) {
+ return false;
+ }
+
+ // js and css keys
+ const ListValue* js = NULL;
+ if (content_script->HasKey(keys::kJs) &&
+ !content_script->GetList(keys::kJs, &js)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidJsList,
+ base::IntToString(definition_index));
+ return false;
+ }
+
+ const ListValue* css = NULL;
+ if (content_script->HasKey(keys::kCss) &&
+ !content_script->GetList(keys::kCss, &css)) {
+ *error = ErrorUtils::
+ FormatErrorMessageUTF16(errors::kInvalidCssList,
+ base::IntToString(definition_index));
+ return false;
+ }
+
+ // The manifest needs to have at least one js or css user script definition.
+ if (((js ? js->GetSize() : 0) + (css ? css->GetSize() : 0)) == 0) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kMissingFile,
+ base::IntToString(definition_index));
+ return false;
+ }
+
+ if (js) {
+ for (size_t script_index = 0; script_index < js->GetSize();
+ ++script_index) {
+ const Value* value;
+ std::string relative;
+ if (!js->Get(script_index, &value) || !value->GetAsString(&relative)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidJs,
+ base::IntToString(definition_index),
+ base::IntToString(script_index));
+ return false;
+ }
+ GURL url = extension->GetResourceURL(relative);
+ ExtensionResource resource = extension->GetResource(relative);
+ result->js_scripts().push_back(UserScript::File(
+ resource.extension_root(), resource.relative_path(), url));
+ }
+ }
+
+ if (css) {
+ for (size_t script_index = 0; script_index < css->GetSize();
+ ++script_index) {
+ const Value* value;
+ std::string relative;
+ if (!css->Get(script_index, &value) || !value->GetAsString(&relative)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidCss,
+ base::IntToString(definition_index),
+ base::IntToString(script_index));
+ return false;
+ }
+ GURL url = extension->GetResourceURL(relative);
+ ExtensionResource resource = extension->GetResource(relative);
+ result->css_scripts().push_back(UserScript::File(
+ resource.extension_root(), resource.relative_path(), url));
+ }
+ }
+
+ return true;
+}
+
+// Returns false and sets the error if script file can't be loaded,
+// or if it's not UTF-8 encoded.
+static bool IsScriptValid(const base::FilePath& path,
+ const base::FilePath& relative_path,
+ int message_id,
+ std::string* error) {
+ std::string content;
+ if (!file_util::PathExists(path) ||
+ !file_util::ReadFileToString(path, &content)) {
+ *error = l10n_util::GetStringFUTF8(
+ message_id,
+ relative_path.LossyDisplayName());
+ return false;
+ }
+
+ if (!IsStringUTF8(content)) {
+ *error = l10n_util::GetStringFUTF8(
+ IDS_EXTENSION_BAD_FILE_ENCODING,
+ relative_path.LossyDisplayName());
+ return false;
+ }
+
+ return true;
+}
+
+struct EmptyUserScriptList {
+ UserScriptList user_script_list;
+};
+
+static base::LazyInstance<EmptyUserScriptList> g_empty_script_list =
+ LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+ContentScriptsInfo::ContentScriptsInfo() {
+}
+
+ContentScriptsInfo::~ContentScriptsInfo() {
+}
+
+// static
+const UserScriptList& ContentScriptsInfo::GetContentScripts(
+ const Extension* extension) {
+ ContentScriptsInfo* info = static_cast<ContentScriptsInfo*>(
+ extension->GetManifestData(keys::kContentScripts));
+ return info ? info->content_scripts
+ : g_empty_script_list.Get().user_script_list;
+}
+
+// static
+bool ContentScriptsInfo::ExtensionHasScriptAtURL(const Extension* extension,
+ const GURL& url) {
+ const UserScriptList& content_scripts = GetContentScripts(extension);
+ for (UserScriptList::const_iterator iter = content_scripts.begin();
+ iter != content_scripts.end(); ++iter) {
+ if (iter->MatchesURL(url))
+ return true;
+ }
+ return false;
+}
+
+ContentScriptsHandler::ContentScriptsHandler() {
+}
+
+ContentScriptsHandler::~ContentScriptsHandler() {
+}
+
+const std::vector<std::string> ContentScriptsHandler::Keys() const {
+ static const char* keys[] = {
+ keys::kContentScripts
+ };
+ return std::vector<std::string>(keys, keys + arraysize(keys));
+}
+
+bool ContentScriptsHandler::Parse(Extension* extension, string16* error) {
+ scoped_ptr<ContentScriptsInfo> content_scripts_info(new ContentScriptsInfo);
+ const ListValue* scripts_list = NULL;
+ if (!extension->manifest()->GetList(keys::kContentScripts, &scripts_list)) {
+ *error = ASCIIToUTF16(errors::kInvalidContentScriptsList);
+ return false;
+ }
+
+ for (size_t i = 0; i < scripts_list->GetSize(); ++i) {
+ const DictionaryValue* script_dict = NULL;
+ if (!scripts_list->GetDictionary(i, &script_dict)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidContentScript,
+ base::IntToString(i));
+ return false;
+ }
+
+ UserScript user_script;
+ if (!LoadUserScriptFromDictionary(script_dict,
+ i,
+ extension,
+ error,
+ &user_script)) {
+ return false; // Failed to parse script context definition.
+ }
+
+ user_script.set_extension_id(extension->id());
+ if (extension->converted_from_user_script()) {
+ user_script.set_emulate_greasemonkey(true);
+ // Greasemonkey matches all frames.
+ user_script.set_match_all_frames(true);
+ }
+ content_scripts_info->content_scripts.push_back(user_script);
+ }
+ extension->SetManifestData(keys::kContentScripts,
+ content_scripts_info.release());
+ return true;
+}
+
+bool ContentScriptsHandler::Validate(
+ const Extension* extension,
+ std::string* error,
+ std::vector<InstallWarning>* warnings) const {
+ // Validate that claimed script resources actually exist,
+ // and are UTF-8 encoded.
+ ExtensionResource::SymlinkPolicy symlink_policy;
+ if ((extension->creation_flags() &
+ Extension::FOLLOW_SYMLINKS_ANYWHERE) != 0) {
+ symlink_policy = ExtensionResource::FOLLOW_SYMLINKS_ANYWHERE;
+ } else {
+ symlink_policy = ExtensionResource::SYMLINKS_MUST_RESOLVE_WITHIN_ROOT;
+ }
+
+ const extensions::UserScriptList& content_scripts =
+ extensions::ContentScriptsInfo::GetContentScripts(extension);
+ for (size_t i = 0; i < content_scripts.size(); ++i) {
+ const extensions::UserScript& script = content_scripts[i];
+
+ for (size_t j = 0; j < script.js_scripts().size(); j++) {
+ const extensions::UserScript::File& js_script = script.js_scripts()[j];
+ const base::FilePath& path = ExtensionResource::GetFilePath(
+ js_script.extension_root(), js_script.relative_path(),
+ symlink_policy);
+ if (!IsScriptValid(path, js_script.relative_path(),
+ IDS_EXTENSION_LOAD_JAVASCRIPT_FAILED, error))
+ return false;
+ }
+
+ for (size_t j = 0; j < script.css_scripts().size(); j++) {
+ const extensions::UserScript::File& css_script = script.css_scripts()[j];
+ const base::FilePath& path = ExtensionResource::GetFilePath(
+ css_script.extension_root(), css_script.relative_path(),
+ symlink_policy);
+ if (!IsScriptValid(path, css_script.relative_path(),
+ IDS_EXTENSION_LOAD_CSS_FAILED, error))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace extensions
diff --git a/chrome/common/extensions/manifest_handlers/content_scripts_handler.h b/chrome/common/extensions/manifest_handlers/content_scripts_handler.h
new file mode 100644
index 0000000..c3b8d06
--- /dev/null
+++ b/chrome/common/extensions/manifest_handlers/content_scripts_handler.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2013 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_HANDLERS_CONTENT_SCRIPTS_HANDLER_H_
+#define CHROME_COMMON_EXTENSIONS_MANIFEST_HANDLERS_CONTENT_SCRIPTS_HANDLER_H_
+
+#include <string>
+
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/manifest_handler.h"
+#include "chrome/common/extensions/user_script.h"
+
+namespace extensions {
+
+struct ContentScriptsInfo : public Extension::ManifestData {
+ ContentScriptsInfo();
+ virtual ~ContentScriptsInfo();
+
+ // Paths to the content scripts the extension contains (possibly empty).
+ UserScriptList content_scripts;
+
+ // Returns the content scripts for the extension (if the extension has
+ // no content scripts, this returns an empty list).
+ static const UserScriptList& GetContentScripts(const Extension* extension);
+
+ // Returns true if the extension has a content script declared at |url|.
+ static bool ExtensionHasScriptAtURL(const Extension* extension,
+ const GURL& url);
+};
+
+// Parses the "content_scripts" manifest key.
+class ContentScriptsHandler : public ManifestHandler {
+ public:
+ ContentScriptsHandler();
+ virtual ~ContentScriptsHandler();
+
+ virtual bool Parse(Extension* extension, string16* error) OVERRIDE;
+ virtual bool Validate(const Extension* extension,
+ std::string* error,
+ std::vector<InstallWarning>* warnings) const OVERRIDE;
+
+ private:
+ virtual const std::vector<std::string> Keys() const OVERRIDE;
+
+ DISALLOW_COPY_AND_ASSIGN(ContentScriptsHandler);
+};
+
+} // namespace extensions
+
+#endif // CHROME_COMMON_EXTENSIONS_MANIFEST_HANDLERS_CONTENT_SCRIPTS_HANDLER_H_
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_contentscript_unittest.cc b/chrome/common/extensions/manifest_handlers/content_scripts_manifest_unittest.cc
index 8470893..679357c0 100644
--- a/chrome/common/extensions/manifest_tests/extension_manifests_contentscript_unittest.cc
+++ b/chrome/common/extensions/manifest_handlers/content_scripts_manifest_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2013 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.
@@ -7,17 +7,28 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_manifest_constants.h"
+#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
#include "chrome/common/extensions/manifest_tests/extension_manifest_test.h"
#include "extensions/common/error_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace errors = extension_manifest_errors;
-TEST_F(ExtensionManifestTest, ContentScriptMatchPattern) {
+namespace extensions {
+
+class ContentScriptsManifestTest : public ExtensionManifestTest {
+ protected:
+ virtual void SetUp() OVERRIDE {
+ ExtensionManifestTest::SetUp();
+ (new ContentScriptsHandler)->Register();
+ }
+};
+
+TEST_F(ContentScriptsManifestTest, ContentScriptMatchPattern) {
Testcase testcases[] = {
// chrome:// urls are not allowed.
Testcase("content_script_chrome_url_invalid.json",
- extensions::ErrorUtils::FormatErrorMessage(
+ ErrorUtils::FormatErrorMessage(
errors::kInvalidMatch,
base::IntToString(0),
base::IntToString(0),
@@ -26,10 +37,10 @@ TEST_F(ExtensionManifestTest, ContentScriptMatchPattern) {
// Match paterns must be strings.
Testcase("content_script_match_pattern_not_string.json",
- extensions::ErrorUtils::FormatErrorMessage(errors::kInvalidMatch,
- base::IntToString(0),
- base::IntToString(0),
- errors::kExpectString))
+ ErrorUtils::FormatErrorMessage(errors::kInvalidMatch,
+ base::IntToString(0),
+ base::IntToString(0),
+ errors::kExpectString))
};
RunTestcases(testcases, arraysize(testcases),
EXPECT_TYPE_ERROR);
@@ -37,7 +48,7 @@ TEST_F(ExtensionManifestTest, ContentScriptMatchPattern) {
LoadAndExpectSuccess("ports_in_content_scripts.json");
}
-TEST_F(ExtensionManifestTest, ContentScriptsOnChromeUrlsWithFlag) {
+TEST_F(ContentScriptsManifestTest, ContentScriptsOnChromeUrlsWithFlag) {
CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kExtensionsOnChromeURLs);
std::string error;
@@ -45,5 +56,8 @@ TEST_F(ExtensionManifestTest, ContentScriptsOnChromeUrlsWithFlag) {
LoadAndExpectSuccess("content_script_chrome_url_invalid.json");
EXPECT_EQ("", error);
const GURL newtab_url("chrome://newtab/");
- EXPECT_TRUE(extension->HasContentScriptAtURL(newtab_url));
+ EXPECT_TRUE(ContentScriptsInfo::ExtensionHasScriptAtURL(extension,
+ newtab_url));
}
+
+} // namespace extensions
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_excludematches_unittest.cc b/chrome/common/extensions/manifest_handlers/exclude_matches_manifest_unittest.cc
index 0f01638..37a4ae5 100644
--- a/chrome/common/extensions/manifest_tests/extension_manifests_excludematches_unittest.cc
+++ b/chrome/common/extensions/manifest_handlers/exclude_matches_manifest_unittest.cc
@@ -1,13 +1,24 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2013 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_tests/extension_manifest_test.h"
#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
+#include "chrome/common/extensions/manifest_tests/extension_manifest_test.h"
#include "testing/gtest/include/gtest/gtest.h"
-TEST_F(ExtensionManifestTest, ExcludeMatchPatterns) {
+namespace extensions {
+
+class ExcludeMatchesManifestTest : public ExtensionManifestTest {
+ protected:
+ virtual void SetUp() OVERRIDE {
+ ExtensionManifestTest::SetUp();
+ (new ContentScriptsHandler)->Register();
+ }
+};
+
+TEST_F(ExcludeMatchesManifestTest, ExcludeMatchPatterns) {
Testcase testcases[] = {
Testcase("exclude_matches.json"),
Testcase("exclude_matches_empty.json")
@@ -25,3 +36,5 @@ TEST_F(ExtensionManifestTest, ExcludeMatchPatterns) {
RunTestcases(testcases2, arraysize(testcases2),
EXPECT_TYPE_ERROR);
}
+
+} // namespace extensions
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_initvalue_unittest.cc b/chrome/common/extensions/manifest_tests/extension_manifests_initvalue_unittest.cc
index 9dc40e4..580e52e 100644
--- a/chrome/common/extensions/manifest_tests/extension_manifests_initvalue_unittest.cc
+++ b/chrome/common/extensions/manifest_tests/extension_manifests_initvalue_unittest.cc
@@ -12,6 +12,7 @@
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_manifest_constants.h"
#include "chrome/common/extensions/manifest_handler.h"
+#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
#include "chrome/common/extensions/manifest_tests/extension_manifest_test.h"
#include "chrome/common/extensions/manifest_url_handler.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -34,6 +35,7 @@ class InitValueManifestTest : public ExtensionManifestTest {
(new extensions::IconsHandler)->Register();
(new extensions::OptionsPageHandler)->Register();
(new extensions::PageActionHandler)->Register();
+ (new extensions::ContentScriptsHandler)->Register();
}
};
diff --git a/chrome/common/extensions/permissions/permission_set.cc b/chrome/common/extensions/permissions/permission_set.cc
index 380f72a..704255b 100644
--- a/chrome/common/extensions/permissions/permission_set.cc
+++ b/chrome/common/extensions/permissions/permission_set.cc
@@ -10,6 +10,7 @@
#include "chrome/common/extensions/api/plugins/plugins_handler.h"
#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
#include "chrome/common/extensions/manifest_url_handler.h"
#include "chrome/common/extensions/permissions/permissions_info.h"
#include "content/public/common/url_constants.h"
@@ -535,8 +536,9 @@ void PermissionSet::InitImplicitExtensionPermissions(
// Add the scriptable hosts.
for (extensions::UserScriptList::const_iterator content_script =
- extension->content_scripts().begin();
- content_script != extension->content_scripts().end(); ++content_script) {
+ ContentScriptsInfo::GetContentScripts(extension).begin();
+ content_script != ContentScriptsInfo::GetContentScripts(extension).end();
+ ++content_script) {
URLPatternSet::const_iterator pattern =
content_script->url_patterns().begin();
for (; pattern != content_script->url_patterns().end(); ++pattern)
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc
index 478aa5e..c569f49 100644
--- a/chrome/common/extensions/permissions/permission_set_unittest.cc
+++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -14,6 +14,7 @@
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/features/feature.h"
#include "chrome/common/extensions/manifest_handler.h"
+#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
#include "chrome/common/extensions/permissions/permission_set.h"
#include "chrome/common/extensions/permissions/permissions_info.h"
#include "chrome/common/extensions/permissions/socket_permission.h"
@@ -77,11 +78,12 @@ bool Contains(const std::vector<string16>& warnings,
} // namespace
-
class PermissionsTest : public testing::Test {
+ protected:
virtual void SetUp() OVERRIDE {
testing::Test::SetUp();
(new BackgroundManifestHandler)->Register();
+ (new ContentScriptsHandler)->Register();
(new PluginsHandler)->Register();
}