OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "extensions/renderer/script_injection_manager.h" | 5 #include "extensions/renderer/script_injection_manager.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
63 class ScriptInjectionManager::RFOHelper : public content::RenderFrameObserver { | 63 class ScriptInjectionManager::RFOHelper : public content::RenderFrameObserver { |
64 public: | 64 public: |
65 RFOHelper(content::RenderFrame* render_frame, | 65 RFOHelper(content::RenderFrame* render_frame, |
66 ScriptInjectionManager* manager); | 66 ScriptInjectionManager* manager); |
67 ~RFOHelper() override; | 67 ~RFOHelper() override; |
68 | 68 |
69 private: | 69 private: |
70 // RenderFrameObserver implementation. | 70 // RenderFrameObserver implementation. |
71 bool OnMessageReceived(const IPC::Message& message) override; | 71 bool OnMessageReceived(const IPC::Message& message) override; |
72 void DidCreateNewDocument() override; | 72 void DidCreateNewDocument() override; |
73 void DidCreateDocumentElement() override; | |
74 void DidFailProvisionalLoad(const blink::WebURLError& error) override; | 73 void DidFailProvisionalLoad(const blink::WebURLError& error) override; |
75 void DidFinishDocumentLoad() override; | 74 void DidFinishDocumentLoad() override; |
76 void DidFinishLoad() override; | 75 void DidFinishLoad() override; |
77 void FrameDetached() override; | 76 void FrameDetached() override; |
78 void OnDestruct() override; | 77 void OnDestruct() override; |
79 | 78 |
80 virtual void OnExecuteCode(const ExtensionMsg_ExecuteCode_Params& params); | 79 virtual void OnExecuteCode(const ExtensionMsg_ExecuteCode_Params& params); |
81 virtual void OnExecuteDeclarativeScript(int tab_id, | 80 virtual void OnExecuteDeclarativeScript(int tab_id, |
82 const ExtensionId& extension_id, | 81 const ExtensionId& extension_id, |
83 int script_id, | 82 int script_id, |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
128 void ScriptInjectionManager::RFOHelper::DidCreateNewDocument() { | 127 void ScriptInjectionManager::RFOHelper::DidCreateNewDocument() { |
129 // A new document is going to be shown, so invalidate the old document state. | 128 // A new document is going to be shown, so invalidate the old document state. |
130 // Check that the frame's state is known before invalidating the frame, | 129 // Check that the frame's state is known before invalidating the frame, |
131 // because it is possible that a script injection was scheduled before the | 130 // because it is possible that a script injection was scheduled before the |
132 // page was loaded, e.g. by navigating to a javascript: URL before the page | 131 // page was loaded, e.g. by navigating to a javascript: URL before the page |
133 // has loaded. | 132 // has loaded. |
134 if (manager_->frame_statuses_.count(render_frame()) != 0) | 133 if (manager_->frame_statuses_.count(render_frame()) != 0) |
135 InvalidateAndResetFrame(); | 134 InvalidateAndResetFrame(); |
136 } | 135 } |
137 | 136 |
138 void ScriptInjectionManager::RFOHelper::DidCreateDocumentElement() { | |
139 manager_->StartInjectScripts(render_frame(), UserScript::DOCUMENT_START); | |
140 } | |
141 | |
142 void ScriptInjectionManager::RFOHelper::DidFailProvisionalLoad( | 137 void ScriptInjectionManager::RFOHelper::DidFailProvisionalLoad( |
143 const blink::WebURLError& error) { | 138 const blink::WebURLError& error) { |
144 FrameStatusMap::iterator it = manager_->frame_statuses_.find(render_frame()); | 139 FrameStatusMap::iterator it = manager_->frame_statuses_.find(render_frame()); |
145 if (it != manager_->frame_statuses_.end() && | 140 if (it != manager_->frame_statuses_.end() && |
146 it->second == UserScript::DOCUMENT_START) { | 141 it->second == UserScript::DOCUMENT_START) { |
147 // Since the provisional load failed, the frame stays at its previous loaded | 142 // Since the provisional load failed, the frame stays at its previous loaded |
148 // state and origin (or the parent's origin for new/about:blank frames). | 143 // state and origin (or the parent's origin for new/about:blank frames). |
149 // Reset the frame to DOCUMENT_IDLE in order to reflect that the frame is | 144 // Reset the frame to DOCUMENT_IDLE in order to reflect that the frame is |
150 // done loading, and avoid any deadlock in the system. | 145 // done loading, and avoid any deadlock in the system. |
151 // | 146 // |
152 // We skip injection of DOCUMENT_END and DOCUMENT_IDLE scripts, because the | 147 // We skip injection of DOCUMENT_END and DOCUMENT_IDLE scripts, because the |
153 // injections closely follow the DOMContentLoaded (and onload) events, which | 148 // injections closely follow the DOMContentLoaded (and onload) events, which |
154 // are not triggered after a failed provisional load. | 149 // are not triggered after a failed provisional load. |
155 // This assumption is verified in the checkDOMContentLoadedEvent subtest of | 150 // This assumption is verified in the checkDOMContentLoadedEvent subtest of |
156 // ExecuteScriptApiTest.FrameWithHttp204 (browser_tests). | 151 // ExecuteScriptApiTest.FrameWithHttp204 (browser_tests). |
157 InvalidateAndResetFrame(); | 152 InvalidateAndResetFrame(); |
158 should_run_idle_ = false; | 153 should_run_idle_ = false; |
159 manager_->frame_statuses_[render_frame()] = UserScript::DOCUMENT_IDLE; | 154 manager_->frame_statuses_[render_frame()] = UserScript::DOCUMENT_IDLE; |
160 } | 155 } |
161 } | 156 } |
162 | 157 |
163 void ScriptInjectionManager::RFOHelper::DidFinishDocumentLoad() { | 158 void ScriptInjectionManager::RFOHelper::DidFinishDocumentLoad() { |
164 DCHECK(content::RenderThread::Get()); | 159 DCHECK(content::RenderThread::Get()); |
165 manager_->StartInjectScripts(render_frame(), UserScript::DOCUMENT_END); | |
166 // We try to run idle in two places: here and DidFinishLoad. | 160 // We try to run idle in two places: here and DidFinishLoad. |
167 // DidFinishDocumentLoad() corresponds to completing the document's load, | 161 // DidFinishDocumentLoad() corresponds to completing the document's load, |
168 // whereas DidFinishLoad corresponds to completing the document and all | 162 // whereas DidFinishLoad corresponds to completing the document and all |
169 // subresources' load. We don't want to hold up script injection for a | 163 // subresources' load. We don't want to hold up script injection for a |
170 // particularly slow subresource, so we set a delayed task from here - but if | 164 // particularly slow subresource, so we set a delayed task from here - but if |
171 // we finish everything before that point (i.e., DidFinishLoad() is | 165 // we finish everything before that point (i.e., DidFinishLoad() is |
172 // triggered), then there's no reason to keep waiting. | 166 // triggered), then there's no reason to keep waiting. |
173 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 167 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
174 FROM_HERE, | 168 FROM_HERE, |
175 base::Bind(&ScriptInjectionManager::RFOHelper::RunIdle, | 169 base::Bind(&ScriptInjectionManager::RFOHelper::RunIdle, |
176 weak_factory_.GetWeakPtr()), | 170 weak_factory_.GetWeakPtr()), |
177 base::TimeDelta::FromMilliseconds(kScriptIdleTimeoutInMs)); | 171 base::TimeDelta::FromMilliseconds(kScriptIdleTimeoutInMs)); |
172 | |
173 // Soon after this method returns, AfterDidFinishDocumentLoad will be called, | |
174 // which injects the DOCUMENT_END scripts. | |
178 } | 175 } |
179 | 176 |
180 void ScriptInjectionManager::RFOHelper::DidFinishLoad() { | 177 void ScriptInjectionManager::RFOHelper::DidFinishLoad() { |
181 DCHECK(content::RenderThread::Get()); | 178 DCHECK(content::RenderThread::Get()); |
182 // Ensure that we don't block any UI progress by running scripts. | 179 // Ensure that we don't block any UI progress by running scripts. |
183 base::ThreadTaskRunnerHandle::Get()->PostTask( | 180 base::ThreadTaskRunnerHandle::Get()->PostTask( |
184 FROM_HERE, | 181 FROM_HERE, |
185 base::Bind(&ScriptInjectionManager::RFOHelper::RunIdle, | 182 base::Bind(&ScriptInjectionManager::RFOHelper::RunIdle, |
186 weak_factory_.GetWeakPtr())); | 183 weak_factory_.GetWeakPtr())); |
187 } | 184 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
247 user_script_set_manager_observer_.Add(user_script_set_manager_); | 244 user_script_set_manager_observer_.Add(user_script_set_manager_); |
248 } | 245 } |
249 | 246 |
250 ScriptInjectionManager::~ScriptInjectionManager() { | 247 ScriptInjectionManager::~ScriptInjectionManager() { |
251 for (const auto& injection : pending_injections_) | 248 for (const auto& injection : pending_injections_) |
252 injection->invalidate_render_frame(); | 249 injection->invalidate_render_frame(); |
253 for (const auto& injection : running_injections_) | 250 for (const auto& injection : running_injections_) |
254 injection->invalidate_render_frame(); | 251 injection->invalidate_render_frame(); |
255 } | 252 } |
256 | 253 |
254 void ScriptInjectionManager::AfterDidCreateDocumentElement( | |
Devlin
2016/02/12 22:21:56
In general, it kind of makes me sad that we can't
| |
255 content::RenderFrame* render_frame) { | |
256 StartInjectScripts(render_frame, UserScript::DOCUMENT_START); | |
257 } | |
258 | |
259 void ScriptInjectionManager::AfterDidFinishDocumentLoad( | |
260 content::RenderFrame* render_frame) { | |
261 StartInjectScripts(render_frame, UserScript::DOCUMENT_END); | |
262 } | |
263 | |
257 void ScriptInjectionManager::OnRenderFrameCreated( | 264 void ScriptInjectionManager::OnRenderFrameCreated( |
258 content::RenderFrame* render_frame) { | 265 content::RenderFrame* render_frame) { |
259 rfo_helpers_.push_back(make_scoped_ptr(new RFOHelper(render_frame, this))); | 266 rfo_helpers_.push_back(make_scoped_ptr(new RFOHelper(render_frame, this))); |
260 } | 267 } |
261 | 268 |
262 void ScriptInjectionManager::OnExtensionUnloaded( | 269 void ScriptInjectionManager::OnExtensionUnloaded( |
263 const std::string& extension_id) { | 270 const std::string& extension_id) { |
264 for (auto iter = pending_injections_.begin(); | 271 for (auto iter = pending_injections_.begin(); |
265 iter != pending_injections_.end();) { | 272 iter != pending_injections_.end();) { |
266 if ((*iter)->host_id().id() == extension_id) { | 273 if ((*iter)->host_id().id() == extension_id) { |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
491 ScriptsRunInfo scripts_run_info(injection->render_frame(), | 498 ScriptsRunInfo scripts_run_info(injection->render_frame(), |
492 UserScript::RUN_DEFERRED); | 499 UserScript::RUN_DEFERRED); |
493 ScriptInjection::InjectionResult res = injection->OnPermissionGranted( | 500 ScriptInjection::InjectionResult res = injection->OnPermissionGranted( |
494 &scripts_run_info); | 501 &scripts_run_info); |
495 if (res == ScriptInjection::INJECTION_BLOCKED) | 502 if (res == ScriptInjection::INJECTION_BLOCKED) |
496 running_injections_.push_back(std::move(injection)); | 503 running_injections_.push_back(std::move(injection)); |
497 scripts_run_info.LogRun(); | 504 scripts_run_info.LogRun(); |
498 } | 505 } |
499 | 506 |
500 } // namespace extensions | 507 } // namespace extensions |
OLD | NEW |