Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(268)

Side by Side Diff: extensions/renderer/script_injection_manager.cc

Issue 1642283002: Deal with frame removal by content scripts (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Push down WeakPtr Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698