diff --git a/extensions/browser/user_script_loader.cc b/extensions/browser/user_script_loader.cc index 2b836332feba54..cc0ce00cf82f4c 100644 --- a/extensions/browser/user_script_loader.cc +++ b/extensions/browser/user_script_loader.cc @@ -444,11 +444,24 @@ void UserScriptLoader::OnScriptsLoaded( // We've got scripts ready to go. shared_memory_.reset(shared_memory.release()); - for (content::RenderProcessHost::iterator i( - content::RenderProcessHost::AllHostsIterator()); - !i.IsAtEnd(); - i.Advance()) { - SendUpdate(i.GetCurrentValue(), shared_memory_.get(), changed_hosts_); + // If user scripts are comming from a , will only notify the + // RenderProcessHost of that ; otherwise will notify all of the + // RenderProcessHosts. + if (user_scripts && !user_scripts->empty() && + (*user_scripts)[0].consumer_instance_type() == + UserScript::ConsumerInstanceType::WEBVIEW) { + DCHECK_EQ(1u, user_scripts->size()); + int render_process_id = (*user_scripts)[0].routing_info().render_process_id; + content::RenderProcessHost* host = + content::RenderProcessHost::FromID(render_process_id); + if (host) + SendUpdate(host, shared_memory_.get(), changed_hosts_); + } else { + for (content::RenderProcessHost::iterator i( + content::RenderProcessHost::AllHostsIterator()); + !i.IsAtEnd(); i.Advance()) { + SendUpdate(i.GetCurrentValue(), shared_memory_.get(), changed_hosts_); + } } changed_hosts_.clear(); diff --git a/extensions/common/user_script.cc b/extensions/common/user_script.cc index b8ba22e1d76395..7859e75f244cb0 100644 --- a/extensions/common/user_script.cc +++ b/extensions/common/user_script.cc @@ -145,6 +145,8 @@ void UserScript::Pickle(::Pickle* pickle) const { pickle->WriteBool(is_incognito_enabled()); PickleHostID(pickle, host_id_); + pickle->WriteInt(consumer_instance_type()); + PickleRoutingInfo(pickle, routing_info_); PickleGlobs(pickle, globs_); PickleGlobs(pickle, exclude_globs_); PickleURLPatternSet(pickle, url_set_); @@ -167,6 +169,12 @@ void UserScript::PickleHostID(::Pickle* pickle, const HostID& host_id) const { pickle->WriteString(host_id.id()); } +void UserScript::PickleRoutingInfo(::Pickle* pickle, + const RoutingInfo& routing_info) const { + pickle->WriteInt(routing_info.render_process_id); + pickle->WriteInt(routing_info.render_view_id); +} + void UserScript::PickleURLPatternSet(::Pickle* pickle, const URLPatternSet& pattern_list) const { pickle->WriteSizeT(pattern_list.patterns().size()); @@ -200,6 +208,13 @@ void UserScript::Unpickle(const ::Pickle& pickle, PickleIterator* iter) { CHECK(iter->ReadBool(&incognito_enabled_)); UnpickleHostID(pickle, iter, &host_id_); + + int consumer_instance_type = 0; + CHECK(iter->ReadInt(&consumer_instance_type)); + consumer_instance_type_ = + static_cast(consumer_instance_type); + + UnpickleRoutingInfo(pickle, iter, &routing_info_); UnpickleGlobs(pickle, iter, &globs_); UnpickleGlobs(pickle, iter, &exclude_globs_); UnpickleURLPatternSet(pickle, iter, &url_set_); @@ -230,6 +245,13 @@ void UserScript::UnpickleHostID(const ::Pickle& pickle, *host_id = HostID(static_cast(type), id); } +void UserScript::UnpickleRoutingInfo(const ::Pickle& pickle, + PickleIterator* iter, + RoutingInfo* routing_info) { + CHECK(iter->ReadInt(&routing_info->render_process_id)); + CHECK(iter->ReadInt(&routing_info->render_view_id)); +} + void UserScript::UnpickleURLPatternSet(const ::Pickle& pickle, PickleIterator* iter, URLPatternSet* pattern_list) { diff --git a/extensions/common/user_script.h b/extensions/common/user_script.h index 6069161e8fb4dc..e0de3f7e2af93a 100644 --- a/extensions/common/user_script.h +++ b/extensions/common/user_script.h @@ -126,6 +126,19 @@ class UserScript { typedef std::vector FileList; + // Render's routing info of a that the user script will be injected + // on. Only user scripts from s have a custom routing info. + struct RoutingInfo { + RoutingInfo() : render_process_id(-1), render_view_id(-1) {}; + ~RoutingInfo() {}; + + int render_process_id; + int render_view_id; + }; + + // Type of a API consumer instance that user scripts will be injected on. + enum ConsumerInstanceType { TAB, WEBVIEW }; + // Constructor. Default the run location to document end, which is like // Greasemonkey and probably more useful for typical scripts. UserScript(); @@ -200,6 +213,19 @@ class UserScript { const HostID& host_id() const { return host_id_; } void set_host_id(const HostID& host_id) { host_id_ = host_id; } + const ConsumerInstanceType& consumer_instance_type() const { + return consumer_instance_type_; + } + void set_consumer_instance_type( + const ConsumerInstanceType& consumer_instance_type) { + consumer_instance_type_ = consumer_instance_type; + } + + const RoutingInfo& routing_info() const { return routing_info_; } + void set_routing_info(const RoutingInfo& routing_info) { + routing_info_ = routing_info; + } + int id() const { return user_script_id_; } void set_id(int id) { user_script_id_ = id; } @@ -226,6 +252,8 @@ class UserScript { void PickleGlobs(::Pickle* pickle, const std::vector& globs) const; void PickleHostID(::Pickle* pickle, const HostID& host_id) const; + void PickleRoutingInfo(::Pickle* pickle, + const RoutingInfo& routing_info) const; void PickleURLPatternSet(::Pickle* pickle, const URLPatternSet& pattern_list) const; void PickleScripts(::Pickle* pickle, const FileList& scripts) const; @@ -236,6 +264,9 @@ class UserScript { void UnpickleHostID(const ::Pickle& pickle, PickleIterator* iter, HostID* host_id); + void UnpickleRoutingInfo(const ::Pickle& pickle, + PickleIterator* iter, + RoutingInfo* routing_info); void UnpickleURLPatternSet(const ::Pickle& pickle, PickleIterator* iter, URLPatternSet* pattern_list); void UnpickleScripts(const ::Pickle& pickle, PickleIterator* iter, @@ -278,6 +309,12 @@ class UserScript { // |host_id| can be empty if the script is a "standlone" user script. HostID host_id_; + // The type of the consumer instance that the script will be injected. + ConsumerInstanceType consumer_instance_type_; + + // The render side's rounting info for content_scripts of . + RoutingInfo routing_info_; + // The globally-unique id associated with this user script. Defaults to // -1 for invalid. int user_script_id_; diff --git a/extensions/renderer/extension_injection_host.cc b/extensions/renderer/extension_injection_host.cc index 5b3c463b0b8e90..55ee1cc6b4dec0 100644 --- a/extensions/renderer/extension_injection_host.cc +++ b/extensions/renderer/extension_injection_host.cc @@ -29,10 +29,15 @@ const std::string& ExtensionInjectionHost::name() const { } PermissionsData::AccessType ExtensionInjectionHost::CanExecuteOnFrame( - const GURL& document_url, - const GURL& top_frame_url, - int tab_id, - bool is_declarative) const { + const GURL& document_url, + const GURL& top_frame_url, + int tab_id, + bool is_declarative) const { + // If we don't have a tab id, we have no UI surface to ask for user consent. + // For now, we treat this as an automatic allow. + if (tab_id == -1) + return PermissionsData::ACCESS_ALLOWED; + // Declarative user scripts use "page access" (from "permissions" section in // manifest) whereas non-declarative user scripts use custom // "content script access" logic. diff --git a/extensions/renderer/user_script_injector.cc b/extensions/renderer/user_script_injector.cc index c3e15ef36e909c..e620a7c65e4ec7 100644 --- a/extensions/renderer/user_script_injector.cc +++ b/extensions/renderer/user_script_injector.cc @@ -8,6 +8,7 @@ #include "base/lazy_instance.h" #include "content/public/common/url_constants.h" +#include "content/public/renderer/render_view.h" #include "extensions/common/extension.h" #include "extensions/common/permissions/permissions_data.h" #include "extensions/renderer/injection_host.h" @@ -127,15 +128,21 @@ PermissionsData::AccessType UserScriptInjector::CanExecuteOnFrame( blink::WebFrame* web_frame, int tab_id, const GURL& top_url) const { - // If we don't have a tab id, we have no UI surface to ask for user consent. - // For now, we treat this as an automatic allow. - if (tab_id == -1) - return PermissionsData::ACCESS_ALLOWED; - GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL( web_frame, web_frame->document().url(), script_->match_about_blank()); - return injection_host->CanExecuteOnFrame( + PermissionsData::AccessType can_execute = injection_host->CanExecuteOnFrame( effective_document_url, top_url, tab_id, is_declarative_); + + if (script_->consumer_instance_type() != + UserScript::ConsumerInstanceType::WEBVIEW || + can_execute == PermissionsData::ACCESS_DENIED) + return can_execute; + + int routing_id = content::RenderView::FromWebView(web_frame->top()->view()) + ->GetRoutingID(); + return script_->routing_info().render_view_id == routing_id + ? PermissionsData::ACCESS_ALLOWED + : PermissionsData::ACCESS_DENIED; } std::vector UserScriptInjector::GetJsSources(