diff options
-rw-r--r-- | extensions/extensions.gypi | 2 | ||||
-rw-r--r-- | extensions/renderer/dispatcher.cc | 2 | ||||
-rw-r--r-- | extensions/renderer/extension_injection_host.cc | 23 | ||||
-rw-r--r-- | extensions/renderer/extension_injection_host.h | 12 | ||||
-rw-r--r-- | extensions/renderer/injection_host.h | 3 | ||||
-rw-r--r-- | extensions/renderer/script_injection.cc | 54 | ||||
-rw-r--r-- | extensions/renderer/script_injection.h | 24 | ||||
-rw-r--r-- | extensions/renderer/script_injection_manager.cc | 73 | ||||
-rw-r--r-- | extensions/renderer/script_injection_manager.h | 3 | ||||
-rw-r--r-- | extensions/renderer/user_script_set.cc | 32 | ||||
-rw-r--r-- | extensions/renderer/user_script_set.h | 5 | ||||
-rw-r--r-- | extensions/renderer/user_script_set_manager.cc | 7 | ||||
-rw-r--r-- | extensions/renderer/user_script_set_manager.h | 7 | ||||
-rw-r--r-- | extensions/renderer/web_ui_injection_host.cc | 41 | ||||
-rw-r--r-- | extensions/renderer/web_ui_injection_host.h | 33 |
15 files changed, 211 insertions, 110 deletions
diff --git a/extensions/extensions.gypi b/extensions/extensions.gypi index 4c2e6cd..20ed947 100644 --- a/extensions/extensions.gypi +++ b/extensions/extensions.gypi @@ -970,6 +970,8 @@ 'renderer/v8_context_native_handler.h', 'renderer/v8_schema_registry.cc', 'renderer/v8_schema_registry.h', + 'renderer/web_ui_injection_host.cc', + 'renderer/web_ui_injection_host.h', ], 'extensions_utility_sources': [ 'utility/unpacker.cc', diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc index e4287e5..38c3e03 100644 --- a/extensions/renderer/dispatcher.cc +++ b/extensions/renderer/dispatcher.cc @@ -1036,6 +1036,8 @@ void Dispatcher::OnUnloaded(const std::string& id) { extensions_.Remove(id); active_extension_ids_.erase(id); + script_injection_manager_->OnExtensionUnloaded(id); + // If the extension is later reloaded with a different set of permissions, // we'd like it to get a new isolated world ID, so that it can pick up the // changed origin whitelist. diff --git a/extensions/renderer/extension_injection_host.cc b/extensions/renderer/extension_injection_host.cc index 55ee1cc..7a27a08 100644 --- a/extensions/renderer/extension_injection_host.cc +++ b/extensions/renderer/extension_injection_host.cc @@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "extensions/common/extension_set.h" #include "extensions/common/manifest_handlers/csp_info.h" #include "extensions/renderer/extension_injection_host.h" namespace extensions { ExtensionInjectionHost::ExtensionInjectionHost( - const scoped_refptr<const Extension>& extension) + const Extension* extension) : InjectionHost(HostID(HostID::EXTENSIONS, extension->id())), extension_(extension) { } @@ -16,8 +17,18 @@ ExtensionInjectionHost::ExtensionInjectionHost( ExtensionInjectionHost::~ExtensionInjectionHost() { } -const std::string& ExtensionInjectionHost::GetContentSecurityPolicy() const { - return CSPInfo::GetContentSecurityPolicy(extension_.get()); +// static +scoped_ptr<const ExtensionInjectionHost> ExtensionInjectionHost::Create( + const std::string& extension_id, const ExtensionSet* extensions) { + const Extension* extension = extensions->GetByID(extension_id); + if (!extension) + return scoped_ptr<const ExtensionInjectionHost>(); + return scoped_ptr<const ExtensionInjectionHost>( + new ExtensionInjectionHost(extension)); +} + +std::string ExtensionInjectionHost::GetContentSecurityPolicy() const { + return CSPInfo::GetContentSecurityPolicy(extension_); } const GURL& ExtensionInjectionHost::url() const { @@ -43,7 +54,7 @@ PermissionsData::AccessType ExtensionInjectionHost::CanExecuteOnFrame( // "content script access" logic. if (is_declarative) { return extension_->permissions_data()->GetPageAccess( - extension_.get(), + extension_, document_url, top_frame_url, tab_id, @@ -51,7 +62,7 @@ PermissionsData::AccessType ExtensionInjectionHost::CanExecuteOnFrame( nullptr /* ignore error */); } else { return extension_->permissions_data()->GetContentScriptAccess( - extension_.get(), + extension_, document_url, top_frame_url, tab_id, @@ -66,7 +77,7 @@ bool ExtensionInjectionHost::ShouldNotifyBrowserOfInjection() const { // otherwise been affected by the scripts-require-action feature. return extension_->permissions_data()->withheld_permissions()->IsEmpty() && PermissionsData::ScriptsMayRequireActionForExtension( - extension_.get(), + extension_, extension_->permissions_data()->active_permissions().get()); } diff --git a/extensions/renderer/extension_injection_host.h b/extensions/renderer/extension_injection_host.h index d940c94..bdf6f41 100644 --- a/extensions/renderer/extension_injection_host.h +++ b/extensions/renderer/extension_injection_host.h @@ -10,17 +10,23 @@ #include "extensions/renderer/injection_host.h" namespace extensions { +class ExtensionSet; // A wrapper class that holds an extension and implements the InjectionHost // interface. class ExtensionInjectionHost : public InjectionHost { public: - ExtensionInjectionHost(const scoped_refptr<const Extension>& extension); + ExtensionInjectionHost(const Extension* extension); ~ExtensionInjectionHost() override; + // Create an ExtensionInjectionHost object. If the extension is gone, returns + // a null scoped ptr. + static scoped_ptr<const ExtensionInjectionHost> Create( + const std::string& extension_id, const ExtensionSet* extensions); + private: // InjectionHost: - const std::string& GetContentSecurityPolicy() const override; + std::string GetContentSecurityPolicy() const override; const GURL& url() const override; const std::string& name() const override; PermissionsData::AccessType CanExecuteOnFrame( @@ -30,7 +36,7 @@ class ExtensionInjectionHost : public InjectionHost { bool is_declarative) const override; bool ShouldNotifyBrowserOfInjection() const override; - scoped_refptr<const Extension> extension_; + const Extension* extension_; DISALLOW_COPY_AND_ASSIGN(ExtensionInjectionHost); }; diff --git a/extensions/renderer/injection_host.h b/extensions/renderer/injection_host.h index 6c23c2d..4dcb225 100644 --- a/extensions/renderer/injection_host.h +++ b/extensions/renderer/injection_host.h @@ -15,7 +15,7 @@ class InjectionHost { InjectionHost(const HostID& host_id); virtual ~InjectionHost(); - virtual const std::string& GetContentSecurityPolicy() const = 0; + virtual std::string GetContentSecurityPolicy() const = 0; // The base url for the host. virtual const GURL& url() const = 0; @@ -35,6 +35,7 @@ class InjectionHost { virtual bool ShouldNotifyBrowserOfInjection() const = 0; const HostID& id() const { return id_; } + private: // The ID of the host. HostID id_; diff --git a/extensions/renderer/script_injection.cc b/extensions/renderer/script_injection.cc index 58cf328..3bb279a 100644 --- a/extensions/renderer/script_injection.cc +++ b/extensions/renderer/script_injection.cc @@ -108,16 +108,17 @@ void ScriptInjection::RemoveIsolatedWorld(const std::string& host_id) { ScriptInjection::ScriptInjection( scoped_ptr<ScriptInjector> injector, blink::WebLocalFrame* web_frame, - const HostID& host_id, + scoped_ptr<const InjectionHost> injection_host, UserScript::RunLocation run_location, int tab_id) : injector_(injector.Pass()), web_frame_(web_frame), - host_id_(host_id), + injection_host_(injection_host.Pass()), run_location_(run_location), tab_id_(tab_id), request_id_(kInvalidRequestId), complete_(false) { + CHECK(injection_host_.get()); } ScriptInjection::~ScriptInjection() { @@ -126,7 +127,6 @@ ScriptInjection::~ScriptInjection() { } bool ScriptInjection::TryToInject(UserScript::RunLocation current_location, - const InjectionHost* injection_host, ScriptsRunInfo* scripts_run_info) { if (current_location < run_location_) return false; // Wait for the right location. @@ -134,13 +134,14 @@ bool ScriptInjection::TryToInject(UserScript::RunLocation current_location, if (request_id_ != kInvalidRequestId) return false; // We're waiting for permission right now, try again later. - if (!injection_host) { + if (!injection_host_) { NotifyWillNotInject(ScriptInjector::EXTENSION_REMOVED); return true; // We're done. } - switch (injector_->CanExecuteOnFrame(injection_host, web_frame_, tab_id_, - web_frame_->top()->document().url())) { + switch (injector_->CanExecuteOnFrame( + injection_host_.get(), web_frame_, tab_id_, + web_frame_->top()->document().url())) { case PermissionsData::ACCESS_DENIED: NotifyWillNotInject(ScriptInjector::NOT_ALLOWED); return true; // We're done. @@ -148,7 +149,7 @@ bool ScriptInjection::TryToInject(UserScript::RunLocation current_location, SendInjectionMessage(true /* request permission */); return false; // Wait around for permission. case PermissionsData::ACCESS_ALLOWED: - Inject(injection_host, scripts_run_info); + Inject(scripts_run_info); return true; // We're done! } @@ -156,17 +157,20 @@ bool ScriptInjection::TryToInject(UserScript::RunLocation current_location, return false; } -bool ScriptInjection::OnPermissionGranted(const InjectionHost* injection_host, - ScriptsRunInfo* scripts_run_info) { - if (!injection_host) { +bool ScriptInjection::OnPermissionGranted(ScriptsRunInfo* scripts_run_info) { + if (!injection_host_) { NotifyWillNotInject(ScriptInjector::EXTENSION_REMOVED); return false; } - Inject(injection_host, scripts_run_info); + Inject(scripts_run_info); return true; } +void ScriptInjection::OnHostRemoved() { + injection_host_.reset(nullptr); +} + void ScriptInjection::SendInjectionMessage(bool request_permission) { content::RenderView* render_view = content::RenderView::FromWebView(web_frame()->top()->view()); @@ -176,7 +180,7 @@ void ScriptInjection::SendInjectionMessage(bool request_permission) { request_id_ = request_permission ? g_next_pending_id++ : kInvalidRequestId; render_view->Send(new ExtensionHostMsg_RequestScriptInjectionPermission( render_view->GetRoutingID(), - host_id_.id(), + host_id().id(), injector_->script_type(), request_id_)); } @@ -187,13 +191,12 @@ void ScriptInjection::NotifyWillNotInject( injector_->OnWillNotInject(reason); } -void ScriptInjection::Inject(const InjectionHost* injection_host, - ScriptsRunInfo* scripts_run_info) { - DCHECK(injection_host); +void ScriptInjection::Inject(ScriptsRunInfo* scripts_run_info) { + DCHECK(injection_host_); DCHECK(scripts_run_info); DCHECK(!complete_); - if (injection_host->ShouldNotifyBrowserOfInjection()) + if (injection_host_->ShouldNotifyBrowserOfInjection()) SendInjectionMessage(false /* don't request permission */); std::vector<blink::WebFrame*> frame_vector; @@ -226,13 +229,14 @@ void ScriptInjection::Inject(const InjectionHost* injection_host, // Note: we don't consider ACCESS_WITHHELD because there is nowhere to // surface a request for a child frame. // TODO(rdevlin.cronin): We should ask for permission somehow. - if (injector_->CanExecuteOnFrame(injection_host, frame, tab_id_, top_url) == - PermissionsData::ACCESS_DENIED) { + if (injector_->CanExecuteOnFrame( + injection_host_.get(), frame, tab_id_, top_url) == + PermissionsData::ACCESS_DENIED) { DCHECK(frame->parent()); continue; } if (inject_js) - InjectJs(injection_host, frame, execution_results.get()); + InjectJs(frame, execution_results.get()); if (inject_css) InjectCss(frame); } @@ -245,20 +249,20 @@ void ScriptInjection::Inject(const InjectionHost* injection_host, run_location_); } -void ScriptInjection::InjectJs(const InjectionHost* injection_host, - blink::WebLocalFrame* frame, +void ScriptInjection::InjectJs(blink::WebLocalFrame* frame, base::ListValue* execution_results) { std::vector<blink::WebScriptSource> sources = injector_->GetJsSources(run_location_); bool in_main_world = injector_->ShouldExecuteInMainWorld(); int world_id = in_main_world ? DOMActivityLogger::kMainWorldId - : GetIsolatedWorldIdForInstance(injection_host, frame); + : GetIsolatedWorldIdForInstance(injection_host_.get(), + frame); bool expects_results = injector_->ExpectsResults(); base::ElapsedTimer exec_timer; - if (injection_host->id().type() == HostID::EXTENSIONS) - DOMActivityLogger::AttachToWorld(world_id, injection_host->id().id()); + if (injection_host_->id().type() == HostID::EXTENSIONS) + DOMActivityLogger::AttachToWorld(world_id, injection_host_->id().id()); v8::HandleScope scope(v8::Isolate::GetCurrent()); v8::Local<v8::Value> script_value; if (in_main_world) { @@ -283,7 +287,7 @@ void ScriptInjection::InjectJs(const InjectionHost* injection_host, script_value = (*results)[0]; } - if (injection_host->id().type() == HostID::EXTENSIONS) + if (injection_host_->id().type() == HostID::EXTENSIONS) UMA_HISTOGRAM_TIMES("Extensions.InjectScriptTime", exec_timer.Elapsed()); if (expects_results) { diff --git a/extensions/renderer/script_injection.h b/extensions/renderer/script_injection.h index a883545..9f4691c 100644 --- a/extensions/renderer/script_injection.h +++ b/extensions/renderer/script_injection.h @@ -8,9 +8,9 @@ #include "base/basictypes.h" #include "base/macros.h" #include "extensions/common/user_script.h" +#include "extensions/renderer/injection_host.h" #include "extensions/renderer/script_injector.h" -class InjectionHost; struct HostID; namespace blink { @@ -32,7 +32,7 @@ class ScriptInjection { ScriptInjection(scoped_ptr<ScriptInjector> injector, blink::WebLocalFrame* web_frame, - const HostID& host_id, + scoped_ptr<const InjectionHost> injection_host, UserScript::RunLocation run_location, int tab_id); ~ScriptInjection(); @@ -41,19 +41,19 @@ class ScriptInjection { // the script has either injected or will never inject (i.e., if the object // is done), and false if injection is delayed (either for permission purposes // or because |current_location| is not the designated |run_location_|). - // NOTE: |injection_host| may be NULL, if the injection_host is removed! bool TryToInject(UserScript::RunLocation current_location, - const InjectionHost* injection_host, ScriptsRunInfo* scripts_run_info); // Called when permission for the given injection has been granted. // Returns true if the injection ran. - bool OnPermissionGranted(const InjectionHost* injection_host, - ScriptsRunInfo* scripts_run_info); + bool OnPermissionGranted(ScriptsRunInfo* scripts_run_info); + + // Resets the pointer of the injection host when the host is gone. + void OnHostRemoved(); // Accessors. blink::WebLocalFrame* web_frame() const { return web_frame_; } - const HostID& host_id() const { return host_id_; } + const HostID& host_id() const { return injection_host_->id(); } int64 request_id() const { return request_id_; } private: @@ -62,13 +62,11 @@ class ScriptInjection { void SendInjectionMessage(bool request_permission); // Injects the script, optionally populating |scripts_run_info|. - void Inject(const InjectionHost* injection_host, - ScriptsRunInfo* scripts_run_info); + void Inject(ScriptsRunInfo* scripts_run_info); // Inject any JS scripts into the |frame|, optionally populating // |execution_results|. - void InjectJs(const InjectionHost* injection_host, - blink::WebLocalFrame* frame, + void InjectJs(blink::WebLocalFrame* frame, base::ListValue* execution_results); // Inject any CSS source into the |frame|. @@ -83,8 +81,8 @@ class ScriptInjection { // The (main) WebFrame into which this should inject the script. blink::WebLocalFrame* web_frame_; - // The id of the associated injection_host. - HostID host_id_; + // The associated injection host. + scoped_ptr<const InjectionHost> injection_host_; // The location in the document load at which we inject the script. UserScript::RunLocation run_location_; diff --git a/extensions/renderer/script_injection_manager.cc b/extensions/renderer/script_injection_manager.cc index 93862dd..7deb027 100644 --- a/extensions/renderer/script_injection_manager.cc +++ b/extensions/renderer/script_injection_manager.cc @@ -53,20 +53,6 @@ UserScript::RunLocation NextRunLocation(UserScript::RunLocation run_location) { return UserScript::RUN_LOCATION_LAST; } - -// TODO(hanxi): let ScriptInjection own an InjectionHost to avoid constructing -// an ExtensionInjectionHost many times. -// Note: the ScriptInjection should be able to know when the backing extension -// is removed. -scoped_ptr<ExtensionInjectionHost> GetExtensionInjectionHost( - const std::string& extension_id, const ExtensionSet* extensions) { - const Extension* extension = extensions->GetByID(extension_id); - if (!extension) - return scoped_ptr<ExtensionInjectionHost>(); - return scoped_ptr<ExtensionInjectionHost>( - new ExtensionInjectionHost(extension)); -} - } // namespace class ScriptInjectionManager::RVOHelper : public content::RenderViewObserver { @@ -256,6 +242,23 @@ void ScriptInjectionManager::OnRenderViewCreated( rvo_helpers_.push_back(new RVOHelper(render_view, this)); } +void ScriptInjectionManager::OnExtensionUnloaded( + const std::string& extension_id) { + for (auto iter = pending_injections_.begin(); + iter != pending_injections_.end();) { + if ((*iter)->host_id().id() == extension_id) { + (*iter)->OnHostRemoved(); + iter = pending_injections_.erase(iter); + } else { + ++iter; + } + } + // If we are currently injection scripts, we need to make a note that this + // extension is "dirty" (invalidated). + if (injecting_scripts_) + invalidated_while_injecting_.insert(extension_id); +} + void ScriptInjectionManager::OnUserScriptsUpdated( const std::set<std::string>& changed_extensions, const std::vector<UserScript*>& scripts) { @@ -392,15 +395,12 @@ void ScriptInjectionManager::InjectScripts( if (!IsFrameValid(frame)) break; - const std::string& extension_id = (*iter)->host_id().id(); - scoped_ptr<ExtensionInjectionHost> extension_injection_host = - GetExtensionInjectionHost(extension_id, extensions_); - // Try to inject the script if the extension is not "dirty" (invalidated by - // an update). If the injection does not finish (i.e., it is waiting for - // permission), add it to the list of pending injections. - if (invalidated_while_injecting_.count(extension_id) == 0 && + // Try to inject the script if the injection host is not "dirty" + // (invalidated by an update). If the injection does not finish + // (i.e., it is waiting for permission), add it to the list of pending + // injections. + if (invalidated_while_injecting_.count((*iter)->host_id().id()) == 0 && !(*iter)->TryToInject(run_location, - extension_injection_host.get(), &scripts_run_info)) { pending_injections_.insert(pending_injections_.begin(), *iter); iter = frame_injections.weak_erase(iter); @@ -433,23 +433,25 @@ void ScriptInjectionManager::HandleExecuteCode( return; } + scoped_ptr<const ExtensionInjectionHost> extension_injection_host = + ExtensionInjectionHost::Create(params.extension_id, extensions_); + + if (!extension_injection_host) + return; + scoped_ptr<ScriptInjection> injection(new ScriptInjection( scoped_ptr<ScriptInjector>( new ProgrammaticScriptInjector(params, main_frame)), main_frame, - HostID(HostID::EXTENSIONS, params.extension_id), + extension_injection_host.Pass(), static_cast<UserScript::RunLocation>(params.run_at), ExtensionHelper::Get(render_view)->tab_id())); ScriptsRunInfo scripts_run_info; FrameStatusMap::const_iterator iter = frame_statuses_.find(main_frame); - scoped_ptr<ExtensionInjectionHost> extension_injection_host = - GetExtensionInjectionHost(injection->host_id().id(), extensions_); - if (!injection->TryToInject( iter == frame_statuses_.end() ? UserScript::UNDEFINED : iter->second, - extension_injection_host.get(), &scripts_run_info)) { pending_injections_.push_back(injection.release()); } @@ -461,9 +463,6 @@ void ScriptInjectionManager::HandleExecuteDeclarativeScript( const ExtensionId& extension_id, int script_id, const GURL& url) { - scoped_ptr<ExtensionInjectionHost> extension_injection_host = - GetExtensionInjectionHost(extension_id, extensions_); - const Extension* extension = extensions_->GetByID(extension_id); // TODO(dcheng): This function signature should really be a WebLocalFrame, // rather than trying to coerce it here. scoped_ptr<ScriptInjection> injection = @@ -472,12 +471,11 @@ void ScriptInjectionManager::HandleExecuteDeclarativeScript( web_frame->toWebLocalFrame(), tab_id, url, - extension); - if (injection.get()) { + extension_id); + if (injection) { ScriptsRunInfo scripts_run_info; // TODO(markdittmer): Use return value of TryToInject for error handling. injection->TryToInject(UserScript::BROWSER_DRIVEN, - extension_injection_host.get(), &scripts_run_info); scripts_run_info.LogRun(web_frame, UserScript::BROWSER_DRIVEN); } @@ -487,8 +485,10 @@ void ScriptInjectionManager::HandlePermitScriptInjection(int64 request_id) { ScopedVector<ScriptInjection>::iterator iter = pending_injections_.begin(); for (; iter != pending_injections_.end(); ++iter) { - if ((*iter)->request_id() == request_id) + if ((*iter)->request_id() == request_id) { + DCHECK((*iter)->host_id().type() == HostID::EXTENSIONS); break; + } } if (iter == pending_injections_.end()) return; @@ -502,10 +502,7 @@ void ScriptInjectionManager::HandlePermitScriptInjection(int64 request_id) { pending_injections_.weak_erase(iter); ScriptsRunInfo scripts_run_info; - scoped_ptr<ExtensionInjectionHost> extension_injection_host = - GetExtensionInjectionHost(injection->host_id().id(), extensions_); - if (injection->OnPermissionGranted(extension_injection_host.get(), - &scripts_run_info)) { + if (injection->OnPermissionGranted(&scripts_run_info)) { scripts_run_info.LogRun(injection->web_frame(), UserScript::RUN_DEFERRED); } } diff --git a/extensions/renderer/script_injection_manager.h b/extensions/renderer/script_injection_manager.h index 8ec3d94..08cf1e1 100644 --- a/extensions/renderer/script_injection_manager.h +++ b/extensions/renderer/script_injection_manager.h @@ -45,6 +45,9 @@ class ScriptInjectionManager : public UserScriptSetManager::Observer { // Notifies that a new render view has been created. void OnRenderViewCreated(content::RenderView* render_view); + // Removes pending injections of the unloaded extension. + void OnExtensionUnloaded(const std::string& extension_id); + private: // A RenderViewObserver implementation which watches the various render views // in order to notify the ScriptInjectionManager of different document load diff --git a/extensions/renderer/user_script_set.cc b/extensions/renderer/user_script_set.cc index 1d66aaa..df7c7c9 100644 --- a/extensions/renderer/user_script_set.cc +++ b/extensions/renderer/user_script_set.cc @@ -12,9 +12,11 @@ #include "extensions/common/permissions/permissions_data.h" #include "extensions/renderer/extension_injection_host.h" #include "extensions/renderer/extensions_renderer_client.h" +#include "extensions/renderer/injection_host.h" #include "extensions/renderer/script_context.h" #include "extensions/renderer/script_injection.h" #include "extensions/renderer/user_script_injector.h" +#include "extensions/renderer/web_ui_injection_host.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebFrame.h" #include "url/gurl.h" @@ -55,6 +57,8 @@ void UserScriptSet::GetActiveExtensionIds( for (ScopedVector<UserScript>::const_iterator iter = scripts_.begin(); iter != scripts_.end(); ++iter) { + if ((*iter)->host_id().type() != HostID::EXTENSIONS) + continue; DCHECK(!(*iter)->extension_id().empty()); ids->insert((*iter)->extension_id()); } @@ -69,16 +73,12 @@ void UserScriptSet::GetInjections( for (ScopedVector<UserScript>::const_iterator iter = scripts_.begin(); iter != scripts_.end(); ++iter) { - const Extension* extension = extensions_->GetByID((*iter)->extension_id()); - if (!extension) - continue; scoped_ptr<ScriptInjection> injection = GetInjectionForScript( *iter, web_frame, tab_id, run_location, document_url, - extension, false /* is_declarative */); if (injection.get()) injections->push_back(injection.release()); @@ -155,8 +155,7 @@ scoped_ptr<ScriptInjection> UserScriptSet::GetDeclarativeScriptInjection( blink::WebFrame* web_frame, int tab_id, UserScript::RunLocation run_location, - const GURL& document_url, - const Extension* extension) { + const GURL& document_url) { for (ScopedVector<UserScript>::const_iterator it = scripts_.begin(); it != scripts_.end(); ++it) { @@ -166,7 +165,6 @@ scoped_ptr<ScriptInjection> UserScriptSet::GetDeclarativeScriptInjection( tab_id, run_location, document_url, - extension, true /* is_declarative */); } } @@ -181,9 +179,20 @@ scoped_ptr<ScriptInjection> UserScriptSet::GetInjectionForScript( int tab_id, UserScript::RunLocation run_location, const GURL& document_url, - const Extension* extension, bool is_declarative) { scoped_ptr<ScriptInjection> injection; + scoped_ptr<const InjectionHost> injection_host; + + const HostID& host_id = script->host_id(); + if (host_id.type() == HostID::EXTENSIONS) { + injection_host = ExtensionInjectionHost::Create(host_id.id(), extensions_); + if (!injection_host) + return injection.Pass(); + } else { + DCHECK_EQ(host_id.type(), HostID::WEBUI); + injection_host.reset(new WebUIInjectionHost(host_id)); + } + if (web_frame->parent() && !script->match_all_frames()) return injection.Pass(); // Only match subframes if the script declared it. @@ -196,11 +205,8 @@ scoped_ptr<ScriptInjection> UserScriptSet::GetInjectionForScript( scoped_ptr<ScriptInjector> injector(new UserScriptInjector(script, this, is_declarative)); - HostID host_id(HostID::EXTENSIONS, extension->id()); - ExtensionInjectionHost extension_injection_host( - make_scoped_refptr<const Extension>(extension)); if (injector->CanExecuteOnFrame( - &extension_injection_host, + injection_host.get(), web_frame, -1, // Content scripts are not tab-specific. web_frame->top()->document().url()) == @@ -216,7 +222,7 @@ scoped_ptr<ScriptInjection> UserScriptSet::GetInjectionForScript( injection.reset(new ScriptInjection( injector.Pass(), web_frame->toWebLocalFrame(), - host_id, + injection_host.Pass(), run_location, tab_id)); } diff --git a/extensions/renderer/user_script_set.h b/extensions/renderer/user_script_set.h index e8d48f9..ab2b585 100644 --- a/extensions/renderer/user_script_set.h +++ b/extensions/renderer/user_script_set.h @@ -24,7 +24,6 @@ class WebFrame; } namespace extensions { -class Extension; class ExtensionSet; class ScriptInjection; @@ -64,8 +63,7 @@ class UserScriptSet { blink::WebFrame* web_frame, int tab_id, UserScript::RunLocation run_location, - const GURL& document_url, - const Extension* extension); + const GURL& document_url); // Updates scripts given the shared memory region containing user scripts. // Returns true if the scripts were successfully updated. @@ -83,7 +81,6 @@ class UserScriptSet { int tab_id, UserScript::RunLocation run_location, const GURL& document_url, - const Extension* extension, bool is_declarative); // Shared memory containing raw script data. diff --git a/extensions/renderer/user_script_set_manager.cc b/extensions/renderer/user_script_set_manager.cc index 4379bab..2a6425f 100644 --- a/extensions/renderer/user_script_set_manager.cc +++ b/extensions/renderer/user_script_set_manager.cc @@ -38,9 +38,9 @@ UserScriptSetManager::GetInjectionForDeclarativeScript( blink::WebFrame* web_frame, int tab_id, const GURL& url, - const Extension* extension) { + const std::string& extension_id) { UserScriptSet* user_script_set = - GetProgrammaticScriptsByExtension(extension->id()); + GetProgrammaticScriptsByExtension(extension_id); if (!user_script_set) return scoped_ptr<ScriptInjection>(); @@ -49,8 +49,7 @@ UserScriptSetManager::GetInjectionForDeclarativeScript( web_frame, tab_id, UserScript::BROWSER_DRIVEN, - url, - extension); + url); } bool UserScriptSetManager::OnControlMessageReceived( diff --git a/extensions/renderer/user_script_set_manager.h b/extensions/renderer/user_script_set_manager.h index d102ea3..4b5e4f0 100644 --- a/extensions/renderer/user_script_set_manager.h +++ b/extensions/renderer/user_script_set_manager.h @@ -56,14 +56,15 @@ class UserScriptSetManager : public content::RenderProcessObserver { void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); - // Looks up the script injection associated with |script_id| and |extension| - // in the context of the given |web_frame|, |tab_id|, and |url|. + // Looks up the script injection associated with |script_id| and + // |extension_id| in the context of the given |web_frame|, |tab_id|, + // and |url|. scoped_ptr<ScriptInjection> GetInjectionForDeclarativeScript( int script_id, blink::WebFrame* web_frame, int tab_id, const GURL& url, - const Extension* extension); + const std::string& extension_id); // Append all injections from |static_scripts| and each of // |programmatic_scripts_| to |injections|. diff --git a/extensions/renderer/web_ui_injection_host.cc b/extensions/renderer/web_ui_injection_host.cc new file mode 100644 index 0000000..334358a --- /dev/null +++ b/extensions/renderer/web_ui_injection_host.cc @@ -0,0 +1,41 @@ +// Copyright 2015 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 "extensions/renderer/web_ui_injection_host.h" + +WebUIInjectionHost::WebUIInjectionHost(const HostID& host_id) + : InjectionHost(host_id), + url_(host_id.id()) { +} + +WebUIInjectionHost::~WebUIInjectionHost() { +} + + +std::string WebUIInjectionHost::GetContentSecurityPolicy() const { + return std::string(); +} + +const GURL& WebUIInjectionHost::url() const { + return url_; +} + +const std::string& WebUIInjectionHost::name() const { + return id().id(); +} + +extensions::PermissionsData::AccessType WebUIInjectionHost::CanExecuteOnFrame( + const GURL& document_url, + const GURL& top_frame_url, + int tab_id, + bool is_declarative) const { + // Content scripts are allowed to inject on webviews created by WebUI. + return extensions::PermissionsData::AccessType::ACCESS_ALLOWED; +} + +bool WebUIInjectionHost::ShouldNotifyBrowserOfInjection() const { + // We don't notify browser of any injection made from WebUI, since the + // decision for injection is made in the render. + return false; +} diff --git a/extensions/renderer/web_ui_injection_host.h b/extensions/renderer/web_ui_injection_host.h new file mode 100644 index 0000000..c81dd5d --- /dev/null +++ b/extensions/renderer/web_ui_injection_host.h @@ -0,0 +1,33 @@ +// Copyright 2015 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 EXTENSIONS_RENDERER_WEBUI_INJECTION_HOST_H_ +#define EXTENSIONS_RENDERER_WEBUI_INJECTION_HOST_H_ + +#include "extensions/renderer/injection_host.h" + +class WebUIInjectionHost : public InjectionHost { + public: + WebUIInjectionHost(const HostID& host_id); + ~WebUIInjectionHost() override; + + private: + // InjectionHost: + std::string GetContentSecurityPolicy() const override; + const GURL& url() const override; + const std::string& name() const override; + extensions::PermissionsData::AccessType CanExecuteOnFrame( + const GURL& document_url, + const GURL& top_frame_url, + int tab_id, + bool is_declarative) const override; + bool ShouldNotifyBrowserOfInjection() const override; + + private: + GURL url_; + + DISALLOW_COPY_AND_ASSIGN(WebUIInjectionHost); +}; + +#endif // EXTENSIONS_RENDERER_WEBUI_INJECTION_HOST_H_ |