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

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> >();
43 }
39 } 44 }
40 45
41 UserScriptIdleScheduler::~UserScriptIdleScheduler() { 46 UserScriptScheduler::~UserScriptScheduler() {
42 } 47 }
43 48
44 void UserScriptIdleScheduler::ExecuteCode( 49 void UserScriptScheduler::ExecuteCode(
45 const ExtensionMsg_ExecuteCode_Params& params) { 50 const ExtensionMsg_ExecuteCode_Params& params) {
46 if (!has_run_) { 51 UserScript::RunLocation run_at =
47 pending_code_execution_queue_.push( 52 static_cast<UserScript::RunLocation>(params.run_at);
53 if (current_location_ < run_at) {
54 pending_execution_map_[run_at].push(
48 linked_ptr<ExtensionMsg_ExecuteCode_Params>( 55 linked_ptr<ExtensionMsg_ExecuteCode_Params>(
49 new ExtensionMsg_ExecuteCode_Params(params))); 56 new ExtensionMsg_ExecuteCode_Params(params)));
50 return; 57 return;
51 } 58 }
52 59
53 ExecuteCodeImpl(params); 60 ExecuteCodeImpl(params);
54 } 61 }
55 62
56 void UserScriptIdleScheduler::DidFinishDocumentLoad() { 63 void UserScriptScheduler::DidCreateDocumentElement() {
64 current_location_ = UserScript::DOCUMENT_START;
65 MaybeRun();
66 }
67
68 void UserScriptScheduler::DidFinishDocumentLoad() {
69 current_location_ = UserScript::DOCUMENT_END;
70 MaybeRun();
71 // Schedule a run for DOCUMENT_IDLE
57 MessageLoop::current()->PostDelayedTask( 72 MessageLoop::current()->PostDelayedTask(
58 FROM_HERE, base::Bind(&UserScriptIdleScheduler::MaybeRun, 73 FROM_HERE, base::Bind(&UserScriptScheduler::IdleTimeout,
59 weak_factory_.GetWeakPtr()), 74 weak_factory_.GetWeakPtr()),
60 base::TimeDelta::FromMilliseconds(kUserScriptIdleTimeoutMs)); 75 base::TimeDelta::FromMilliseconds(kUserScriptIdleTimeoutMs));
61 } 76 }
62 77
63 void UserScriptIdleScheduler::DidFinishLoad() { 78 void UserScriptScheduler::DidFinishLoad() {
79 current_location_ = UserScript::DOCUMENT_IDLE;
64 // Ensure that running scripts does not keep any progress UI running. 80 // Ensure that running scripts does not keep any progress UI running.
65 MessageLoop::current()->PostTask( 81 MessageLoop::current()->PostTask(
66 FROM_HERE, base::Bind(&UserScriptIdleScheduler::MaybeRun, 82 FROM_HERE, base::Bind(&UserScriptScheduler::MaybeRun,
67 weak_factory_.GetWeakPtr())); 83 weak_factory_.GetWeakPtr()));
68 } 84 }
69 85
70 void UserScriptIdleScheduler::DidStartProvisionalLoad() { 86 void UserScriptScheduler::DidStartProvisionalLoad() {
71 // The frame is navigating, so reset the state since we'll want to inject 87 // The frame is navigating, so reset the state since we'll want to inject
72 // scripts once the load finishes. 88 // scripts once the load finishes.
73 has_run_ = false; 89 current_location_ = UserScript::UNDEFINED;
90 has_run_idle_ = false;
74 weak_factory_.InvalidateWeakPtrs(); 91 weak_factory_.InvalidateWeakPtrs();
75 while (!pending_code_execution_queue_.empty()) 92 std::map<UserScript::RunLocation, ExecutionQueue>::iterator itr =
76 pending_code_execution_queue_.pop(); 93 pending_execution_map_.begin();
77 } 94 for (itr = pending_execution_map_.begin();
78 95 itr != pending_execution_map_.end(); ++itr) {
79 void UserScriptIdleScheduler::MaybeRun() { 96 while (!itr->second.empty())
80 if (has_run_) 97 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 } 98 }
98 } 99 }
99 100
100 void UserScriptIdleScheduler::ExecuteCodeImpl( 101 void UserScriptScheduler::IdleTimeout() {
102 current_location_ = UserScript::DOCUMENT_IDLE;
103 MaybeRun();
104 }
105
106 void UserScriptScheduler::MaybeRun() {
107 if (current_location_ == UserScript::UNDEFINED)
108 return;
109
110 if (!has_run_idle_ && current_location_ == UserScript::DOCUMENT_IDLE) {
111 has_run_idle_ = true;
112 extension_dispatcher_->user_script_slave()->InjectScripts(
113 frame_, UserScript::DOCUMENT_IDLE);
114 }
115
116 // Run all tasks from the current time and earlier.
117 for (int i = UserScript::DOCUMENT_START;
118 i <= current_location_; ++i) {
119 UserScript::RunLocation run_time = static_cast<UserScript::RunLocation>(i);
120 while (!pending_execution_map_[run_time].empty()) {
121 linked_ptr<ExtensionMsg_ExecuteCode_Params>& params =
122 pending_execution_map_[run_time].front();
123 ExecuteCodeImpl(*params);
124 pending_execution_map_[run_time].pop();
125 }
126 }
127 }
128
129 void UserScriptScheduler::ExecuteCodeImpl(
101 const ExtensionMsg_ExecuteCode_Params& params) { 130 const ExtensionMsg_ExecuteCode_Params& params) {
102 const Extension* extension = extension_dispatcher_->extensions()->GetByID( 131 const Extension* extension = extension_dispatcher_->extensions()->GetByID(
103 params.extension_id); 132 params.extension_id);
104 content::RenderView* render_view = 133 content::RenderView* render_view =
105 content::RenderView::FromWebView(frame_->view()); 134 content::RenderView::FromWebView(frame_->view());
106 135
107 // Since extension info is sent separately from user script info, they can 136 // Since extension info is sent separately from user script info, they can
108 // be out of sync. We just ignore this situation. 137 // be out of sync. We just ignore this situation.
109 if (!extension) { 138 if (!extension) {
110 render_view->Send(new ExtensionHostMsg_ExecuteCodeFinished( 139 render_view->Send(new ExtensionHostMsg_ExecuteCodeFinished(
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 WebString::fromUTF8(params.code), 190 WebString::fromUTF8(params.code),
162 // Author level is consistent with WebView::addUserStyleSheet. 191 // Author level is consistent with WebView::addUserStyleSheet.
163 WebDocument::UserStyleAuthorLevel); 192 WebDocument::UserStyleAuthorLevel);
164 } 193 }
165 } 194 }
166 195
167 render_view->Send(new ExtensionHostMsg_ExecuteCodeFinished( 196 render_view->Send(new ExtensionHostMsg_ExecuteCodeFinished(
168 render_view->GetRoutingID(), params.request_id, true, "")); 197 render_view->GetRoutingID(), params.request_id, true, ""));
169 } 198 }
170 199
171 bool UserScriptIdleScheduler::GetAllChildFrames( 200 bool UserScriptScheduler::GetAllChildFrames(
172 WebFrame* parent_frame, 201 WebFrame* parent_frame,
173 std::vector<WebFrame*>* frames_vector) const { 202 std::vector<WebFrame*>* frames_vector) const {
174 if (!parent_frame) 203 if (!parent_frame)
175 return false; 204 return false;
176 205
177 for (WebFrame* child_frame = parent_frame->firstChild(); child_frame; 206 for (WebFrame* child_frame = parent_frame->firstChild(); child_frame;
178 child_frame = child_frame->nextSibling()) { 207 child_frame = child_frame->nextSibling()) {
179 frames_vector->push_back(child_frame); 208 frames_vector->push_back(child_frame);
180 GetAllChildFrames(child_frame, frames_vector); 209 GetAllChildFrames(child_frame, frames_vector);
181 } 210 }
182 return true; 211 return true;
183 } 212 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698