 Chromium Code Reviews
 Chromium Code Reviews Issue 1642283002:
  Deal with frame removal by content scripts  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 1642283002:
  Deal with frame removal by content scripts  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| 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 |