| 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 |