blob: 895e25a92ebc5d967db784f49596881e711a09f8 [file] [log] [blame]
[email protected]ac2f89372014-06-23 21:44:251// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "extensions/renderer/script_injection_manager.h"
6
rdevlin.cronin1463eeaf2014-12-11 18:06:567#include "base/auto_reset.h"
[email protected]ac2f89372014-06-23 21:44:258#include "base/bind.h"
9#include "base/memory/weak_ptr.h"
[email protected]ac2f89372014-06-23 21:44:2510#include "base/values.h"
rdevlin.cronin4bb32d72015-06-02 21:55:0111#include "content/public/renderer/render_frame.h"
12#include "content/public/renderer/render_frame_observer.h"
alexclarke5f9af5642015-01-09 19:24:3113#include "content/public/renderer/render_thread.h"
[email protected]ac2f89372014-06-23 21:44:2514#include "extensions/common/extension.h"
15#include "extensions/common/extension_messages.h"
16#include "extensions/common/extension_set.h"
rdevlin.croninb67a34772015-06-04 16:32:3817#include "extensions/renderer/extension_frame_helper.h"
hanxia5c856cf2015-02-13 20:51:5818#include "extensions/renderer/extension_injection_host.h"
[email protected]c11e6592014-06-27 17:07:3419#include "extensions/renderer/programmatic_script_injector.h"
annekao6572d5c2015-08-19 16:13:3620#include "extensions/renderer/renderer_extension_registry.h"
[email protected]c11e6592014-06-27 17:07:3421#include "extensions/renderer/script_injection.h"
22#include "extensions/renderer/scripts_run_info.h"
hanxi79f7a572015-03-09 20:46:5923#include "extensions/renderer/web_ui_injection_host.h"
[email protected]ac2f89372014-06-23 21:44:2524#include "ipc/ipc_message_macros.h"
markdittmer9ea140f2014-08-29 02:46:1525#include "third_party/WebKit/public/web/WebDocument.h"
[email protected]ac2f89372014-06-23 21:44:2526#include "third_party/WebKit/public/web/WebFrame.h"
27#include "third_party/WebKit/public/web/WebLocalFrame.h"
28#include "third_party/WebKit/public/web/WebView.h"
29#include "url/gurl.h"
30
31namespace extensions {
32
33namespace {
34
35// The length of time to wait after the DOM is complete to try and run user
36// scripts.
37const int kScriptIdleTimeoutInMs = 200;
38
rdevlin.cronin1463eeaf2014-12-11 18:06:5639// Returns the RunLocation that follows |run_location|.
40UserScript::RunLocation NextRunLocation(UserScript::RunLocation run_location) {
41 switch (run_location) {
42 case UserScript::DOCUMENT_START:
43 return UserScript::DOCUMENT_END;
44 case UserScript::DOCUMENT_END:
45 return UserScript::DOCUMENT_IDLE;
46 case UserScript::DOCUMENT_IDLE:
47 return UserScript::RUN_LOCATION_LAST;
48 case UserScript::UNDEFINED:
49 case UserScript::RUN_DEFERRED:
50 case UserScript::BROWSER_DRIVEN:
51 case UserScript::RUN_LOCATION_LAST:
52 break;
53 }
54 NOTREACHED();
55 return UserScript::RUN_LOCATION_LAST;
56}
57
[email protected]ac2f89372014-06-23 21:44:2558} // namespace
59
rdevlin.cronin4bb32d72015-06-02 21:55:0160class ScriptInjectionManager::RFOHelper : public content::RenderFrameObserver {
[email protected]ac2f89372014-06-23 21:44:2561 public:
rdevlin.cronin4bb32d72015-06-02 21:55:0162 RFOHelper(content::RenderFrame* render_frame,
63 ScriptInjectionManager* manager);
64 ~RFOHelper() override;
[email protected]ac2f89372014-06-23 21:44:2565
66 private:
rdevlin.cronin4bb32d72015-06-02 21:55:0167 // RenderFrameObserver implementation.
dcheng9168b2f2014-10-21 12:38:2468 bool OnMessageReceived(const IPC::Message& message) override;
rdevlin.cronin4bb32d72015-06-02 21:55:0169 void DidCreateNewDocument() override;
70 void DidCreateDocumentElement() override;
71 void DidFinishDocumentLoad() override;
72 void DidFinishLoad() override;
73 void FrameDetached() override;
dcheng9168b2f2014-10-21 12:38:2474 void OnDestruct() override;
[email protected]ac2f89372014-06-23 21:44:2575
76 virtual void OnExecuteCode(const ExtensionMsg_ExecuteCode_Params& params);
markdittmer9ea140f2014-08-29 02:46:1577 virtual void OnExecuteDeclarativeScript(int tab_id,
78 const ExtensionId& extension_id,
79 int script_id,
80 const GURL& url);
[email protected]ac2f89372014-06-23 21:44:2581 virtual void OnPermitScriptInjection(int64 request_id);
82
83 // Tells the ScriptInjectionManager to run tasks associated with
84 // document_idle.
rdevlin.cronin4bb32d72015-06-02 21:55:0185 void RunIdle();
[email protected]ac2f89372014-06-23 21:44:2586
rdevlin.cronin4bb32d72015-06-02 21:55:0187 // Indicate that the frame is no longer valid because it is starting
[email protected]5672620d2014-07-30 10:07:1788 // a new load or closing.
rdevlin.cronin3ae4a32012015-06-30 17:43:1989 void InvalidateAndResetFrame();
[email protected]5672620d2014-07-30 10:07:1790
91 // The owning ScriptInjectionManager.
[email protected]ac2f89372014-06-23 21:44:2592 ScriptInjectionManager* manager_;
[email protected]5672620d2014-07-30 10:07:1793
rdevlin.cronin3ae4a32012015-06-30 17:43:1994 bool should_run_idle_;
[email protected]5672620d2014-07-30 10:07:1795
rdevlin.cronin4bb32d72015-06-02 21:55:0196 base::WeakPtrFactory<RFOHelper> weak_factory_;
[email protected]ac2f89372014-06-23 21:44:2597};
98
rdevlin.cronin3ae4a32012015-06-30 17:43:1999ScriptInjectionManager::RFOHelper::RFOHelper(content::RenderFrame* render_frame,
100 ScriptInjectionManager* manager)
rdevlin.cronin4bb32d72015-06-02 21:55:01101 : content::RenderFrameObserver(render_frame),
[email protected]ac2f89372014-06-23 21:44:25102 manager_(manager),
rdevlin.cronin3ae4a32012015-06-30 17:43:19103 should_run_idle_(true),
[email protected]ac2f89372014-06-23 21:44:25104 weak_factory_(this) {
105}
106
rdevlin.cronin4bb32d72015-06-02 21:55:01107ScriptInjectionManager::RFOHelper::~RFOHelper() {
[email protected]ac2f89372014-06-23 21:44:25108}
109
rdevlin.cronin4bb32d72015-06-02 21:55:01110bool ScriptInjectionManager::RFOHelper::OnMessageReceived(
[email protected]ac2f89372014-06-23 21:44:25111 const IPC::Message& message) {
112 bool handled = true;
rdevlin.cronin4bb32d72015-06-02 21:55:01113 IPC_BEGIN_MESSAGE_MAP(ScriptInjectionManager::RFOHelper, message)
[email protected]ac2f89372014-06-23 21:44:25114 IPC_MESSAGE_HANDLER(ExtensionMsg_ExecuteCode, OnExecuteCode)
115 IPC_MESSAGE_HANDLER(ExtensionMsg_PermitScriptInjection,
116 OnPermitScriptInjection)
markdittmer9ea140f2014-08-29 02:46:15117 IPC_MESSAGE_HANDLER(ExtensionMsg_ExecuteDeclarativeScript,
118 OnExecuteDeclarativeScript)
[email protected]ac2f89372014-06-23 21:44:25119 IPC_MESSAGE_UNHANDLED(handled = false)
120 IPC_END_MESSAGE_MAP()
121 return handled;
122}
123
rdevlin.cronin4bb32d72015-06-02 21:55:01124void ScriptInjectionManager::RFOHelper::DidCreateNewDocument() {
rob5ef11ff2014-11-17 23:56:20125 // A new document is going to be shown, so invalidate the old document state.
126 // Check that the frame's state is known before invalidating the frame,
127 // because it is possible that a script injection was scheduled before the
128 // page was loaded, e.g. by navigating to a javascript: URL before the page
129 // has loaded.
rdevlin.cronin4bb32d72015-06-02 21:55:01130 if (manager_->frame_statuses_.count(render_frame()) != 0)
rdevlin.cronin3ae4a32012015-06-30 17:43:19131 InvalidateAndResetFrame();
rob5ef11ff2014-11-17 23:56:20132}
133
rdevlin.cronin4bb32d72015-06-02 21:55:01134void ScriptInjectionManager::RFOHelper::DidCreateDocumentElement() {
135 manager_->StartInjectScripts(render_frame(), UserScript::DOCUMENT_START);
[email protected]ac2f89372014-06-23 21:44:25136}
137
rdevlin.cronin4bb32d72015-06-02 21:55:01138void ScriptInjectionManager::RFOHelper::DidFinishDocumentLoad() {
skyostiled8969c2015-07-20 16:57:08139 DCHECK(content::RenderThread::Get());
rdevlin.cronin4bb32d72015-06-02 21:55:01140 manager_->StartInjectScripts(render_frame(), UserScript::DOCUMENT_END);
[email protected]5672620d2014-07-30 10:07:17141 // We try to run idle in two places: here and DidFinishLoad.
142 // DidFinishDocumentLoad() corresponds to completing the document's load,
143 // whereas DidFinishLoad corresponds to completing the document and all
144 // subresources' load. We don't want to hold up script injection for a
145 // particularly slow subresource, so we set a delayed task from here - but if
146 // we finish everything before that point (i.e., DidFinishLoad() is
147 // triggered), then there's no reason to keep waiting.
skyostiled8969c2015-07-20 16:57:08148 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
[email protected]ac2f89372014-06-23 21:44:25149 FROM_HERE,
rdevlin.cronin4bb32d72015-06-02 21:55:01150 base::Bind(&ScriptInjectionManager::RFOHelper::RunIdle,
151 weak_factory_.GetWeakPtr()),
[email protected]ac2f89372014-06-23 21:44:25152 base::TimeDelta::FromMilliseconds(kScriptIdleTimeoutInMs));
153}
154
rdevlin.cronin4bb32d72015-06-02 21:55:01155void ScriptInjectionManager::RFOHelper::DidFinishLoad() {
skyostiled8969c2015-07-20 16:57:08156 DCHECK(content::RenderThread::Get());
[email protected]5672620d2014-07-30 10:07:17157 // Ensure that we don't block any UI progress by running scripts.
skyostiled8969c2015-07-20 16:57:08158 base::ThreadTaskRunnerHandle::Get()->PostTask(
[email protected]ac2f89372014-06-23 21:44:25159 FROM_HERE,
rdevlin.cronin4bb32d72015-06-02 21:55:01160 base::Bind(&ScriptInjectionManager::RFOHelper::RunIdle,
161 weak_factory_.GetWeakPtr()));
[email protected]ac2f89372014-06-23 21:44:25162}
163
rdevlin.cronin4bb32d72015-06-02 21:55:01164void ScriptInjectionManager::RFOHelper::FrameDetached() {
[email protected]5672620d2014-07-30 10:07:17165 // The frame is closing - invalidate.
rdevlin.cronin3ae4a32012015-06-30 17:43:19166 InvalidateAndResetFrame();
[email protected]ac2f89372014-06-23 21:44:25167}
168
rdevlin.cronin4bb32d72015-06-02 21:55:01169void ScriptInjectionManager::RFOHelper::OnDestruct() {
[email protected]ac2f89372014-06-23 21:44:25170 manager_->RemoveObserver(this);
171}
172
rdevlin.cronin4bb32d72015-06-02 21:55:01173void ScriptInjectionManager::RFOHelper::OnExecuteCode(
[email protected]ac2f89372014-06-23 21:44:25174 const ExtensionMsg_ExecuteCode_Params& params) {
rdevlin.cronin4bb32d72015-06-02 21:55:01175 manager_->HandleExecuteCode(params, render_frame());
[email protected]ac2f89372014-06-23 21:44:25176}
177
rdevlin.cronin4bb32d72015-06-02 21:55:01178void ScriptInjectionManager::RFOHelper::OnExecuteDeclarativeScript(
markdittmer9ea140f2014-08-29 02:46:15179 int tab_id,
180 const ExtensionId& extension_id,
181 int script_id,
182 const GURL& url) {
rdevlin.cronin45dca7f2015-06-08 19:47:03183 // TODO(markdittmer): URL-checking isn't the best security measure.
rdevlin.cronin4bb32d72015-06-02 21:55:01184 // Begin script injection workflow only if the current URL is identical to
markdittmer9ea140f2014-08-29 02:46:15185 // the one that matched declarative conditions in the browser.
rdevlin.cronin45dca7f2015-06-08 19:47:03186 if (render_frame()->GetWebFrame()->document().url() == url) {
rdevlin.cronin4bb32d72015-06-02 21:55:01187 manager_->HandleExecuteDeclarativeScript(render_frame(),
markdittmer9ea140f2014-08-29 02:46:15188 tab_id,
189 extension_id,
190 script_id,
191 url);
192 }
193}
194
rdevlin.cronin4bb32d72015-06-02 21:55:01195void ScriptInjectionManager::RFOHelper::OnPermitScriptInjection(
[email protected]ac2f89372014-06-23 21:44:25196 int64 request_id) {
197 manager_->HandlePermitScriptInjection(request_id);
198}
199
rdevlin.cronin4bb32d72015-06-02 21:55:01200void ScriptInjectionManager::RFOHelper::RunIdle() {
[email protected]5672620d2014-07-30 10:07:17201 // Only notify the manager if the frame hasn't either been removed or already
202 // had idle run since the task to RunIdle() was posted.
rdevlin.cronin3ae4a32012015-06-30 17:43:19203 if (should_run_idle_) {
204 should_run_idle_ = false;
rdevlin.cronin4bb32d72015-06-02 21:55:01205 manager_->StartInjectScripts(render_frame(), UserScript::DOCUMENT_IDLE);
[email protected]5672620d2014-07-30 10:07:17206 }
207}
208
rdevlin.cronin3ae4a32012015-06-30 17:43:19209void ScriptInjectionManager::RFOHelper::InvalidateAndResetFrame() {
210 // Invalidate any pending idle injections, and reset the frame inject on idle.
211 weak_factory_.InvalidateWeakPtrs();
212 // We reset to inject on idle, because the frame can be reused (in the case of
213 // navigation).
214 should_run_idle_ = true;
rdevlin.cronin4bb32d72015-06-02 21:55:01215 manager_->InvalidateForFrame(render_frame());
[email protected]ac2f89372014-06-23 21:44:25216}
217
218ScriptInjectionManager::ScriptInjectionManager(
[email protected]4c356902014-07-30 09:52:02219 UserScriptSetManager* user_script_set_manager)
annekao6572d5c2015-08-19 16:13:36220 : user_script_set_manager_(user_script_set_manager),
[email protected]4c356902014-07-30 09:52:02221 user_script_set_manager_observer_(this) {
222 user_script_set_manager_observer_.Add(user_script_set_manager_);
[email protected]ac2f89372014-06-23 21:44:25223}
224
225ScriptInjectionManager::~ScriptInjectionManager() {
226}
227
rdevlin.cronin4bb32d72015-06-02 21:55:01228void ScriptInjectionManager::OnRenderFrameCreated(
229 content::RenderFrame* render_frame) {
230 rfo_helpers_.push_back(new RFOHelper(render_frame, this));
[email protected]ac2f89372014-06-23 21:44:25231}
232
hanxi9b841662015-03-04 14:36:41233void ScriptInjectionManager::OnExtensionUnloaded(
234 const std::string& extension_id) {
235 for (auto iter = pending_injections_.begin();
236 iter != pending_injections_.end();) {
237 if ((*iter)->host_id().id() == extension_id) {
238 (*iter)->OnHostRemoved();
239 iter = pending_injections_.erase(iter);
240 } else {
241 ++iter;
242 }
243 }
kozyatinskiyc8bc9a582015-03-06 09:33:41244}
245
246void ScriptInjectionManager::OnInjectionFinished(
247 ScriptInjection* injection) {
248 ScopedVector<ScriptInjection>::iterator iter =
249 std::find(running_injections_.begin(),
250 running_injections_.end(),
251 injection);
252 if (iter != running_injections_.end())
253 running_injections_.erase(iter);
hanxi9b841662015-03-04 14:36:41254}
255
[email protected]ac2f89372014-06-23 21:44:25256void ScriptInjectionManager::OnUserScriptsUpdated(
hanxi3df97b22015-03-11 23:40:06257 const std::set<HostID>& changed_hosts,
[email protected]ac2f89372014-06-23 21:44:25258 const std::vector<UserScript*>& scripts) {
259 for (ScopedVector<ScriptInjection>::iterator iter =
260 pending_injections_.begin();
261 iter != pending_injections_.end();) {
hanxi3df97b22015-03-11 23:40:06262 if (changed_hosts.count((*iter)->host_id()) > 0)
[email protected]ac2f89372014-06-23 21:44:25263 iter = pending_injections_.erase(iter);
264 else
265 ++iter;
266 }
267}
268
rdevlin.cronin4bb32d72015-06-02 21:55:01269void ScriptInjectionManager::RemoveObserver(RFOHelper* helper) {
270 for (ScopedVector<RFOHelper>::iterator iter = rfo_helpers_.begin();
271 iter != rfo_helpers_.end();
[email protected]ac2f89372014-06-23 21:44:25272 ++iter) {
273 if (*iter == helper) {
rdevlin.cronin4bb32d72015-06-02 21:55:01274 rfo_helpers_.erase(iter);
[email protected]ac2f89372014-06-23 21:44:25275 break;
276 }
277 }
278}
279
rdevlin.cronin4bb32d72015-06-02 21:55:01280void ScriptInjectionManager::InvalidateForFrame(content::RenderFrame* frame) {
rdevlin.cronin3ae4a32012015-06-30 17:43:19281 // If the frame invalidated is the frame being injected into, we need to
282 // note it.
283 active_injection_frames_.erase(frame);
284
[email protected]ac2f89372014-06-23 21:44:25285 for (ScopedVector<ScriptInjection>::iterator iter =
286 pending_injections_.begin();
287 iter != pending_injections_.end();) {
rdevlin.cronin3e11c9862015-06-04 19:54:25288 if ((*iter)->render_frame() == frame)
[email protected]ac2f89372014-06-23 21:44:25289 iter = pending_injections_.erase(iter);
290 else
291 ++iter;
292 }
293
294 frame_statuses_.erase(frame);
295}
296
rdevlin.cronin1463eeaf2014-12-11 18:06:56297void ScriptInjectionManager::StartInjectScripts(
rdevlin.cronin4bb32d72015-06-02 21:55:01298 content::RenderFrame* frame,
299 UserScript::RunLocation run_location) {
[email protected]ac2f89372014-06-23 21:44:25300 FrameStatusMap::iterator iter = frame_statuses_.find(frame);
[email protected]5672620d2014-07-30 10:07:17301 // We also don't execute if we detect that the run location is somehow out of
302 // order. This can happen if:
303 // - The first run location reported for the frame isn't DOCUMENT_START, or
304 // - The run location reported doesn't immediately follow the previous
305 // reported run location.
306 // We don't want to run because extensions may have requirements that scripts
307 // running in an earlier run location have run by the time a later script
308 // runs. Better to just not run.
rdevlin.cronin1463eeaf2014-12-11 18:06:56309 // Note that we check run_location > NextRunLocation() in the second clause
310 // (as opposed to !=) because earlier signals (like DidCreateDocumentElement)
311 // can happen multiple times, so we can receive earlier/equal run locations.
[email protected]5672620d2014-07-30 10:07:17312 if ((iter == frame_statuses_.end() &&
313 run_location != UserScript::DOCUMENT_START) ||
rdevlin.cronin1463eeaf2014-12-11 18:06:56314 (iter != frame_statuses_.end() &&
315 run_location > NextRunLocation(iter->second))) {
[email protected]5672620d2014-07-30 10:07:17316 // We also invalidate the frame, because the run order of pending injections
317 // may also be bad.
318 InvalidateForFrame(frame);
319 return;
rdevlin.cronin1463eeaf2014-12-11 18:06:56320 } else if (iter != frame_statuses_.end() && iter->second >= run_location) {
[email protected]5672620d2014-07-30 10:07:17321 // Certain run location signals (like DidCreateDocumentElement) can happen
322 // multiple times. Ignore the subsequent signals.
323 return;
[email protected]ac2f89372014-06-23 21:44:25324 }
325
[email protected]5672620d2014-07-30 10:07:17326 // Otherwise, all is right in the world, and we can get on with the
327 // injections!
[email protected]5672620d2014-07-30 10:07:17328 frame_statuses_[frame] = run_location;
kozyatinskiyc8bc9a582015-03-06 09:33:41329 InjectScripts(frame, run_location);
rdevlin.cronin1463eeaf2014-12-11 18:06:56330}
331
332void ScriptInjectionManager::InjectScripts(
rdevlin.cronin4bb32d72015-06-02 21:55:01333 content::RenderFrame* frame,
rdevlin.cronin1463eeaf2014-12-11 18:06:56334 UserScript::RunLocation run_location) {
rdevlin.cronind63148dc2014-12-16 19:22:34335 // Find any injections that want to run on the given frame.
rdevlin.cronind63148dc2014-12-16 19:22:34336 ScopedVector<ScriptInjection> frame_injections;
[email protected]ac2f89372014-06-23 21:44:25337 for (ScopedVector<ScriptInjection>::iterator iter =
338 pending_injections_.begin();
339 iter != pending_injections_.end();) {
rdevlin.cronin3e11c9862015-06-04 19:54:25340 if ((*iter)->render_frame() == frame) {
rdevlin.cronind63148dc2014-12-16 19:22:34341 frame_injections.push_back(*iter);
342 iter = pending_injections_.weak_erase(iter);
[email protected]ac2f89372014-06-23 21:44:25343 } else {
344 ++iter;
345 }
346 }
347
rdevlin.cronind63148dc2014-12-16 19:22:34348 // Add any injections for user scripts.
rdevlin.croninb67a34772015-06-04 16:32:38349 int tab_id = ExtensionFrameHelper::Get(frame)->tab_id();
[email protected]4c356902014-07-30 09:52:02350 user_script_set_manager_->GetAllInjections(
rdevlin.cronin3e11c9862015-06-04 19:54:25351 &frame_injections, frame, tab_id, run_location);
rdevlin.cronind63148dc2014-12-16 19:22:34352
rdevlin.cronin3ae4a32012015-06-30 17:43:19353 // Note that we are running in |frame|.
354 active_injection_frames_.insert(frame);
355
356 ScriptsRunInfo scripts_run_info(frame, run_location);
kozyatinskiyc8bc9a582015-03-06 09:33:41357 std::vector<ScriptInjection*> released_injections;
358 frame_injections.release(&released_injections);
rdevlin.cronin3ae4a32012015-06-30 17:43:19359 for (ScriptInjection* injection : released_injections) {
360 // It's possible for the frame to be invalidated in the course of injection
361 // (if a script removes its own frame, for example). If this happens, abort.
362 if (!active_injection_frames_.count(frame))
363 break;
kozyatinskiyc8bc9a582015-03-06 09:33:41364 TryToInject(make_scoped_ptr(injection), run_location, &scripts_run_info);
rdevlin.cronin3ae4a32012015-06-30 17:43:19365 }
kozyatinskiyc8bc9a582015-03-06 09:33:41366
rdevlin.cronin3ae4a32012015-06-30 17:43:19367 // We are done running in the frame.
368 active_injection_frames_.erase(frame);
369
370 scripts_run_info.LogRun();
kozyatinskiyc8bc9a582015-03-06 09:33:41371}
372
373void ScriptInjectionManager::TryToInject(
374 scoped_ptr<ScriptInjection> injection,
375 UserScript::RunLocation run_location,
376 ScriptsRunInfo* scripts_run_info) {
377 // Try to inject the script. If the injection is waiting (i.e., for
378 // permission), add it to the list of pending injections. If the injection
379 // has blocked, add it to the list of running injections.
rdevlin.cronin4bb32d72015-06-02 21:55:01380 // The Unretained below is safe because this object owns all the
381 // ScriptInjections, so is guaranteed to outlive them.
kozyatinskiyc8bc9a582015-03-06 09:33:41382 switch (injection->TryToInject(
383 run_location,
384 scripts_run_info,
rdevlin.cronin4bb32d72015-06-02 21:55:01385 base::Bind(&ScriptInjectionManager::OnInjectionFinished,
386 base::Unretained(this)))) {
kozyatinskiyc8bc9a582015-03-06 09:33:41387 case ScriptInjection::INJECTION_WAITING:
vaibhav1.ad7332682015-05-27 05:45:43388 pending_injections_.push_back(injection.Pass());
rdevlin.cronind63148dc2014-12-16 19:22:34389 break;
kozyatinskiyc8bc9a582015-03-06 09:33:41390 case ScriptInjection::INJECTION_BLOCKED:
vaibhav1.ad7332682015-05-27 05:45:43391 running_injections_.push_back(injection.Pass());
kozyatinskiyc8bc9a582015-03-06 09:33:41392 break;
393 case ScriptInjection::INJECTION_FINISHED:
394 break;
[email protected]ac2f89372014-06-23 21:44:25395 }
[email protected]ac2f89372014-06-23 21:44:25396}
397
398void ScriptInjectionManager::HandleExecuteCode(
399 const ExtensionMsg_ExecuteCode_Params& params,
rdevlin.cronin4bb32d72015-06-02 21:55:01400 content::RenderFrame* render_frame) {
hanxi79f7a572015-03-09 20:46:59401 scoped_ptr<const InjectionHost> injection_host;
402 if (params.host_id.type() == HostID::EXTENSIONS) {
annekao6572d5c2015-08-19 16:13:36403 injection_host = ExtensionInjectionHost::Create(params.host_id.id());
hanxi79f7a572015-03-09 20:46:59404 if (!injection_host)
405 return;
406 } else if (params.host_id.type() == HostID::WEBUI) {
407 injection_host.reset(
408 new WebUIInjectionHost(params.host_id));
409 }
hanxi9b841662015-03-04 14:36:41410
[email protected]c11e6592014-06-27 17:07:34411 scoped_ptr<ScriptInjection> injection(new ScriptInjection(
412 scoped_ptr<ScriptInjector>(
rdevlin.cronin3e11c9862015-06-04 19:54:25413 new ProgrammaticScriptInjector(params, render_frame)),
414 render_frame,
hanxi79f7a572015-03-09 20:46:59415 injection_host.Pass(),
[email protected]c11e6592014-06-27 17:07:34416 static_cast<UserScript::RunLocation>(params.run_at),
rdevlin.croninb67a34772015-06-04 16:32:38417 ExtensionFrameHelper::Get(render_frame)->tab_id()));
[email protected]ac2f89372014-06-23 21:44:25418
rdevlin.cronin4bb32d72015-06-02 21:55:01419 FrameStatusMap::const_iterator iter = frame_statuses_.find(render_frame);
rdevlin.cronin3ae4a32012015-06-30 17:43:19420 UserScript::RunLocation run_location =
421 iter == frame_statuses_.end() ? UserScript::UNDEFINED : iter->second;
hanxia5c856cf2015-02-13 20:51:58422
rdevlin.cronin3ae4a32012015-06-30 17:43:19423 ScriptsRunInfo scripts_run_info(render_frame, run_location);
424 TryToInject(injection.Pass(), run_location, &scripts_run_info);
[email protected]ac2f89372014-06-23 21:44:25425}
426
markdittmer9ea140f2014-08-29 02:46:15427void ScriptInjectionManager::HandleExecuteDeclarativeScript(
rdevlin.cronin4bb32d72015-06-02 21:55:01428 content::RenderFrame* render_frame,
markdittmer9ea140f2014-08-29 02:46:15429 int tab_id,
430 const ExtensionId& extension_id,
431 int script_id,
432 const GURL& url) {
markdittmer9ea140f2014-08-29 02:46:15433 scoped_ptr<ScriptInjection> injection =
434 user_script_set_manager_->GetInjectionForDeclarativeScript(
435 script_id,
rdevlin.cronin3e11c9862015-06-04 19:54:25436 render_frame,
markdittmer9ea140f2014-08-29 02:46:15437 tab_id,
438 url,
hanxi9b841662015-03-04 14:36:41439 extension_id);
kozyatinskiyc8bc9a582015-03-06 09:33:41440 if (injection.get()) {
rdevlin.cronin3ae4a32012015-06-30 17:43:19441 ScriptsRunInfo scripts_run_info(render_frame, UserScript::BROWSER_DRIVEN);
markdittmer9ea140f2014-08-29 02:46:15442 // TODO(markdittmer): Use return value of TryToInject for error handling.
kozyatinskiyc8bc9a582015-03-06 09:33:41443 TryToInject(injection.Pass(),
444 UserScript::BROWSER_DRIVEN,
445 &scripts_run_info);
446
rdevlin.cronin3ae4a32012015-06-30 17:43:19447 scripts_run_info.LogRun();
markdittmer9ea140f2014-08-29 02:46:15448 }
449}
450
[email protected]d2056002014-07-03 06:18:06451void ScriptInjectionManager::HandlePermitScriptInjection(int64 request_id) {
[email protected]ac2f89372014-06-23 21:44:25452 ScopedVector<ScriptInjection>::iterator iter =
453 pending_injections_.begin();
454 for (; iter != pending_injections_.end(); ++iter) {
hanxi9b841662015-03-04 14:36:41455 if ((*iter)->request_id() == request_id) {
456 DCHECK((*iter)->host_id().type() == HostID::EXTENSIONS);
[email protected]ac2f89372014-06-23 21:44:25457 break;
hanxi9b841662015-03-04 14:36:41458 }
[email protected]ac2f89372014-06-23 21:44:25459 }
460 if (iter == pending_injections_.end())
461 return;
462
[email protected]d2056002014-07-03 06:18:06463 // At this point, because the request is present in pending_injections_, we
464 // know that this is the same page that issued the request (otherwise,
rdevlin.cronin4bb32d72015-06-02 21:55:01465 // RFOHelper's DidStartProvisionalLoad callback would have caused it to be
[email protected]d2056002014-07-03 06:18:06466 // cleared out).
467
[email protected]ac2f89372014-06-23 21:44:25468 scoped_ptr<ScriptInjection> injection(*iter);
469 pending_injections_.weak_erase(iter);
470
rdevlin.cronin3ae4a32012015-06-30 17:43:19471 ScriptsRunInfo scripts_run_info(injection->render_frame(),
472 UserScript::RUN_DEFERRED);
kozyatinskiyc8bc9a582015-03-06 09:33:41473 ScriptInjection::InjectionResult res = injection->OnPermissionGranted(
474 &scripts_run_info);
475 if (res == ScriptInjection::INJECTION_BLOCKED)
476 running_injections_.push_back(injection.Pass());
rdevlin.cronin3ae4a32012015-06-30 17:43:19477 scripts_run_info.LogRun();
[email protected]ac2f89372014-06-23 21:44:25478}
479
480} // namespace extensions