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

Side by Side Diff: trunk/src/extensions/renderer/user_script_slave.cc

Issue 307933008: Revert 273866 "Block content scripts from executing until user g..." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 6 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « trunk/src/extensions/renderer/user_script_slave.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/user_script_slave.h" 5 #include "extensions/renderer/user_script_slave.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/shared_memory.h" 10 #include "base/memory/shared_memory.h"
(...skipping 13 matching lines...) Expand all
24 #include "third_party/WebKit/public/web/WebFrame.h" 24 #include "third_party/WebKit/public/web/WebFrame.h"
25 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" 25 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
26 #include "third_party/WebKit/public/web/WebSecurityPolicy.h" 26 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
27 #include "third_party/WebKit/public/web/WebView.h" 27 #include "third_party/WebKit/public/web/WebView.h"
28 #include "url/gurl.h" 28 #include "url/gurl.h"
29 29
30 using blink::WebFrame; 30 using blink::WebFrame;
31 using blink::WebSecurityOrigin; 31 using blink::WebSecurityOrigin;
32 using blink::WebSecurityPolicy; 32 using blink::WebSecurityPolicy;
33 using blink::WebString; 33 using blink::WebString;
34 using blink::WebView;
34 using content::RenderThread; 35 using content::RenderThread;
35 36
36 namespace extensions { 37 namespace extensions {
37 38
38 int UserScriptSlave::GetIsolatedWorldIdForExtension(const Extension* extension, 39 int UserScriptSlave::GetIsolatedWorldIdForExtension(const Extension* extension,
39 WebFrame* frame) { 40 WebFrame* frame) {
40 static int g_next_isolated_world_id = 41 static int g_next_isolated_world_id =
41 ExtensionsRendererClient::Get()->GetLowestIsolatedWorldId(); 42 ExtensionsRendererClient::Get()->GetLowestIsolatedWorldId();
42 43
43 int id = 0; 44 int id = 0;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 DCHECK(!(*iter)->extension_id().empty()); 95 DCHECK(!(*iter)->extension_id().empty());
95 extension_ids->insert((*iter)->extension_id()); 96 extension_ids->insert((*iter)->extension_id());
96 } 97 }
97 } 98 }
98 99
99 const Extension* UserScriptSlave::GetExtension( 100 const Extension* UserScriptSlave::GetExtension(
100 const std::string& extension_id) { 101 const std::string& extension_id) {
101 return extensions_->GetByID(extension_id); 102 return extensions_->GetByID(extension_id);
102 } 103 }
103 104
104 bool UserScriptSlave::UpdateScripts( 105 bool UserScriptSlave::UpdateScripts(base::SharedMemoryHandle shared_memory) {
105 base::SharedMemoryHandle shared_memory, 106 script_injections_.clear();
106 const std::set<std::string>& changed_extensions) { 107
107 bool only_inject_incognito = 108 bool only_inject_incognito =
108 ExtensionsRendererClient::Get()->IsIncognitoProcess(); 109 ExtensionsRendererClient::Get()->IsIncognitoProcess();
109 110
110 // Create the shared memory object (read only). 111 // Create the shared memory object (read only).
111 shared_memory_.reset(new base::SharedMemory(shared_memory, true)); 112 shared_memory_.reset(new base::SharedMemory(shared_memory, true));
112 if (!shared_memory_.get()) 113 if (!shared_memory_.get())
113 return false; 114 return false;
114 115
115 // First get the size of the memory block. 116 // First get the size of the memory block.
116 if (!shared_memory_->Map(sizeof(Pickle::Header))) 117 if (!shared_memory_->Map(sizeof(Pickle::Header)))
117 return false; 118 return false;
118 Pickle::Header* pickle_header = 119 Pickle::Header* pickle_header =
119 reinterpret_cast<Pickle::Header*>(shared_memory_->memory()); 120 reinterpret_cast<Pickle::Header*>(shared_memory_->memory());
120 121
121 // Now map in the rest of the block. 122 // Now map in the rest of the block.
122 int pickle_size = sizeof(Pickle::Header) + pickle_header->payload_size; 123 int pickle_size = sizeof(Pickle::Header) + pickle_header->payload_size;
123 shared_memory_->Unmap(); 124 shared_memory_->Unmap();
124 if (!shared_memory_->Map(pickle_size)) 125 if (!shared_memory_->Map(pickle_size))
125 return false; 126 return false;
126 127
127 // Unpickle scripts. 128 // Unpickle scripts.
128 uint64 num_scripts = 0; 129 uint64 num_scripts = 0;
129 Pickle pickle(reinterpret_cast<char*>(shared_memory_->memory()), pickle_size); 130 Pickle pickle(reinterpret_cast<char*>(shared_memory_->memory()), pickle_size);
130 PickleIterator iter(pickle); 131 PickleIterator iter(pickle);
131 CHECK(pickle.ReadUInt64(&iter, &num_scripts)); 132 CHECK(pickle.ReadUInt64(&iter, &num_scripts));
132 133
133 // If we pass no explicit extension ids, we should refresh all extensions.
134 bool include_all_extensions = changed_extensions.empty();
135
136 // If we include all extensions, then we clear the script injections and
137 // start from scratch. If not, then clear only the scripts for extension ids
138 // that we are updating. This is important to maintain pending script
139 // injection state for each ScriptInjection.
140 if (include_all_extensions) {
141 script_injections_.clear();
142 } else {
143 for (ScopedVector<ScriptInjection>::iterator iter =
144 script_injections_.begin();
145 iter != script_injections_.end();) {
146 if (changed_extensions.count((*iter)->extension_id()) > 0)
147 iter = script_injections_.erase(iter);
148 else
149 ++iter;
150 }
151 }
152
153 script_injections_.reserve(num_scripts); 134 script_injections_.reserve(num_scripts);
154 for (uint64 i = 0; i < num_scripts; ++i) { 135 for (uint64 i = 0; i < num_scripts; ++i) {
155 scoped_ptr<UserScript> script(new UserScript()); 136 scoped_ptr<UserScript> script(new UserScript());
156 script->Unpickle(pickle, &iter); 137 script->Unpickle(pickle, &iter);
157 138
158 // Note that this is a pointer into shared memory. We don't own it. It gets 139 // Note that this is a pointer into shared memory. We don't own it. It gets
159 // cleared up when the last renderer or browser process drops their 140 // cleared up when the last renderer or browser process drops their
160 // reference to the shared memory. 141 // reference to the shared memory.
161 for (size_t j = 0; j < script->js_scripts().size(); ++j) { 142 for (size_t j = 0; j < script->js_scripts().size(); ++j) {
162 const char* body = NULL; 143 const char* body = NULL;
163 int body_length = 0; 144 int body_length = 0;
164 CHECK(pickle.ReadData(&iter, &body, &body_length)); 145 CHECK(pickle.ReadData(&iter, &body, &body_length));
165 script->js_scripts()[j].set_external_content( 146 script->js_scripts()[j].set_external_content(
166 base::StringPiece(body, body_length)); 147 base::StringPiece(body, body_length));
167 } 148 }
168 for (size_t j = 0; j < script->css_scripts().size(); ++j) { 149 for (size_t j = 0; j < script->css_scripts().size(); ++j) {
169 const char* body = NULL; 150 const char* body = NULL;
170 int body_length = 0; 151 int body_length = 0;
171 CHECK(pickle.ReadData(&iter, &body, &body_length)); 152 CHECK(pickle.ReadData(&iter, &body, &body_length));
172 script->css_scripts()[j].set_external_content( 153 script->css_scripts()[j].set_external_content(
173 base::StringPiece(body, body_length)); 154 base::StringPiece(body, body_length));
174 } 155 }
175 156
176 // Don't add the script if it shouldn't shouldn't run in this tab, or if 157 if (only_inject_incognito && !script->is_incognito_enabled())
177 // we don't need to reload that extension. 158 continue; // This script shouldn't run in an incognito tab.
178 // It's a shame we don't catch this sooner, but since we lump all the user
179 // scripts together, we can't skip parsing any.
180 if ((only_inject_incognito && !script->is_incognito_enabled()) ||
181 (!include_all_extensions &&
182 changed_extensions.count(script->extension_id()) == 0)) {
183 continue;
184 }
185 159
186 script_injections_.push_back(new ScriptInjection(script.Pass(), this)); 160 script_injections_.push_back(new ScriptInjection(script.Pass(), this));
187 } 161 }
188 162
189 return true; 163 return true;
190 } 164 }
191 165
192 void UserScriptSlave::InjectScripts(WebFrame* frame, 166 void UserScriptSlave::InjectScripts(WebFrame* frame,
193 UserScript::RunLocation location) { 167 UserScript::RunLocation location) {
194 GURL document_url = ScriptInjection::GetDocumentUrlForFrame(frame); 168 GURL document_url = ScriptInjection::GetDocumentUrlForFrame(frame);
195 if (document_url.is_empty()) 169 if (document_url.is_empty())
196 return; 170 return;
197 171
172 content::RenderView* top_render_view =
173 content::RenderView::FromWebView(frame->top()->view());
174
198 ScriptInjection::ScriptsRunInfo scripts_run_info; 175 ScriptInjection::ScriptsRunInfo scripts_run_info;
199 for (ScopedVector<ScriptInjection>::const_iterator iter = 176 for (ScopedVector<ScriptInjection>::const_iterator iter =
200 script_injections_.begin(); 177 script_injections_.begin();
201 iter != script_injections_.end(); 178 iter != script_injections_.end();
202 ++iter) { 179 ++iter) {
203 (*iter)->InjectIfAllowed(frame, location, document_url, &scripts_run_info); 180 ScriptInjection* injection = *iter;
181 if (!injection->WantsToRun(frame, location, document_url))
182 continue;
183
184 const Extension* extension = GetExtension(injection->extension_id());
185 DCHECK(extension);
186
187 if (PermissionsData::RequiresActionForScriptExecution(
188 extension,
189 ExtensionHelper::Get(top_render_view)->tab_id(),
190 document_url)) {
191 // TODO(rdevlin.cronin): Right now, this is just a notification, but soon
192 // we should block without user consent.
193 top_render_view->Send(
194 new ExtensionHostMsg_NotifyExtensionScriptExecution(
195 top_render_view->GetRoutingID(),
196 extension->id(),
197 top_render_view->GetPageId()));
198 }
199
200 injection->Inject(frame, location, &scripts_run_info);
204 } 201 }
205 202
206 LogScriptsRun(frame, location, scripts_run_info); 203 LogScriptsRun(frame, location, scripts_run_info);
207 } 204 }
208 205
209 void UserScriptSlave::OnContentScriptGrantedPermission(
210 content::RenderView* render_view, int request_id) {
211 ScriptInjection::ScriptsRunInfo run_info;
212 blink::WebFrame* frame = NULL;
213 // Notify the injections that a request to inject has been granted.
214 for (ScopedVector<ScriptInjection>::iterator iter =
215 script_injections_.begin();
216 iter != script_injections_.end();
217 ++iter) {
218 if ((*iter)->NotifyScriptPermitted(request_id,
219 render_view,
220 &run_info,
221 &frame)) {
222 DCHECK(frame);
223 LogScriptsRun(frame, UserScript::RUN_DEFERRED, run_info);
224 break;
225 }
226 }
227 }
228
229 void UserScriptSlave::FrameDetached(blink::WebFrame* frame) {
230 for (ScopedVector<ScriptInjection>::iterator iter =
231 script_injections_.begin();
232 iter != script_injections_.end();
233 ++iter) {
234 (*iter)->FrameDetached(frame);
235 }
236 }
237
238 void UserScriptSlave::LogScriptsRun( 206 void UserScriptSlave::LogScriptsRun(
239 blink::WebFrame* frame, 207 blink::WebFrame* frame,
240 UserScript::RunLocation location, 208 UserScript::RunLocation location,
241 const ScriptInjection::ScriptsRunInfo& info) { 209 const ScriptInjection::ScriptsRunInfo& info) {
242 // Notify the browser if any extensions are now executing scripts. 210 // Notify the browser if any extensions are now executing scripts.
243 if (!info.executing_scripts.empty()) { 211 if (!info.executing_scripts.empty()) {
244 content::RenderView* render_view = 212 content::RenderView* render_view =
245 content::RenderView::FromWebView(frame->view()); 213 content::RenderView::FromWebView(frame->view());
246 render_view->Send(new ExtensionHostMsg_ContentScriptsExecuting( 214 render_view->Send(new ExtensionHostMsg_ContentScriptsExecuting(
247 render_view->GetRoutingID(), 215 render_view->GetRoutingID(),
248 info.executing_scripts, 216 info.executing_scripts,
249 render_view->GetPageId(), 217 render_view->GetPageId(),
250 ScriptContext::GetDataSourceURLForFrame(frame))); 218 ScriptContext::GetDataSourceURLForFrame(frame)));
251 } 219 }
252 220
253 switch (location) { 221 if (location == UserScript::DOCUMENT_START) {
254 case UserScript::DOCUMENT_START: 222 UMA_HISTOGRAM_COUNTS_100("Extensions.InjectStart_CssCount",
255 UMA_HISTOGRAM_COUNTS_100("Extensions.InjectStart_CssCount", 223 info.num_css);
256 info.num_css); 224 UMA_HISTOGRAM_COUNTS_100("Extensions.InjectStart_ScriptCount", info.num_js);
257 UMA_HISTOGRAM_COUNTS_100("Extensions.InjectStart_ScriptCount", 225 if (info.num_css || info.num_js)
258 info.num_js); 226 UMA_HISTOGRAM_TIMES("Extensions.InjectStart_Time", info.timer.Elapsed());
259 if (info.num_css || info.num_js) 227 } else if (location == UserScript::DOCUMENT_END) {
260 UMA_HISTOGRAM_TIMES("Extensions.InjectStart_Time", 228 UMA_HISTOGRAM_COUNTS_100("Extensions.InjectEnd_ScriptCount", info.num_js);
261 info.timer.Elapsed()); 229 if (info.num_js)
262 break; 230 UMA_HISTOGRAM_TIMES("Extensions.InjectEnd_Time", info.timer.Elapsed());
263 case UserScript::DOCUMENT_END: 231 } else if (location == UserScript::DOCUMENT_IDLE) {
264 UMA_HISTOGRAM_COUNTS_100("Extensions.InjectEnd_ScriptCount", info.num_js); 232 UMA_HISTOGRAM_COUNTS_100("Extensions.InjectIdle_ScriptCount", info.num_js);
265 if (info.num_js) 233 if (info.num_js)
266 UMA_HISTOGRAM_TIMES("Extensions.InjectEnd_Time", info.timer.Elapsed()); 234 UMA_HISTOGRAM_TIMES("Extensions.InjectIdle_Time", info.timer.Elapsed());
267 break; 235 } else {
268 case UserScript::DOCUMENT_IDLE: 236 NOTREACHED();
269 UMA_HISTOGRAM_COUNTS_100("Extensions.InjectIdle_ScriptCount",
270 info.num_js);
271 if (info.num_js)
272 UMA_HISTOGRAM_TIMES("Extensions.InjectIdle_Time", info.timer.Elapsed());
273 break;
274 case UserScript::RUN_DEFERRED:
275 // TODO(rdevlin.cronin): Add histograms.
276 break;
277 case UserScript::UNDEFINED:
278 case UserScript::RUN_LOCATION_LAST:
279 NOTREACHED();
280 } 237 }
281 } 238 }
282 239
283 } // namespace extensions 240 } // namespace extensions
OLDNEW
« no previous file with comments | « trunk/src/extensions/renderer/user_script_slave.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698