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

Unified Diff: extensions/browser/api/guest_view/web_view/web_view_internal_api.cc

Issue 959413003: Implement <webview>.addContentScript/removeContentScript API [1] (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 months 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: extensions/browser/api/guest_view/web_view/web_view_internal_api.cc
diff --git a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc
index 74c89c6346f931030692756356d28be189b178e3..12e9686c48bbe77cc5e40e9554b9588c5221545d 100644
--- a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc
+++ b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc
@@ -4,6 +4,7 @@
#include "extensions/browser/api/guest_view/web_view/web_view_internal_api.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/browser_context.h"
@@ -13,17 +14,26 @@
#include "content/public/common/stop_find_action.h"
#include "content/public/common/url_fetcher.h"
#include "extensions/browser/guest_view/web_view/web_view_constants.h"
+#include "extensions/browser/guest_view/web_view/web_view_content_script_manager.h"
#include "extensions/common/api/web_view_internal.h"
#include "extensions/common/error_utils.h"
+#include "extensions/common/manifest_constants.h"
+#include "extensions/common/permissions/permissions_data.h"
+#include "extensions/common/user_script.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "third_party/WebKit/public/web/WebFindOptions.h"
using content::WebContents;
+using extensions::ExtensionResource;
+using extensions::core_api::web_view_internal::ContentScriptDetails;
using extensions::core_api::web_view_internal::SetPermission::Params;
using extensions::core_api::extension_types::InjectDetails;
+using extensions::UserScript;
using ui_zoom::ZoomController;
+// error messages for content scripts:
+namespace errors = extensions::manifest_errors;
namespace web_view_internal = extensions::core_api::web_view_internal;
namespace {
@@ -37,6 +47,9 @@ const char kLocalStorageKey[] = "localStorage";
const char kWebSQLKey[] = "webSQL";
const char kSinceKey[] = "since";
const char kLoadFileError[] = "Failed to load file: \"*\". ";
+const char kViewInstanceIdError[] = "view_instance_id is missing.";
+const char kDuplicatedContentScriptNamesError[] =
+ "The given content script name already exists.";
uint32 MaskForKey(const char* key) {
if (strcmp(key, kAppCacheKey) == 0)
@@ -56,6 +69,169 @@ uint32 MaskForKey(const char* key) {
return 0;
}
+HostID GenerateHostIDFromEmbedder(const extensions::Extension* extension,
+ const content::WebContents* web_contents) {
+ if (extension)
+ return HostID(HostID::EXTENSIONS, extension->id());
+
+ if (web_contents && web_contents->GetWebUI()) {
+ const GURL& url = web_contents->GetSiteInstance()->GetSiteURL();
+ return HostID(HostID::WEBUI, url.spec());
+ }
+ NOTREACHED();
+ return HostID();
+}
+
+// Parses the values stored in ContentScriptDetails, and constructs a
+// UserScript.
+bool ParseContentScript(const ContentScriptDetails& script_value,
+ const extensions::Extension* extension,
+ const GURL& owner_base_url,
+ UserScript* script,
+ std::string* error) {
+ // matches (required):
+ if (script_value.matches.empty())
+ return false;
+
+ // The default for WebUI is not having special access, but we can change that
+ // if needed.
+ bool allowed_everywhere = false;
+ if (extension &&
+ extensions::PermissionsData::CanExecuteScriptEverywhere(extension))
+ allowed_everywhere = true;
+
+ for (const std::string& match : script_value.matches) {
+ URLPattern pattern(UserScript::ValidUserScriptSchemes(allowed_everywhere));
+ if (pattern.Parse(match) != URLPattern::PARSE_SUCCESS) {
+ *error = errors::kInvalidMatches;
+ return false;
+ }
+ script->add_url_pattern(pattern);
+ }
+
+ // exclude_matches:
+ if (script_value.exclude_matches) {
+ const std::vector<std::string>& exclude_matches =
+ *(script_value.exclude_matches.get());
+ for (const std::string& exclude_match : exclude_matches) {
+ URLPattern pattern(
+ UserScript::ValidUserScriptSchemes(allowed_everywhere));
+
+ if (pattern.Parse(exclude_match) != URLPattern::PARSE_SUCCESS) {
+ *error = errors::kInvalidExcludeMatches;
+ return false;
+ }
+ script->add_exclude_url_pattern(pattern);
+ }
+ }
+ // run_at:
+ if (script_value.run_at) {
+ UserScript::RunLocation run_at = UserScript::UNDEFINED;
+ switch (script_value.run_at) {
+ case extensions::core_api::extension_types::RUN_AT_NONE:
+ case extensions::core_api::extension_types::RUN_AT_DOCUMENT_IDLE:
+ run_at = UserScript::DOCUMENT_IDLE;
+ break;
+ case extensions::core_api::extension_types::RUN_AT_DOCUMENT_START:
+ run_at = UserScript::DOCUMENT_START;
+ break;
+ case extensions::core_api::extension_types::RUN_AT_DOCUMENT_END:
+ run_at = UserScript::DOCUMENT_END;
+ break;
+ }
+ // The default for run_at is RUN_AT_DOCUMENT_IDLE.
+ script->set_run_location(run_at);
+ }
+
+ // match_about_blank:
+ if (script_value.match_about_blank)
+ script->set_match_about_blank(*script_value.match_about_blank);
+
+ // css:
+ if (script_value.css) {
+ for (const std::string& relative : *(script_value.css.get())) {
+ GURL url = owner_base_url.Resolve(relative);
+ if (extension) {
+ ExtensionResource resource = extension->GetResource(relative);
+ script->css_scripts().push_back(UserScript::File(
+ resource.extension_root(), resource.relative_path(), url));
+ } else {
+ script->css_scripts().push_back(extensions::UserScript::File(
+ base::FilePath(), base::FilePath(), url));
+ }
+ }
+ }
+
+ // js:
+ if (script_value.js) {
+ for (const std::string& relative : *(script_value.js.get())) {
+ GURL url = owner_base_url.Resolve(relative);
+ if (extension) {
+ ExtensionResource resource = extension->GetResource(relative);
+ script->js_scripts().push_back(UserScript::File(
+ resource.extension_root(), resource.relative_path(), url));
+ } else {
+ script->js_scripts().push_back(extensions::UserScript::File(
+ base::FilePath(), base::FilePath(), url));
+ }
+ }
+ }
+
+ // all_frames:
+ if (script_value.all_frames)
+ script->set_match_all_frames(*(script_value.all_frames));
+
+ // include_globs:
+ if (script_value.include_globs) {
+ for (const std::string& glob : *(script_value.include_globs.get()))
+ script->add_glob(glob);
+ }
+
+ // exclude_globs:
+ if (script_value.exclude_globs) {
+ for (const std::string& glob : *(script_value.exclude_globs.get()))
+ script->add_exclude_glob(glob);
+ }
+
+ return true;
+}
+
+bool ParseContentScripts(
+ std::vector<linked_ptr<ContentScriptDetails>> content_script_list,
+ const extensions::Extension* extension,
+ const HostID& host_id,
+ bool incognito_enabled,
+ const GURL& owner_base_url,
+ std::set<UserScript>* result,
+ std::string* error) {
+ if (content_script_list.empty())
+ return false;
+
+ std::set<std::string> names;
+ for (const linked_ptr<ContentScriptDetails> script_value :
+ content_script_list) {
+ const std::string& name = script_value->name;
+ if (!names.insert(name).second) {
+ // The name was already in the list.
+ *error = kDuplicatedContentScriptNamesError;
+ return false;
+ }
+
+ UserScript script;
+ if (!ParseContentScript(*script_value, extension, owner_base_url, &script,
+ error))
+ return false;
+
+ script.set_id(UserScript::GenerateUserScriptID());
+ script.set_name(name);
+ script.set_incognito_enabled(incognito_enabled);
+ script.set_host_id(host_id);
+ script.set_consumer_instance_type(UserScript::WEBVIEW);
+ result->insert(script);
+ }
+ return true;
+}
+
} // namespace
namespace extensions {
@@ -256,6 +432,77 @@ bool WebViewInternalInsertCSSFunction::ShouldInsertCSS() const {
return true;
}
+WebViewInternalAddContentScriptsFunction::
+ WebViewInternalAddContentScriptsFunction() {
+}
+
+WebViewInternalAddContentScriptsFunction::
+ ~WebViewInternalAddContentScriptsFunction() {
+}
+
+ExecuteCodeFunction::ResponseAction
+WebViewInternalAddContentScriptsFunction::Run() {
+ scoped_ptr<web_view_internal::AddContentScripts::Params> params(
+ web_view_internal::AddContentScripts::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+
+ if (!params->instance_id)
+ return RespondNow(Error(kViewInstanceIdError));
+
+ GURL owner_base_url(
+ render_view_host()->GetSiteInstance()->GetSiteURL().GetWithEmptyPath());
+ std::set<UserScript> result;
+
+ content::WebContents* sender_web_contents = GetSenderWebContents();
+ HostID host_id = GenerateHostIDFromEmbedder(extension(), sender_web_contents);
+ bool incognito_enabled = browser_context()->IsOffTheRecord();
+
+ if (!ParseContentScripts(params->content_script_list, extension(), host_id,
+ incognito_enabled, owner_base_url, &result, &error_))
+ return RespondNow(Error(error_));
+
+ WebViewContentScriptManager* manager =
+ WebViewContentScriptManager::Get(browser_context());
+ DCHECK(manager);
+
+ manager->AddContentScripts(sender_web_contents, params->instance_id, host_id,
+ result);
+
+ return RespondNow(NoArguments());
+}
+
+WebViewInternalRemoveContentScriptsFunction::
+ WebViewInternalRemoveContentScriptsFunction() {
+}
+
+WebViewInternalRemoveContentScriptsFunction::
+ ~WebViewInternalRemoveContentScriptsFunction() {
+}
+
+ExecuteCodeFunction::ResponseAction
+WebViewInternalRemoveContentScriptsFunction::Run() {
+ scoped_ptr<web_view_internal::RemoveContentScripts::Params> params(
+ web_view_internal::RemoveContentScripts::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+
+ if (!params->instance_id)
+ return RespondNow(Error(kViewInstanceIdError));
+
+ WebViewContentScriptManager* manager =
+ WebViewContentScriptManager::Get(browser_context());
+ DCHECK(manager);
+
+ content::WebContents* sender_web_contents = GetSenderWebContents();
+ HostID host_id = GenerateHostIDFromEmbedder(extension(), sender_web_contents);
+
+ std::vector<std::string> script_name_list;
+ if (params->script_name_list)
+ script_name_list.swap(*params->script_name_list);
+ manager->RemoveContentScripts(GetSenderWebContents(), params->instance_id,
+ host_id, script_name_list);
+ return RespondNow(NoArguments());
+}
+
WebViewInternalSetNameFunction::WebViewInternalSetNameFunction() {
}

Powered by Google App Engine
This is Rietveld 408576698