Index: extensions/renderer/script_injection_manager.cc |
diff --git a/extensions/renderer/script_injection_manager.cc b/extensions/renderer/script_injection_manager.cc |
index aa0f5d32b9aa35ee7c4cbb85461f79899b169c6e..ad387a2b257cd6afca971c5fd572f43426a16588 100644 |
--- a/extensions/renderer/script_injection_manager.cc |
+++ b/extensions/renderer/script_injection_manager.cc |
@@ -27,6 +27,7 @@ |
#include "ipc/ipc_message_macros.h" |
#include "third_party/WebKit/public/web/WebDocument.h" |
#include "third_party/WebKit/public/web/WebFrame.h" |
+#include "third_party/WebKit/public/web/WebKit.h" |
#include "third_party/WebKit/public/web/WebLocalFrame.h" |
#include "third_party/WebKit/public/web/WebView.h" |
#include "url/gurl.h" |
@@ -67,6 +68,8 @@ class ScriptInjectionManager::RFOHelper : public content::RenderFrameObserver { |
~RFOHelper() override; |
private: |
+ class ScheduledScriptInjection; |
+ |
// RenderFrameObserver implementation. |
bool OnMessageReceived(const IPC::Message& message) override; |
void DidCreateNewDocument() override; |
@@ -111,6 +114,39 @@ ScriptInjectionManager::RFOHelper::RFOHelper(content::RenderFrame* render_frame, |
ScriptInjectionManager::RFOHelper::~RFOHelper() { |
} |
+// This class schedules a script injection at |run_location| in the frame. |
+class ScriptInjectionManager::RFOHelper::ScheduledScriptInjection { |
+ public: |
+ ScheduledScriptInjection(base::WeakPtr<RFOHelper> rfo_helper_weak, |
+ UserScript::RunLocation run_location) |
+ : rfo_helper_weak_(rfo_helper_weak), run_location_(run_location) { |
+ v8::Isolate* isolate = blink::mainThreadIsolate(); |
+ isolate->EnqueueMicrotask(RunScheduledScriptInjection, this); |
+ } |
+ |
+ private: |
+ // This is called once when V8 runs the microtask. |
+ static void RunScheduledScriptInjection(void* data) { |
+ ScheduledScriptInjection* scheduled_script_injection = |
+ static_cast<ScheduledScriptInjection*>(data); |
+ scheduled_script_injection->StartInjectScripts(); |
+ delete scheduled_script_injection; |
+ } |
+ |
+ void StartInjectScripts() { |
+ RFOHelper* rfo_helper = rfo_helper_weak_.get(); |
+ if (!rfo_helper) |
+ return; |
+ rfo_helper->manager_->StartInjectScripts(rfo_helper->render_frame(), |
+ run_location_); |
+ } |
+ |
+ base::WeakPtr<RFOHelper> rfo_helper_weak_; |
+ UserScript::RunLocation run_location_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ScheduledScriptInjection); |
+}; |
+ |
bool ScriptInjectionManager::RFOHelper::OnMessageReceived( |
const IPC::Message& message) { |
bool handled = true; |
@@ -136,7 +172,8 @@ void ScriptInjectionManager::RFOHelper::DidCreateNewDocument() { |
} |
void ScriptInjectionManager::RFOHelper::DidCreateDocumentElement() { |
- manager_->StartInjectScripts(render_frame(), UserScript::DOCUMENT_START); |
+ new ScheduledScriptInjection( |
+ weak_factory_.GetWeakPtr(), UserScript::DOCUMENT_START); |
} |
void ScriptInjectionManager::RFOHelper::DidFailProvisionalLoad( |
@@ -162,7 +199,9 @@ void ScriptInjectionManager::RFOHelper::DidFailProvisionalLoad( |
void ScriptInjectionManager::RFOHelper::DidFinishDocumentLoad() { |
DCHECK(content::RenderThread::Get()); |
- manager_->StartInjectScripts(render_frame(), UserScript::DOCUMENT_END); |
+ new ScheduledScriptInjection( |
+ weak_factory_.GetWeakPtr(), UserScript::DOCUMENT_END); |
+ |
// We try to run idle in two places: here and DidFinishLoad. |
// DidFinishDocumentLoad() corresponds to completing the document's load, |
// whereas DidFinishLoad corresponds to completing the document and all |
@@ -227,7 +266,8 @@ void ScriptInjectionManager::RFOHelper::RunIdle() { |
// had idle run since the task to RunIdle() was posted. |
if (should_run_idle_) { |
should_run_idle_ = false; |
- manager_->StartInjectScripts(render_frame(), UserScript::DOCUMENT_IDLE); |
+ new ScheduledScriptInjection( |
+ weak_factory_.GetWeakPtr(), UserScript::DOCUMENT_IDLE); |
} |
} |