OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_slave.h" | 5 #include "chrome/renderer/extensions/user_script_slave.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 26 matching lines...) Expand all Loading... |
37 using WebKit::WebSecurityPolicy; | 37 using WebKit::WebSecurityPolicy; |
38 using WebKit::WebString; | 38 using WebKit::WebString; |
39 using WebKit::WebVector; | 39 using WebKit::WebVector; |
40 using WebKit::WebView; | 40 using WebKit::WebView; |
41 | 41 |
42 // These two strings are injected before and after the Greasemonkey API and | 42 // These two strings are injected before and after the Greasemonkey API and |
43 // user script to wrap it in an anonymous scope. | 43 // user script to wrap it in an anonymous scope. |
44 static const char kUserScriptHead[] = "(function (unsafeWindow) {\n"; | 44 static const char kUserScriptHead[] = "(function (unsafeWindow) {\n"; |
45 static const char kUserScriptTail[] = "\n})(window);"; | 45 static const char kUserScriptTail[] = "\n})(window);"; |
46 | 46 |
47 // Sets up the chrome.extension module. This may be run multiple times per | |
48 // context, but the init method deletes itself after the first time. | |
49 static const char kInitExtension[] = | |
50 "if (chrome.initExtension) chrome.initExtension('%s', true, %s);"; | |
51 | |
52 int UserScriptSlave::GetIsolatedWorldIdForExtension( | 47 int UserScriptSlave::GetIsolatedWorldIdForExtension( |
53 const Extension* extension, WebFrame* frame) { | 48 const Extension* extension, WebFrame* frame) { |
54 static int g_next_isolated_world_id = 1; | 49 static int g_next_isolated_world_id = 1; |
55 | 50 |
56 IsolatedWorldMap::iterator iter = isolated_world_ids_.find(extension->id()); | 51 IsolatedWorldMap::iterator iter = isolated_world_ids_.find(extension->id()); |
57 if (iter != isolated_world_ids_.end()) { | 52 if (iter != isolated_world_ids_.end()) { |
58 // We need to set the isolated world origin even if it's not a new world | 53 // We need to set the isolated world origin even if it's not a new world |
59 // since that is stored per frame, and we might not have used this isolated | 54 // since that is stored per frame, and we might not have used this isolated |
60 // world in this frame before. | 55 // world in this frame before. |
61 frame->setIsolatedWorldSecurityOrigin( | 56 frame->setIsolatedWorldSecurityOrigin( |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 script->match_all_frames() ? | 222 script->match_all_frames() ? |
228 WebView::UserContentInjectInAllFrames : | 223 WebView::UserContentInjectInAllFrames : |
229 WebView::UserContentInjectInTopFrameOnly, | 224 WebView::UserContentInjectInTopFrameOnly, |
230 WebView::UserStyleInjectInExistingDocuments); | 225 WebView::UserStyleInjectInExistingDocuments); |
231 } | 226 } |
232 } | 227 } |
233 | 228 |
234 return true; | 229 return true; |
235 } | 230 } |
236 | 231 |
237 // static | |
238 void UserScriptSlave::InsertInitExtensionCode( | |
239 std::vector<WebScriptSource>* sources, const std::string& extension_id) { | |
240 DCHECK(sources); | |
241 bool incognito = ChromeRenderProcessObserver::is_incognito_process(); | |
242 sources->insert(sources->begin(), WebScriptSource(WebString::fromUTF8( | |
243 base::StringPrintf(kInitExtension, | |
244 extension_id.c_str(), | |
245 incognito ? "true" : "false")))); | |
246 } | |
247 | |
248 void UserScriptSlave::InjectScripts(WebFrame* frame, | 232 void UserScriptSlave::InjectScripts(WebFrame* frame, |
249 UserScript::RunLocation location) { | 233 UserScript::RunLocation location) { |
250 // Normally we would use frame->document().url() to determine the document's | 234 // Normally we would use frame->document().url() to determine the document's |
251 // URL, but to decide whether to inject a content script, we use the URL from | 235 // URL, but to decide whether to inject a content script, we use the URL from |
252 // the data source. This "quirk" helps prevents content scripts from | 236 // the data source. This "quirk" helps prevents content scripts from |
253 // inadvertently adding DOM elements to the compose iframe in Gmail because | 237 // inadvertently adding DOM elements to the compose iframe in Gmail because |
254 // the compose iframe's dataSource URL is about:blank, but the document URL | 238 // the compose iframe's dataSource URL is about:blank, but the document URL |
255 // changes to match the parent document after Gmail document.writes into | 239 // changes to match the parent document after Gmail document.writes into |
256 // it to create the editor. | 240 // it to create the editor. |
257 // http://code.google.com/p/chromium/issues/detail?id=86742 | 241 // http://code.google.com/p/chromium/issues/detail?id=86742 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 num_css += script->css_scripts().size(); | 274 num_css += script->css_scripts().size(); |
291 | 275 |
292 if (script->run_location() == location) { | 276 if (script->run_location() == location) { |
293 num_scripts += script->js_scripts().size(); | 277 num_scripts += script->js_scripts().size(); |
294 for (size_t j = 0; j < script->js_scripts().size(); ++j) { | 278 for (size_t j = 0; j < script->js_scripts().size(); ++j) { |
295 UserScript::File &file = script->js_scripts()[j]; | 279 UserScript::File &file = script->js_scripts()[j]; |
296 std::string content = file.GetContent().as_string(); | 280 std::string content = file.GetContent().as_string(); |
297 | 281 |
298 // We add this dumb function wrapper for standalone user script to | 282 // We add this dumb function wrapper for standalone user script to |
299 // emulate what Greasemonkey does. | 283 // emulate what Greasemonkey does. |
| 284 // TODO(aa): I think that maybe "is_standalone" scripts don't exist |
| 285 // anymore. Investigate. |
300 if (script->is_standalone() || script->emulate_greasemonkey()) { | 286 if (script->is_standalone() || script->emulate_greasemonkey()) { |
301 content.insert(0, kUserScriptHead); | 287 content.insert(0, kUserScriptHead); |
302 content += kUserScriptTail; | 288 content += kUserScriptTail; |
303 } | 289 } |
304 sources.push_back( | 290 sources.push_back( |
305 WebScriptSource(WebString::fromUTF8(content), file.url())); | 291 WebScriptSource(WebString::fromUTF8(content), file.url())); |
306 } | 292 } |
307 } | 293 } |
308 | 294 |
309 if (!sources.empty()) { | 295 if (!sources.empty()) { |
310 int isolated_world_id = 0; | 296 int isolated_world_id = 0; |
311 | 297 |
312 // Emulate Greasemonkey API for scripts that were converted to extensions | 298 // Emulate Greasemonkey API for scripts that were converted to extensions |
313 // and "standalone" user scripts. | 299 // and "standalone" user scripts. |
314 if (script->is_standalone() || script->emulate_greasemonkey()) { | 300 if (script->is_standalone() || script->emulate_greasemonkey()) { |
315 sources.insert(sources.begin(), | 301 sources.insert(sources.begin(), |
316 WebScriptSource(WebString::fromUTF8(api_js_.as_string()))); | 302 WebScriptSource(WebString::fromUTF8(api_js_.as_string()))); |
317 } | 303 } |
318 | 304 |
319 // Setup chrome.self to contain an Extension object with the correct | 305 // Setup chrome.self to contain an Extension object with the correct |
320 // ID. | 306 // ID. |
321 if (!script->extension_id().empty()) { | 307 // TODO(aa): Can extension_id() ever be empty anymore? |
322 InsertInitExtensionCode(&sources, script->extension_id()); | 308 if (!script->extension_id().empty()) |
323 isolated_world_id = GetIsolatedWorldIdForExtension(extension, frame); | 309 isolated_world_id = GetIsolatedWorldIdForExtension(extension, frame); |
324 } | |
325 | 310 |
326 PerfTimer exec_timer; | 311 PerfTimer exec_timer; |
327 frame->executeScriptInIsolatedWorld( | 312 frame->executeScriptInIsolatedWorld( |
328 isolated_world_id, &sources.front(), sources.size(), | 313 isolated_world_id, &sources.front(), sources.size(), |
329 EXTENSION_GROUP_CONTENT_SCRIPTS); | 314 EXTENSION_GROUP_CONTENT_SCRIPTS); |
330 UMA_HISTOGRAM_TIMES("Extensions.InjectScriptTime", exec_timer.Elapsed()); | 315 UMA_HISTOGRAM_TIMES("Extensions.InjectScriptTime", exec_timer.Elapsed()); |
331 } | 316 } |
332 } | 317 } |
333 | 318 |
334 // Log debug info. | 319 // Log debug info. |
335 if (location == UserScript::DOCUMENT_START) { | 320 if (location == UserScript::DOCUMENT_START) { |
336 UMA_HISTOGRAM_COUNTS_100("Extensions.InjectStart_CssCount", num_css); | 321 UMA_HISTOGRAM_COUNTS_100("Extensions.InjectStart_CssCount", num_css); |
337 UMA_HISTOGRAM_COUNTS_100("Extensions.InjectStart_ScriptCount", num_scripts); | 322 UMA_HISTOGRAM_COUNTS_100("Extensions.InjectStart_ScriptCount", num_scripts); |
338 if (num_css || num_scripts) | 323 if (num_css || num_scripts) |
339 UMA_HISTOGRAM_TIMES("Extensions.InjectStart_Time", timer.Elapsed()); | 324 UMA_HISTOGRAM_TIMES("Extensions.InjectStart_Time", timer.Elapsed()); |
340 } else if (location == UserScript::DOCUMENT_END) { | 325 } else if (location == UserScript::DOCUMENT_END) { |
341 UMA_HISTOGRAM_COUNTS_100("Extensions.InjectEnd_ScriptCount", num_scripts); | 326 UMA_HISTOGRAM_COUNTS_100("Extensions.InjectEnd_ScriptCount", num_scripts); |
342 if (num_scripts) | 327 if (num_scripts) |
343 UMA_HISTOGRAM_TIMES("Extensions.InjectEnd_Time", timer.Elapsed()); | 328 UMA_HISTOGRAM_TIMES("Extensions.InjectEnd_Time", timer.Elapsed()); |
344 } else if (location == UserScript::DOCUMENT_IDLE) { | 329 } else if (location == UserScript::DOCUMENT_IDLE) { |
345 UMA_HISTOGRAM_COUNTS_100("Extensions.InjectIdle_ScriptCount", num_scripts); | 330 UMA_HISTOGRAM_COUNTS_100("Extensions.InjectIdle_ScriptCount", num_scripts); |
346 if (num_scripts) | 331 if (num_scripts) |
347 UMA_HISTOGRAM_TIMES("Extensions.InjectIdle_Time", timer.Elapsed()); | 332 UMA_HISTOGRAM_TIMES("Extensions.InjectIdle_Time", timer.Elapsed()); |
348 } else { | 333 } else { |
349 NOTREACHED(); | 334 NOTREACHED(); |
350 } | 335 } |
351 } | 336 } |
OLD | NEW |