1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// found in the LICENSE file. 4116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/renderer/script_injection_manager.h" 6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/bind.h" 8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/memory/weak_ptr.h" 9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/values.h" 10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/renderer/render_view.h" 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/renderer/render_view_observer.h" 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/common/extension.h" 13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/common/extension_messages.h" 14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/common/extension_set.h" 15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/renderer/extension_helper.h" 16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/renderer/programmatic_script_injector.h" 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/renderer/script_injection.h" 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/renderer/scripts_run_info.h" 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ipc/ipc_message_macros.h" 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/WebKit/public/web/WebDocument.h" 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "third_party/WebKit/public/web/WebFrame.h" 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "third_party/WebKit/public/web/WebLocalFrame.h" 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "third_party/WebKit/public/web/WebView.h" 24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "url/gurl.h" 25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 26116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace extensions { 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 28116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace { 29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// The length of time to wait after the DOM is complete to try and run user 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// scripts. 32116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst int kScriptIdleTimeoutInMs = 200; 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass ScriptInjectionManager::RVOHelper : public content::RenderViewObserver { 37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public: 38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch RVOHelper(content::RenderView* render_view, ScriptInjectionManager* manager); 39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual ~RVOHelper(); 40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private: 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // RenderViewObserver implementation. 43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual void DidCreateDocumentElement(blink::WebLocalFrame* frame) OVERRIDE; 45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual void DidFinishDocumentLoad(blink::WebLocalFrame* frame) OVERRIDE; 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual void DidFinishLoad(blink::WebLocalFrame* frame) OVERRIDE; 47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual void DidStartProvisionalLoad(blink::WebLocalFrame* frame) OVERRIDE; 48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual void FrameDetached(blink::WebFrame* frame) OVERRIDE; 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual void OnDestruct() OVERRIDE; 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual void OnExecuteCode(const ExtensionMsg_ExecuteCode_Params& params); 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual void OnExecuteDeclarativeScript(int tab_id, 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ExtensionId& extension_id, 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int script_id, 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const GURL& url); 56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual void OnPermitScriptInjection(int64 request_id); 57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Tells the ScriptInjectionManager to run tasks associated with 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // document_idle. 60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void RunIdle(blink::WebFrame* frame); 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Indicate that the given |frame| is no longer valid because it is starting 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // a new load or closing. 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void InvalidateFrame(blink::WebFrame* frame); 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The owning ScriptInjectionManager. 67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ScriptInjectionManager* manager_; 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The set of frames that we are about to notify for DOCUMENT_IDLE. We keep 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // a set of those that are valid, so we don't notify that an invalid frame 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // became idle. 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::set<blink::WebFrame*> pending_idle_frames_; 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::WeakPtrFactory<RVOHelper> weak_factory_; 75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}; 76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 77116680a4aac90f2aa7413d9095a592090648e557Ben MurdochScriptInjectionManager::RVOHelper::RVOHelper( 78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch content::RenderView* render_view, 79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ScriptInjectionManager* manager) 80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : content::RenderViewObserver(render_view), 81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch manager_(manager), 82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch weak_factory_(this) { 83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 85116680a4aac90f2aa7413d9095a592090648e557Ben MurdochScriptInjectionManager::RVOHelper::~RVOHelper() { 86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 88116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool ScriptInjectionManager::RVOHelper::OnMessageReceived( 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const IPC::Message& message) { 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool handled = true; 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IPC_BEGIN_MESSAGE_MAP(ScriptInjectionManager::RVOHelper, message) 92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IPC_MESSAGE_HANDLER(ExtensionMsg_ExecuteCode, OnExecuteCode) 93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IPC_MESSAGE_HANDLER(ExtensionMsg_PermitScriptInjection, 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch OnPermitScriptInjection) 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_HANDLER(ExtensionMsg_ExecuteDeclarativeScript, 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnExecuteDeclarativeScript) 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IPC_MESSAGE_UNHANDLED(handled = false) 98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IPC_END_MESSAGE_MAP() 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return handled; 100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 102116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ScriptInjectionManager::RVOHelper::DidCreateDocumentElement( 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blink::WebLocalFrame* frame) { 104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch manager_->InjectScripts(frame, UserScript::DOCUMENT_START); 105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 107116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ScriptInjectionManager::RVOHelper::DidFinishDocumentLoad( 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blink::WebLocalFrame* frame) { 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch manager_->InjectScripts(frame, UserScript::DOCUMENT_END); 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pending_idle_frames_.insert(frame); 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // We try to run idle in two places: here and DidFinishLoad. 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // DidFinishDocumentLoad() corresponds to completing the document's load, 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // whereas DidFinishLoad corresponds to completing the document and all 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // subresources' load. We don't want to hold up script injection for a 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // particularly slow subresource, so we set a delayed task from here - but if 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // we finish everything before that point (i.e., DidFinishLoad() is 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // triggered), then there's no reason to keep waiting. 118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::MessageLoop::current()->PostDelayedTask( 119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FROM_HERE, 120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&ScriptInjectionManager::RVOHelper::RunIdle, 121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch weak_factory_.GetWeakPtr(), 122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch frame), 123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::TimeDelta::FromMilliseconds(kScriptIdleTimeoutInMs)); 124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 126116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ScriptInjectionManager::RVOHelper::DidFinishLoad( 127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blink::WebLocalFrame* frame) { 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Ensure that we don't block any UI progress by running scripts. 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // We *don't* add the frame to |pending_idle_frames_| here because 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // DidFinishDocumentLoad should strictly come before DidFinishLoad, so the 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // first posted task to RunIdle() pops it out of the set. This ensures we 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // don't try to run idle twice. 133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::MessageLoop::current()->PostTask( 134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FROM_HERE, 135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&ScriptInjectionManager::RVOHelper::RunIdle, 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch weak_factory_.GetWeakPtr(), 137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch frame)); 138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ScriptInjectionManager::RVOHelper::DidStartProvisionalLoad( 141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blink::WebLocalFrame* frame) { 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // We're starting a new load - invalidate. 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) InvalidateFrame(frame); 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ScriptInjectionManager::RVOHelper::FrameDetached(blink::WebFrame* frame) { 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The frame is closing - invalidate. 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) InvalidateFrame(frame); 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ScriptInjectionManager::RVOHelper::OnDestruct() { 152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch manager_->RemoveObserver(this); 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 155116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ScriptInjectionManager::RVOHelper::OnExecuteCode( 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ExtensionMsg_ExecuteCode_Params& params) { 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch manager_->HandleExecuteCode(params, render_view()); 158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ScriptInjectionManager::RVOHelper::OnExecuteDeclarativeScript( 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int tab_id, 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ExtensionId& extension_id, 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int script_id, 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const GURL& url) { 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci blink::WebFrame* main_frame = render_view()->GetWebView()->mainFrame(); 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(main_frame); 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(markdittmer): This would be cleaner if we compared page_ids instead. 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Begin script injeciton workflow only if the current URL is identical to 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the one that matched declarative conditions in the browser. 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (main_frame->top()->document().url() == url) { 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manager_->HandleExecuteDeclarativeScript(main_frame, 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci tab_id, 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension_id, 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci script_id, 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url); 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 180116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ScriptInjectionManager::RVOHelper::OnPermitScriptInjection( 181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int64 request_id) { 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch manager_->HandlePermitScriptInjection(request_id); 183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 185116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ScriptInjectionManager::RVOHelper::RunIdle(blink::WebFrame* frame) { 1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Only notify the manager if the frame hasn't either been removed or already 1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // had idle run since the task to RunIdle() was posted. 1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (pending_idle_frames_.count(frame) > 0) { 1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) manager_->InjectScripts(frame, UserScript::DOCUMENT_IDLE); 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pending_idle_frames_.erase(frame); 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ScriptInjectionManager::RVOHelper::InvalidateFrame( 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) blink::WebFrame* frame) { 1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pending_idle_frames_.erase(frame); 1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) manager_->InvalidateForFrame(frame); 198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 200116680a4aac90f2aa7413d9095a592090648e557Ben MurdochScriptInjectionManager::ScriptInjectionManager( 201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ExtensionSet* extensions, 2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) UserScriptSetManager* user_script_set_manager) 203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : extensions_(extensions), 2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) user_script_set_manager_(user_script_set_manager), 2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) user_script_set_manager_observer_(this) { 2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) user_script_set_manager_observer_.Add(user_script_set_manager_); 207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 209116680a4aac90f2aa7413d9095a592090648e557Ben MurdochScriptInjectionManager::~ScriptInjectionManager() { 210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 212116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ScriptInjectionManager::OnRenderViewCreated( 213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch content::RenderView* render_view) { 214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rvo_helpers_.push_back(new RVOHelper(render_view, this)); 215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 217116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ScriptInjectionManager::OnUserScriptsUpdated( 218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::set<std::string>& changed_extensions, 219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::vector<UserScript*>& scripts) { 220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (ScopedVector<ScriptInjection>::iterator iter = 221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_injections_.begin(); 222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch iter != pending_injections_.end();) { 223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (changed_extensions.count((*iter)->extension_id()) > 0) 224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch iter = pending_injections_.erase(iter); 225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch else 226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++iter; 227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 230116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ScriptInjectionManager::RemoveObserver(RVOHelper* helper) { 231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (ScopedVector<RVOHelper>::iterator iter = rvo_helpers_.begin(); 232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch iter != rvo_helpers_.end(); 233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++iter) { 234116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (*iter == helper) { 235116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rvo_helpers_.erase(iter); 236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch break; 237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 241116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ScriptInjectionManager::InvalidateForFrame(blink::WebFrame* frame) { 242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (ScopedVector<ScriptInjection>::iterator iter = 243116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_injections_.begin(); 244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch iter != pending_injections_.end();) { 245116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if ((*iter)->web_frame() == frame) 246116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch iter = pending_injections_.erase(iter); 247116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch else 248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++iter; 249116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 250116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 251116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch frame_statuses_.erase(frame); 252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 254116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ScriptInjectionManager::InjectScripts( 255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blink::WebFrame* frame, UserScript::RunLocation run_location) { 256116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FrameStatusMap::iterator iter = frame_statuses_.find(frame); 2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // We also don't execute if we detect that the run location is somehow out of 2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // order. This can happen if: 2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // - The first run location reported for the frame isn't DOCUMENT_START, or 2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // - The run location reported doesn't immediately follow the previous 2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // reported run location. 2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // We don't want to run because extensions may have requirements that scripts 2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // running in an earlier run location have run by the time a later script 2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // runs. Better to just not run. 2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if ((iter == frame_statuses_.end() && 2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) run_location != UserScript::DOCUMENT_START) || 2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (iter != frame_statuses_.end() && run_location - iter->second > 1)) { 2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // We also invalidate the frame, because the run order of pending injections 2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // may also be bad. 2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) InvalidateForFrame(frame); 2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else if (iter != frame_statuses_.end() && iter->second > run_location) { 2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Certain run location signals (like DidCreateDocumentElement) can happen 2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // multiple times. Ignore the subsequent signals. 2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 276116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 277116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Otherwise, all is right in the world, and we can get on with the 2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // injections! 2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) frame_statuses_[frame] = run_location; 2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 283116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Inject any scripts that were waiting for the right run location. 284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ScriptsRunInfo scripts_run_info; 285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (ScopedVector<ScriptInjection>::iterator iter = 286116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_injections_.begin(); 287116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch iter != pending_injections_.end();) { 288116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if ((*iter)->web_frame() == frame && 289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch (*iter)->TryToInject(run_location, 290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extensions_->GetByID((*iter)->extension_id()), 291116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &scripts_run_info)) { 292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch iter = pending_injections_.erase(iter); 293116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 294116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++iter; 295116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 296116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 298116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Try to inject any user scripts that should run for this location. If they 299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // don't complete their injection (for example, waiting for a permission 300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // response) then they will be added to |pending_injections_|. 301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ScopedVector<ScriptInjection> user_script_injections; 302116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int tab_id = ExtensionHelper::Get(content::RenderView::FromWebView( 303116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch frame->top()->view()))->tab_id(); 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) user_script_set_manager_->GetAllInjections( 305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &user_script_injections, frame, tab_id, run_location); 306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (ScopedVector<ScriptInjection>::iterator iter = 307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch user_script_injections.begin(); 308116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch iter != user_script_injections.end();) { 309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<ScriptInjection> injection(*iter); 310116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch iter = user_script_injections.weak_erase(iter); 311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!injection->TryToInject(run_location, 312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extensions_->GetByID(injection->extension_id()), 313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &scripts_run_info)) { 314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_injections_.push_back(injection.release()); 315116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 317116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 318116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scripts_run_info.LogRun(frame, run_location); 319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 321116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ScriptInjectionManager::HandleExecuteCode( 322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ExtensionMsg_ExecuteCode_Params& params, 323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch content::RenderView* render_view) { 3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(dcheng): Not sure how this can happen today. In an OOPI world, it 3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // would indicate a logic error--the browser must direct this request to the 3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // right renderer process to begin with. 3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci blink::WebLocalFrame* main_frame = 3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_view->GetWebView()->mainFrame()->toWebLocalFrame(); 329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!main_frame) { 330116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch render_view->Send( 331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new ExtensionHostMsg_ExecuteCodeFinished(render_view->GetRoutingID(), 332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch params.request_id, 333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch "No main frame", 334116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GURL(std::string()), 335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::ListValue())); 336116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 337116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<ScriptInjection> injection(new ScriptInjection( 340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<ScriptInjector>( 341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new ProgrammaticScriptInjector(params, main_frame)), 342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch main_frame, 343116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch params.extension_id, 344116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch static_cast<UserScript::RunLocation>(params.run_at), 345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ExtensionHelper::Get(render_view)->tab_id())); 346116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ScriptsRunInfo scripts_run_info; 348116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FrameStatusMap::const_iterator iter = frame_statuses_.find(main_frame); 349116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!injection->TryToInject( 350116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch iter == frame_statuses_.end() ? UserScript::UNDEFINED : iter->second, 351116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extensions_->GetByID(injection->extension_id()), 352116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &scripts_run_info)) { 353116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_injections_.push_back(injection.release()); 354116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 356116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ScriptInjectionManager::HandleExecuteDeclarativeScript( 3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci blink::WebFrame* web_frame, 3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int tab_id, 3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ExtensionId& extension_id, 3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int script_id, 3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const GURL& url) { 3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Extension* extension = extensions_->GetByID(extension_id); 3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(dcheng): This function signature should really be a WebLocalFrame, 3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // rather than trying to coerce it here. 3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<ScriptInjection> injection = 3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci user_script_set_manager_->GetInjectionForDeclarativeScript( 3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci script_id, 3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci web_frame->toWebLocalFrame(), 3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci tab_id, 3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url, 3721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension); 3731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (injection.get()) { 3741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ScriptsRunInfo scripts_run_info; 3751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(markdittmer): Use return value of TryToInject for error handling. 3761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci injection->TryToInject(UserScript::BROWSER_DRIVEN, 3771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension, 3781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &scripts_run_info); 3791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scripts_run_info.LogRun(web_frame, UserScript::BROWSER_DRIVEN); 3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 383116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ScriptInjectionManager::HandlePermitScriptInjection(int64 request_id) { 384116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ScopedVector<ScriptInjection>::iterator iter = 385116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_injections_.begin(); 386116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (; iter != pending_injections_.end(); ++iter) { 387116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if ((*iter)->request_id() == request_id) 388116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch break; 389116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 390116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (iter == pending_injections_.end()) 391116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 392116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 393116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // At this point, because the request is present in pending_injections_, we 394116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // know that this is the same page that issued the request (otherwise, 395116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // RVOHelper's DidStartProvisionalLoad callback would have caused it to be 396116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // cleared out). 397116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 398116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<ScriptInjection> injection(*iter); 399116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_injections_.weak_erase(iter); 400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ScriptsRunInfo scripts_run_info; 402116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (injection->OnPermissionGranted(extensions_->GetByID( 403116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch injection->extension_id()), 404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &scripts_run_info)) { 405116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scripts_run_info.LogRun(injection->web_frame(), UserScript::RUN_DEFERRED); 406116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 407116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 408116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 409116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace extensions 410