Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5558)

Unified Diff: chrome/common/extensions/api/content_scripts/content_scripts_handler.cc

Issue 11724002: Move ContentScripts out of Extension (Closed) Base URL: http://git.chromium.org/chromium/src.git@dc_unref_browser_action
Patch Set: Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/common/extensions/api/content_scripts/content_scripts_handler.cc
diff --git a/chrome/common/extensions/api/content_scripts/content_scripts_handler.cc b/chrome/common/extensions/api/content_scripts/content_scripts_handler.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2a9761e4f57b01b5d188ff1e673844bc1d63b7d5
--- /dev/null
+++ b/chrome/common/extensions/api/content_scripts/content_scripts_handler.cc
@@ -0,0 +1,341 @@
+// Copyright (c) 2012 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/api/content_scripts/content_scripts_handler.h"
+
+#include "base/lazy_instance.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/string_number_conversions.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 "chrome/common/extensions/extension_resource.h"
+#include "content/public/common/url_constants.h"
+#include "extensions/common/error_utils.h"
+#include "extensions/common/url_pattern.h"
+#include "googleurl/src/gurl.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::kValidUserScriptSchemes);
+ if (extension->CanExecuteScriptEverywhere())
+ pattern.SetValidSchemes(URLPattern::SCHEME_ALL);
+
+ 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;
+ }
+
+ if (pattern.MatchesScheme(chrome::kFileScheme) &&
+ !extension->CanExecuteScriptEverywhere()) {
+ extension->set_wants_file_access(true);
Devlin 2012/12/29 21:18:38 This is bad. Do we know how we want to handle thin
Yoyo Zhou 2013/01/04 00:13:30 I'd put a TODO saying what's wrong, at least until
Devlin 2013/01/11 20:30:02 Done (in Extension.h, with the method).
+ 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;
+ }
+
+ URLPattern pattern(UserScript::kValidUserScriptSchemes);
+ if (extension->CanExecuteScriptEverywhere())
+ pattern.SetValidSchemes(URLPattern::SCHEME_ALL);
+
+ 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;
+}
+
+struct EmptyUserScriptList {
+ UserScriptList user_script_list;
+};
+
+static base::LazyInstance<EmptyUserScriptList> g_empty_script_list =
+ LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+// 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;
+}
+
+ContentScriptsHandler::ContentScriptsHandler() {
+}
+
+ContentScriptsHandler::~ContentScriptsHandler() {
+}
+
+bool ContentScriptsHandler::Parse(const base::Value* value,
+ Extension* extension,
+ string16* error) {
+ scoped_ptr<ContentScriptsInfo> content_scripts_info(new ContentScriptsInfo);
+ const ListValue* scripts_list = NULL;
+ if (!value->GetAsList(&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(
+ extension_manifest_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;
+}
+
+} // namespace extensions
+

Powered by Google App Engine
This is Rietveld 408576698