summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-08 01:52:56 +0000
committeraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-08 01:52:56 +0000
commit146486ff9a39e4d323df0e60e891e33a1e8d8390 (patch)
treef61da72a65c5c94807b639a6c88b7d8b4369dfb2
parenta74efa3f82f1ce5ed2d61cfc1ac22410355eb32f (diff)
downloadchromium_src-146486ff9a39e4d323df0e60e891e33a1e8d8390.zip
chromium_src-146486ff9a39e4d323df0e60e891e33a1e8d8390.tar.gz
chromium_src-146486ff9a39e4d323df0e60e891e33a1e8d8390.tar.bz2
Make all content scripts from an extension run in the same
isolated world. Chromium side of change. Review URL: http://codereview.chromium.org/262002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28369 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--DEPS2
-rw-r--r--chrome/browser/extensions/isolated_world_apitest.cc16
-rwxr-xr-xchrome/chrome.gyp2
-rw-r--r--chrome/renderer/render_view.cc5
-rw-r--r--chrome/renderer/user_script_slave.cc27
-rw-r--r--chrome/renderer/user_script_slave.h2
-rw-r--r--chrome/test/data/extensions/api_test/isolated_world1/a.js2
-rw-r--r--chrome/test/data/extensions/api_test/isolated_world1/b.js2
-rw-r--r--chrome/test/data/extensions/api_test/isolated_world1/background.html23
-rw-r--r--chrome/test/data/extensions/api_test/isolated_world1/c.js2
-rw-r--r--chrome/test/data/extensions/api_test/isolated_world1/manifest.json17
-rw-r--r--chrome/test/data/extensions/api_test/isolated_world2/a.js3
-rw-r--r--chrome/test/data/extensions/api_test/isolated_world2/background.html18
-rw-r--r--chrome/test/data/extensions/api_test/isolated_world2/manifest.json7
-rw-r--r--webkit/api/public/WebFrame.h6
-rw-r--r--webkit/glue/webframe_impl.cc6
-rw-r--r--webkit/glue/webframe_impl.h6
-rw-r--r--webkit/tools/test_shell/layout_test_controller.cc9
18 files changed, 138 insertions, 17 deletions
diff --git a/DEPS b/DEPS
index 95b5a3b..c3a95a7 100644
--- a/DEPS
+++ b/DEPS
@@ -1,7 +1,7 @@
vars = {
"webkit_trunk":
"http://svn.webkit.org/repository/webkit/trunk",
- "webkit_revision": "49260",
+ "webkit_revision": "49278",
"ffmpeg_revision": "27457",
}
diff --git a/chrome/browser/extensions/isolated_world_apitest.cc b/chrome/browser/extensions/isolated_world_apitest.cc
new file mode 100644
index 0000000..25c6144
--- /dev/null
+++ b/chrome/browser/extensions/isolated_world_apitest.cc
@@ -0,0 +1,16 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/extension_apitest.h"
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IsolatedWorld1) {
+ // This extension runs various bits of script and tests that they all run in
+ // the same isolated world.
+ StartHTTPServer();
+ ASSERT_TRUE(RunExtensionTest("isolated_world1")) << message_;
+
+ // Now load a different extension, inject into same page, verify worlds aren't
+ // shared.
+ ASSERT_TRUE(RunExtensionTest("isolated_world2")) << message_;
+}
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 0aef38a..780dc7d 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -62,6 +62,7 @@
'browser/extensions/extension_browsertests_misc.cc',
'browser/extensions/extension_override_apitest.cc',
'browser/extensions/extension_toolstrip_apitest.cc',
+ 'browser/extensions/isolated_world_apitest.cc'
],
'browser_tests_sources_win_specific': [
'browser/extensions/browser_action_test.cc',
@@ -95,6 +96,7 @@
'browser/extensions/extension_browsertests_misc.cc',
'browser/extensions/extension_override_apitest.cc',
'browser/extensions/extension_toolstrip_apitest.cc',
+ 'browser/extensions/isolated_world_apitest.cc',
'browser/ssl/ssl_browser_tests.cc',
],
# TODO(jcampan): move these vars to views.gyp.
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index ae98ac3..7c626ad 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -3606,8 +3606,9 @@ void RenderView::OnExecuteCode(int request_id, const std::string& extension_id,
sources.push_back(
WebScriptSource(WebString::fromUTF8(code_string)));
UserScriptSlave::InsertInitExtensionCode(&sources, extension_id);
- main_frame->executeScriptInNewWorld(&sources.front(), sources.size(),
- EXTENSION_GROUP_CONTENT_SCRIPTS);
+ main_frame->executeScriptInIsolatedWorld(
+ UserScriptSlave::GetIsolatedWorldId(extension_id),
+ &sources.front(), sources.size(), EXTENSION_GROUP_CONTENT_SCRIPTS);
} else {
main_frame->insertStyleText(WebString::fromUTF8(code_string), WebString());
}
diff --git a/chrome/renderer/user_script_slave.cc b/chrome/renderer/user_script_slave.cc
index f76a1e7..86fcc1a 100644
--- a/chrome/renderer/user_script_slave.cc
+++ b/chrome/renderer/user_script_slave.cc
@@ -32,6 +32,25 @@ static const char kInitExtension[] =
"chrome.extension = new chrome.Extension('%s');"
"chrome.self.onConnect = chrome.extension.onConnect;";
+int UserScriptSlave::GetIsolatedWorldId(const std::string& extension_id) {
+ typedef std::map<std::string, int> IsolatedWorldMap;
+
+ static IsolatedWorldMap g_isolated_world_ids;
+ static int g_next_isolated_world_id = 1;
+
+ IsolatedWorldMap::iterator iter = g_isolated_world_ids.find(extension_id);
+ if (iter != g_isolated_world_ids.end())
+ return iter->second;
+
+ int new_id = g_next_isolated_world_id;
+ ++g_next_isolated_world_id;
+
+ // This map will tend to pile up over time, but realistically, you're never
+ // going to have enough extensions for it to matter.
+ g_isolated_world_ids[extension_id] = new_id;
+ return new_id;
+}
+
UserScriptSlave::UserScriptSlave()
: shared_memory_(NULL),
script_deleter_(&scripts_),
@@ -159,6 +178,8 @@ bool UserScriptSlave::InjectScripts(WebFrame* frame,
}
if (!sources.empty()) {
+ int isolated_world_id = 0;
+
if (script->is_standalone()) {
// For standalone scripts, we try to emulate the Greasemonkey API.
sources.insert(sources.begin(),
@@ -167,10 +188,12 @@ bool UserScriptSlave::InjectScripts(WebFrame* frame,
// Setup chrome.self to contain an Extension object with the correct
// ID.
InsertInitExtensionCode(&sources, script->extension_id());
+ isolated_world_id = GetIsolatedWorldId(script->extension_id());
}
- frame->executeScriptInNewWorld(&sources.front(), sources.size(),
- EXTENSION_GROUP_CONTENT_SCRIPTS);
+ frame->executeScriptInIsolatedWorld(
+ isolated_world_id, &sources.front(), sources.size(),
+ EXTENSION_GROUP_CONTENT_SCRIPTS);
}
}
diff --git a/chrome/renderer/user_script_slave.h b/chrome/renderer/user_script_slave.h
index 39407f1..8232ec4 100644
--- a/chrome/renderer/user_script_slave.h
+++ b/chrome/renderer/user_script_slave.h
@@ -35,6 +35,8 @@ class UserScriptSlave {
// testability.
bool InjectScripts(WebKit::WebFrame* frame, UserScript::RunLocation location);
+ static int GetIsolatedWorldId(const std::string& extension_id);
+
static void InsertInitExtensionCode(std::vector<WebScriptSource>* sources,
const std::string& extension_id);
private:
diff --git a/chrome/test/data/extensions/api_test/isolated_world1/a.js b/chrome/test/data/extensions/api_test/isolated_world1/a.js
new file mode 100644
index 0000000..95eacea
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/isolated_world1/a.js
@@ -0,0 +1,2 @@
+// This variable is read and updated by other script from the extenion.
+var num = 1;
diff --git a/chrome/test/data/extensions/api_test/isolated_world1/b.js b/chrome/test/data/extensions/api_test/isolated_world1/b.js
new file mode 100644
index 0000000..5e66b40
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/isolated_world1/b.js
@@ -0,0 +1,2 @@
+// Updates the variable defined in a.js.
+num++;
diff --git a/chrome/test/data/extensions/api_test/isolated_world1/background.html b/chrome/test/data/extensions/api_test/isolated_world1/background.html
new file mode 100644
index 0000000..d5125c4
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/isolated_world1/background.html
@@ -0,0 +1,23 @@
+<script>
+chrome.extension.onConnect.addListener(function(port) {
+ chrome.test.log("got connect");
+ port.onMessage.addListener(function(msg) {
+ chrome.test.log("got message: " + msg);
+ chrome.test.assertEq(2, msg);
+ chrome.test.notifyPass();
+ });
+});
+
+chrome.tabs.onUpdated.addListener(function(tabId, changeInfo) {
+ chrome.test.log("Got update event: " + JSON.stringify(changeInfo));
+ if (changeInfo.status == "complete") {
+ chrome.tabs.executeScript(tabId, {file: "c.js"});
+ chrome.tabs.onUpdated.removeListener(arguments.callee);
+ }
+});
+
+chrome.test.log("Creating tab...");
+chrome.tabs.create({
+ url: "http://localhost:1337/files/extensions/test_file.html"
+});
+</script>
diff --git a/chrome/test/data/extensions/api_test/isolated_world1/c.js b/chrome/test/data/extensions/api_test/isolated_world1/c.js
new file mode 100644
index 0000000..d3bbc41
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/isolated_world1/c.js
@@ -0,0 +1,2 @@
+// Send the variable defined by a.js and modified by b.js back to the extension.
+chrome.extension.connect().postMessage(num);
diff --git a/chrome/test/data/extensions/api_test/isolated_world1/manifest.json b/chrome/test/data/extensions/api_test/isolated_world1/manifest.json
new file mode 100644
index 0000000..0528cdd
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/isolated_world1/manifest.json
@@ -0,0 +1,17 @@
+{
+ "name": "isolated world 1",
+ "version": "0.1",
+ "description": "tests that all scripts from an extension run in the same isolated world",
+ "background_page": "background.html",
+ "permissions": ["http://*/*", "tabs"],
+ "content_scripts": [
+ {
+ "matches": ["http://*/*"],
+ "js": ["a.js"]
+ },
+ {
+ "matches": ["http://*/*"],
+ "js": ["b.js"]
+ }
+ ]
+}
diff --git a/chrome/test/data/extensions/api_test/isolated_world2/a.js b/chrome/test/data/extensions/api_test/isolated_world2/a.js
new file mode 100644
index 0000000..394feee
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/isolated_world2/a.js
@@ -0,0 +1,3 @@
+// We should not be able to read the "num" variable which was defined in a.js
+// from the "isolated world 1" extension.
+chrome.extension.connect().postMessage(typeof num == "undefined");
diff --git a/chrome/test/data/extensions/api_test/isolated_world2/background.html b/chrome/test/data/extensions/api_test/isolated_world2/background.html
new file mode 100644
index 0000000..731182f
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/isolated_world2/background.html
@@ -0,0 +1,18 @@
+<script>
+chrome.extension.onConnect.addListener(function(port) {
+ chrome.test.log("got connect");
+ port.onMessage.addListener(function(msg) {
+ chrome.test.log("got message: " + msg);
+ chrome.test.assertTrue(msg);
+ chrome.test.notifyPass();
+ });
+});
+
+chrome.tabs.getAllInWindow(null, function(tabs) {
+ chrome.test.log("Got tabs: " + JSON.stringify(tabs));
+
+ // The last tab is the one that the other extension should have run scripts
+ // in.
+ chrome.tabs.executeScript(tabs.pop().id, {file: "a.js"});
+});
+</script>
diff --git a/chrome/test/data/extensions/api_test/isolated_world2/manifest.json b/chrome/test/data/extensions/api_test/isolated_world2/manifest.json
new file mode 100644
index 0000000..c4c60b5
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/isolated_world2/manifest.json
@@ -0,0 +1,7 @@
+{
+ "name": "isolated world 2",
+ "version": "0.1",
+ "description": "together with isolated world 1, tests that scripts from different extensions run in different worlds",
+ "background_page": "background.html",
+ "permissions": ["http://*/*", "tabs"]
+}
diff --git a/webkit/api/public/WebFrame.h b/webkit/api/public/WebFrame.h
index 07f5cf5..671c550 100644
--- a/webkit/api/public/WebFrame.h
+++ b/webkit/api/public/WebFrame.h
@@ -196,9 +196,9 @@ namespace WebKit {
// extensionGroup is an embedder-provided specifier that controls which
// v8 extensions are loaded into the new context - see
// WebKit::registerExtension for the corresponding specifier.
- virtual void executeScriptInNewWorld(const WebScriptSource* sources,
- unsigned numSources,
- int extensionGroup) = 0;
+ virtual void executeScriptInIsolatedWorld(
+ int worldId, const WebScriptSource* sources, unsigned numSources,
+ int extensionGroup) = 0;
// Logs to the console associated with this frame.
virtual void addMessageToConsole(const WebConsoleMessage&) = 0;
diff --git a/webkit/glue/webframe_impl.cc b/webkit/glue/webframe_impl.cc
index 7fd7ce9..511a238 100644
--- a/webkit/glue/webframe_impl.cc
+++ b/webkit/glue/webframe_impl.cc
@@ -628,8 +628,8 @@ void WebFrameImpl::executeScriptInNewContext(
frame_->script()->evaluateInNewContext(sources, extension_group);
}
-void WebFrameImpl::executeScriptInNewWorld(
- const WebScriptSource* sources_in, unsigned num_sources,
+void WebFrameImpl::executeScriptInIsolatedWorld(
+ int world_id, const WebScriptSource* sources_in, unsigned num_sources,
int extension_group) {
Vector<WebCore::ScriptSourceCode> sources;
@@ -640,7 +640,7 @@ void WebFrameImpl::executeScriptInNewWorld(
sources_in[i].startLine));
}
- frame_->script()->evaluateInNewWorld(sources, extension_group);
+ frame_->script()->evaluateInIsolatedWorld(world_id, sources, extension_group);
}
void WebFrameImpl::addMessageToConsole(const WebConsoleMessage& message) {
diff --git a/webkit/glue/webframe_impl.h b/webkit/glue/webframe_impl.h
index b4cff81..f840df4 100644
--- a/webkit/glue/webframe_impl.h
+++ b/webkit/glue/webframe_impl.h
@@ -99,9 +99,9 @@ class WebFrameImpl : public WebKit::WebFrame, public RefCounted<WebFrameImpl> {
virtual void executeScriptInNewContext(
const WebKit::WebScriptSource* sources, unsigned num_sources,
int extension_group);
- virtual void executeScriptInNewWorld(
- const WebKit::WebScriptSource* sources, unsigned num_sources,
- int extension_group);
+ virtual void executeScriptInIsolatedWorld(
+ int world_id, const WebKit::WebScriptSource* sources,
+ unsigned num_sources, int extension_group);
virtual void addMessageToConsole(const WebKit::WebConsoleMessage&);
virtual void collectGarbage();
#if WEBKIT_USING_V8
diff --git a/webkit/tools/test_shell/layout_test_controller.cc b/webkit/tools/test_shell/layout_test_controller.cc
index 3dd2be2..d757d8b 100644
--- a/webkit/tools/test_shell/layout_test_controller.cc
+++ b/webkit/tools/test_shell/layout_test_controller.cc
@@ -825,9 +825,12 @@ void LayoutTestController::setXSSAuditorEnabled(
void LayoutTestController::evaluateScriptInIsolatedWorld(
const CppArgumentList& args, CppVariant* result) {
- if (args.size() > 0 && args[0].isString()) {
- WebScriptSource source(WebString::fromUTF8(args[0].ToString()));
- shell_->webView()->mainFrame()->executeScriptInNewWorld(&source, 1, 1);
+ if (args.size() >= 2 && args[0].isNumber() && args[1].isString()) {
+ WebScriptSource source(WebString::fromUTF8(args[1].ToString()));
+ // This relies on the iframe focusing itself when it loads. This is a bit
+ // sketchy, but it seems to be what other tests do.
+ shell_->webView()->focusedFrame()->executeScriptInIsolatedWorld(
+ args[0].ToInt32(), &source, 1, 1);
}
result->SetNull();
}