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

Side by Side Diff: chrome/renderer/extensions/user_script_scheduler.cc

Issue 9456037: Adding run_at to chrome.tabs.executeScript/insertCss. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 8 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/renderer/extensions/user_script_idle_scheduler.h" 5 #include "chrome/renderer/extensions/user_script_scheduler.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "chrome/common/extensions/extension_error_utils.h" 9 #include "chrome/common/extensions/extension_error_utils.h"
10 #include "chrome/common/extensions/extension_manifest_constants.h" 10 #include "chrome/common/extensions/extension_manifest_constants.h"
11 #include "chrome/common/extensions/extension_messages.h" 11 #include "chrome/common/extensions/extension_messages.h"
12 #include "chrome/renderer/extensions/extension_dispatcher.h" 12 #include "chrome/renderer/extensions/extension_dispatcher.h"
13 #include "chrome/renderer/extensions/extension_groups.h" 13 #include "chrome/renderer/extensions/extension_groups.h"
14 #include "chrome/renderer/extensions/extension_helper.h" 14 #include "chrome/renderer/extensions/extension_helper.h"
15 #include "chrome/renderer/extensions/user_script_slave.h" 15 #include "chrome/renderer/extensions/user_script_slave.h"
16 #include "content/public/renderer/render_view.h" 16 #include "content/public/renderer/render_view.h"
17 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" 20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
21 21
22 namespace { 22 namespace {
23 // The length of time to wait after the DOM is complete to try and run user 23 // The length of time to wait after the DOM is complete to try and run user
24 // scripts. 24 // scripts.
25 const int kUserScriptIdleTimeoutMs = 200; 25 const int kUserScriptIdleTimeoutMs = 200;
26 } 26 }
27 27
28 using WebKit::WebDocument; 28 using WebKit::WebDocument;
29 using WebKit::WebFrame; 29 using WebKit::WebFrame;
30 using WebKit::WebString; 30 using WebKit::WebString;
31 using WebKit::WebView; 31 using WebKit::WebView;
32 32
33 UserScriptIdleScheduler::UserScriptIdleScheduler( 33 UserScriptScheduler::UserScriptScheduler(
34 WebFrame* frame, ExtensionDispatcher* extension_dispatcher) 34 WebFrame* frame, ExtensionDispatcher* extension_dispatcher)
35 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), 35 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
36 frame_(frame), 36 frame_(frame),
37 has_run_(false), 37 current_location_(UserScript::UNDEFINED),
38 has_run_idle_(false),
38 extension_dispatcher_(extension_dispatcher) { 39 extension_dispatcher_(extension_dispatcher) {
40 for (int i = UserScript::UNDEFINED; i < UserScript::RUN_LOCATION_LAST; ++i)
41 pending_execution_map_[static_cast<UserScript::RunLocation>(i)] =
42 std::queue<linked_ptr<ExtensionMsg_ExecuteCode_Params> >();
39 } 43 }
40 44
41 UserScriptIdleScheduler::~UserScriptIdleScheduler() { 45 UserScriptScheduler::~UserScriptScheduler() {
42 } 46 }
43 47
44 void UserScriptIdleScheduler::ExecuteCode( 48 void UserScriptScheduler::ExecuteCode(
45 const ExtensionMsg_ExecuteCode_Params& params) { 49 const ExtensionMsg_ExecuteCode_Params& params) {
46 if (!has_run_) { 50 UserScript::RunLocation run_at =
47 pending_code_execution_queue_.push( 51 static_cast<UserScript::RunLocation>(params.run_at);
52 if (current_location_ < run_at) {
53 pending_execution_map_[run_at].push(
48 linked_ptr<ExtensionMsg_ExecuteCode_Params>( 54 linked_ptr<ExtensionMsg_ExecuteCode_Params>(
49 new ExtensionMsg_ExecuteCode_Params(params))); 55 new ExtensionMsg_ExecuteCode_Params(params)));
50 return; 56 return;
51 } 57 }
52 58
53 ExecuteCodeImpl(params); 59 ExecuteCodeImpl(params);
54 } 60 }
55 61
56 void UserScriptIdleScheduler::DidFinishDocumentLoad() { 62 void UserScriptScheduler::DidCreateDocumentElement() {
63 current_location_ = UserScript::DOCUMENT_START;
64 MaybeRun();
65 }
66
67 void UserScriptScheduler::DidFinishDocumentLoad() {
68 current_location_ = UserScript::DOCUMENT_END;
69 MaybeRun();
70 // Schedule a run for DOCUMENT_IDLE
57 MessageLoop::current()->PostDelayedTask( 71 MessageLoop::current()->PostDelayedTask(
58 FROM_HERE, base::Bind(&UserScriptIdleScheduler::MaybeRun, 72 FROM_HERE, base::Bind(&UserScriptScheduler::IdleTimeout,
59 weak_factory_.GetWeakPtr()), 73 weak_factory_.GetWeakPtr()),
60 base::TimeDelta::FromMilliseconds(kUserScriptIdleTimeoutMs)); 74 base::TimeDelta::FromMilliseconds(kUserScriptIdleTimeoutMs));
61 } 75 }
62 76
63 void UserScriptIdleScheduler::DidFinishLoad() { 77 void UserScriptScheduler::DidFinishLoad() {
78 current_location_ = UserScript::DOCUMENT_IDLE;
64 // Ensure that running scripts does not keep any progress UI running. 79 // Ensure that running scripts does not keep any progress UI running.
65 MessageLoop::current()->PostTask( 80 MessageLoop::current()->PostTask(
66 FROM_HERE, base::Bind(&UserScriptIdleScheduler::MaybeRun, 81 FROM_HERE, base::Bind(&UserScriptScheduler::MaybeRun,
67 weak_factory_.GetWeakPtr())); 82 weak_factory_.GetWeakPtr()));
68 } 83 }
69 84
70 void UserScriptIdleScheduler::DidStartProvisionalLoad() { 85 void UserScriptScheduler::DidStartProvisionalLoad() {
71 // The frame is navigating, so reset the state since we'll want to inject 86 // The frame is navigating, so reset the state since we'll want to inject
72 // scripts once the load finishes. 87 // scripts once the load finishes.
73 has_run_ = false; 88 current_location_ = UserScript::UNDEFINED;
89 has_run_idle_ = false;
74 weak_factory_.InvalidateWeakPtrs(); 90 weak_factory_.InvalidateWeakPtrs();
75 while (!pending_code_execution_queue_.empty()) 91 std::map<UserScript::RunLocation, ExecutionQueue>::iterator itr =
76 pending_code_execution_queue_.pop(); 92 pending_execution_map_.begin();
77 } 93 for (itr = pending_execution_map_.begin();
78 94 itr != pending_execution_map_.end(); ++itr) {
79 void UserScriptIdleScheduler::MaybeRun() { 95 while (!itr->second.empty())
80 if (has_run_) 96 itr->second.pop();
81 return;
82
83 // Note: we must set this before calling ExecuteCodeImpl, because that may
84 // result in a synchronous call back into MaybeRun if there is a pending task
85 // currently in the queue.
86 // http://code.google.com/p/chromium/issues/detail?id=29644
87 has_run_ = true;
88
89 extension_dispatcher_->user_script_slave()->InjectScripts(
90 frame_, UserScript::DOCUMENT_IDLE);
91
92 while (!pending_code_execution_queue_.empty()) {
93 linked_ptr<ExtensionMsg_ExecuteCode_Params>& params =
94 pending_code_execution_queue_.front();
95 ExecuteCodeImpl(*params);
96 pending_code_execution_queue_.pop();
97 } 97 }
98 } 98 }
99 99
100 void UserScriptIdleScheduler::ExecuteCodeImpl( 100 void UserScriptScheduler::IdleTimeout() {
101 current_location_ = UserScript::DOCUMENT_IDLE;
102 MaybeRun();
103 }
104
105 void UserScriptScheduler::MaybeRun() {
106 if (current_location_ == UserScript::UNDEFINED)
107 return;
108
109 if (!has_run_idle_ && current_location_ == UserScript::DOCUMENT_IDLE) {
110 extension_dispatcher_->user_script_slave()->InjectScripts(
111 frame_, UserScript::DOCUMENT_IDLE);
112 has_run_idle_ = true;
113 }
114
115 // Run all tasks from the current time and earlier.
116 for (int i = UserScript::DOCUMENT_START;
117 i <= current_location_; ++i) {
118 UserScript::RunLocation run_time = static_cast<UserScript::RunLocation>(i);
119 while (!pending_execution_map_[run_time].empty()) {
120 linked_ptr<ExtensionMsg_ExecuteCode_Params>& params =
121 pending_execution_map_[run_time].front();
122 ExecuteCodeImpl(*params);
123 pending_execution_map_[run_time].pop();
124 }
125 }
126 }
127
128 void UserScriptScheduler::ExecuteCodeImpl(
101 const ExtensionMsg_ExecuteCode_Params& params) { 129 const ExtensionMsg_ExecuteCode_Params& params) {
102 const Extension* extension = extension_dispatcher_->extensions()->GetByID( 130 const Extension* extension = extension_dispatcher_->extensions()->GetByID(
103 params.extension_id); 131 params.extension_id);
104 content::RenderView* render_view = 132 content::RenderView* render_view =
105 content::RenderView::FromWebView(frame_->view()); 133 content::RenderView::FromWebView(frame_->view());
106 134
107 // Since extension info is sent separately from user script info, they can 135 // Since extension info is sent separately from user script info, they can
108 // be out of sync. We just ignore this situation. 136 // be out of sync. We just ignore this situation.
109 if (!extension) { 137 if (!extension) {
110 render_view->Send(new ExtensionHostMsg_ExecuteCodeFinished( 138 render_view->Send(new ExtensionHostMsg_ExecuteCodeFinished(
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 WebString::fromUTF8(params.code), 189 WebString::fromUTF8(params.code),
162 // Author level is consistent with WebView::addUserStyleSheet. 190 // Author level is consistent with WebView::addUserStyleSheet.
163 WebDocument::UserStyleAuthorLevel); 191 WebDocument::UserStyleAuthorLevel);
164 } 192 }
165 } 193 }
166 194
167 render_view->Send(new ExtensionHostMsg_ExecuteCodeFinished( 195 render_view->Send(new ExtensionHostMsg_ExecuteCodeFinished(
168 render_view->GetRoutingID(), params.request_id, true, "")); 196 render_view->GetRoutingID(), params.request_id, true, ""));
169 } 197 }
170 198
171 bool UserScriptIdleScheduler::GetAllChildFrames( 199 bool UserScriptScheduler::GetAllChildFrames(
172 WebFrame* parent_frame, 200 WebFrame* parent_frame,
173 std::vector<WebFrame*>* frames_vector) const { 201 std::vector<WebFrame*>* frames_vector) const {
174 if (!parent_frame) 202 if (!parent_frame)
175 return false; 203 return false;
176 204
177 for (WebFrame* child_frame = parent_frame->firstChild(); child_frame; 205 for (WebFrame* child_frame = parent_frame->firstChild(); child_frame;
178 child_frame = child_frame->nextSibling()) { 206 child_frame = child_frame->nextSibling()) {
179 frames_vector->push_back(child_frame); 207 frames_vector->push_back(child_frame);
180 GetAllChildFrames(child_frame, frames_vector); 208 GetAllChildFrames(child_frame, frames_vector);
181 } 209 }
182 return true; 210 return true;
183 } 211 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698