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

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

Powered by Google App Engine
This is Rietveld 408576698