Commit f853287c authored by hanxi's avatar hanxi Committed by Commit bot

This CL adds routing info for content scripts from <webview>.

To support dynamically added/removed content scripts in <webview>, we store
these content scripts in the same shared memory where user scripts from
declarative content API are stored, but the decision for injection will
be made in the render once the url pattern is matched. Since render doesn't
need to send IPCs to ask a decision from browser, it makes a precise time
injection possible.

Special to <webview>, once the content scripts are updated (added/removed),
browser will only notify the render process of the given <webview>, rather than
all of the renders (which is the case for user scripts).

BUG=437566

Review URL: https://codereview.chromium.org/906493004

Cr-Commit-Position: refs/heads/master@{#318774}
parent b5a74792
...@@ -444,11 +444,24 @@ void UserScriptLoader::OnScriptsLoaded( ...@@ -444,11 +444,24 @@ void UserScriptLoader::OnScriptsLoaded(
// We've got scripts ready to go. // We've got scripts ready to go.
shared_memory_.reset(shared_memory.release()); shared_memory_.reset(shared_memory.release());
for (content::RenderProcessHost::iterator i( // If user scripts are comming from a <webview>, will only notify the
content::RenderProcessHost::AllHostsIterator()); // RenderProcessHost of that <webview>; otherwise will notify all of the
!i.IsAtEnd(); // RenderProcessHosts.
i.Advance()) { if (user_scripts && !user_scripts->empty() &&
SendUpdate(i.GetCurrentValue(), shared_memory_.get(), changed_hosts_); (*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(); changed_hosts_.clear();
......
...@@ -145,6 +145,8 @@ void UserScript::Pickle(::Pickle* pickle) const { ...@@ -145,6 +145,8 @@ void UserScript::Pickle(::Pickle* pickle) const {
pickle->WriteBool(is_incognito_enabled()); pickle->WriteBool(is_incognito_enabled());
PickleHostID(pickle, host_id_); PickleHostID(pickle, host_id_);
pickle->WriteInt(consumer_instance_type());
PickleRoutingInfo(pickle, routing_info_);
PickleGlobs(pickle, globs_); PickleGlobs(pickle, globs_);
PickleGlobs(pickle, exclude_globs_); PickleGlobs(pickle, exclude_globs_);
PickleURLPatternSet(pickle, url_set_); PickleURLPatternSet(pickle, url_set_);
...@@ -167,6 +169,12 @@ void UserScript::PickleHostID(::Pickle* pickle, const HostID& host_id) const { ...@@ -167,6 +169,12 @@ void UserScript::PickleHostID(::Pickle* pickle, const HostID& host_id) const {
pickle->WriteString(host_id.id()); 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, void UserScript::PickleURLPatternSet(::Pickle* pickle,
const URLPatternSet& pattern_list) const { const URLPatternSet& pattern_list) const {
pickle->WriteSizeT(pattern_list.patterns().size()); pickle->WriteSizeT(pattern_list.patterns().size());
...@@ -200,6 +208,13 @@ void UserScript::Unpickle(const ::Pickle& pickle, PickleIterator* iter) { ...@@ -200,6 +208,13 @@ void UserScript::Unpickle(const ::Pickle& pickle, PickleIterator* iter) {
CHECK(iter->ReadBool(&incognito_enabled_)); CHECK(iter->ReadBool(&incognito_enabled_));
UnpickleHostID(pickle, iter, &host_id_); UnpickleHostID(pickle, iter, &host_id_);
int consumer_instance_type = 0;
CHECK(iter->ReadInt(&consumer_instance_type));
consumer_instance_type_ =
static_cast<ConsumerInstanceType>(consumer_instance_type);
UnpickleRoutingInfo(pickle, iter, &routing_info_);
UnpickleGlobs(pickle, iter, &globs_); UnpickleGlobs(pickle, iter, &globs_);
UnpickleGlobs(pickle, iter, &exclude_globs_); UnpickleGlobs(pickle, iter, &exclude_globs_);
UnpickleURLPatternSet(pickle, iter, &url_set_); UnpickleURLPatternSet(pickle, iter, &url_set_);
...@@ -230,6 +245,13 @@ void UserScript::UnpickleHostID(const ::Pickle& pickle, ...@@ -230,6 +245,13 @@ void UserScript::UnpickleHostID(const ::Pickle& pickle,
*host_id = HostID(static_cast<HostID::HostType>(type), id); *host_id = HostID(static_cast<HostID::HostType>(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, void UserScript::UnpickleURLPatternSet(const ::Pickle& pickle,
PickleIterator* iter, PickleIterator* iter,
URLPatternSet* pattern_list) { URLPatternSet* pattern_list) {
......
...@@ -126,6 +126,19 @@ class UserScript { ...@@ -126,6 +126,19 @@ class UserScript {
typedef std::vector<File> FileList; typedef std::vector<File> FileList;
// Render's routing info of a <webview> that the user script will be injected
// on. Only user scripts from <webview>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 // Constructor. Default the run location to document end, which is like
// Greasemonkey and probably more useful for typical scripts. // Greasemonkey and probably more useful for typical scripts.
UserScript(); UserScript();
...@@ -200,6 +213,19 @@ class UserScript { ...@@ -200,6 +213,19 @@ class UserScript {
const HostID& host_id() const { return host_id_; } const HostID& host_id() const { return host_id_; }
void set_host_id(const HostID& host_id) { host_id_ = 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_; } int id() const { return user_script_id_; }
void set_id(int id) { user_script_id_ = id; } void set_id(int id) { user_script_id_ = id; }
...@@ -226,6 +252,8 @@ class UserScript { ...@@ -226,6 +252,8 @@ class UserScript {
void PickleGlobs(::Pickle* pickle, void PickleGlobs(::Pickle* pickle,
const std::vector<std::string>& globs) const; const std::vector<std::string>& globs) const;
void PickleHostID(::Pickle* pickle, const HostID& host_id) const; void PickleHostID(::Pickle* pickle, const HostID& host_id) const;
void PickleRoutingInfo(::Pickle* pickle,
const RoutingInfo& routing_info) const;
void PickleURLPatternSet(::Pickle* pickle, void PickleURLPatternSet(::Pickle* pickle,
const URLPatternSet& pattern_list) const; const URLPatternSet& pattern_list) const;
void PickleScripts(::Pickle* pickle, const FileList& scripts) const; void PickleScripts(::Pickle* pickle, const FileList& scripts) const;
...@@ -236,6 +264,9 @@ class UserScript { ...@@ -236,6 +264,9 @@ class UserScript {
void UnpickleHostID(const ::Pickle& pickle, void UnpickleHostID(const ::Pickle& pickle,
PickleIterator* iter, PickleIterator* iter,
HostID* host_id); HostID* host_id);
void UnpickleRoutingInfo(const ::Pickle& pickle,
PickleIterator* iter,
RoutingInfo* routing_info);
void UnpickleURLPatternSet(const ::Pickle& pickle, PickleIterator* iter, void UnpickleURLPatternSet(const ::Pickle& pickle, PickleIterator* iter,
URLPatternSet* pattern_list); URLPatternSet* pattern_list);
void UnpickleScripts(const ::Pickle& pickle, PickleIterator* iter, void UnpickleScripts(const ::Pickle& pickle, PickleIterator* iter,
...@@ -278,6 +309,12 @@ class UserScript { ...@@ -278,6 +309,12 @@ class UserScript {
// |host_id| can be empty if the script is a "standlone" user script. // |host_id| can be empty if the script is a "standlone" user script.
HostID host_id_; 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 <webview>.
RoutingInfo routing_info_;
// The globally-unique id associated with this user script. Defaults to // The globally-unique id associated with this user script. Defaults to
// -1 for invalid. // -1 for invalid.
int user_script_id_; int user_script_id_;
......
...@@ -29,10 +29,15 @@ const std::string& ExtensionInjectionHost::name() const { ...@@ -29,10 +29,15 @@ const std::string& ExtensionInjectionHost::name() const {
} }
PermissionsData::AccessType ExtensionInjectionHost::CanExecuteOnFrame( PermissionsData::AccessType ExtensionInjectionHost::CanExecuteOnFrame(
const GURL& document_url, const GURL& document_url,
const GURL& top_frame_url, const GURL& top_frame_url,
int tab_id, int tab_id,
bool is_declarative) const { 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 // Declarative user scripts use "page access" (from "permissions" section in
// manifest) whereas non-declarative user scripts use custom // manifest) whereas non-declarative user scripts use custom
// "content script access" logic. // "content script access" logic.
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/lazy_instance.h" #include "base/lazy_instance.h"
#include "content/public/common/url_constants.h" #include "content/public/common/url_constants.h"
#include "content/public/renderer/render_view.h"
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
#include "extensions/common/permissions/permissions_data.h" #include "extensions/common/permissions/permissions_data.h"
#include "extensions/renderer/injection_host.h" #include "extensions/renderer/injection_host.h"
...@@ -127,15 +128,21 @@ PermissionsData::AccessType UserScriptInjector::CanExecuteOnFrame( ...@@ -127,15 +128,21 @@ PermissionsData::AccessType UserScriptInjector::CanExecuteOnFrame(
blink::WebFrame* web_frame, blink::WebFrame* web_frame,
int tab_id, int tab_id,
const GURL& top_url) const { 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( GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL(
web_frame, web_frame->document().url(), script_->match_about_blank()); 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_); 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<blink::WebScriptSource> UserScriptInjector::GetJsSources( std::vector<blink::WebScriptSource> UserScriptInjector::GetJsSources(
......
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