Chromium Code Reviews| 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 |