summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-08 21:32:34 +0000
committermpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-08 21:32:34 +0000
commit414785a5dce34bbe90b08c360992fd850612c2a1 (patch)
tree74a3f7b053dfc409afbc9187281dc0eac87160de
parent0df4ace4713e5b74a5215638111d514971aaf40d (diff)
downloadchromium_src-414785a5dce34bbe90b08c360992fd850612c2a1.zip
chromium_src-414785a5dce34bbe90b08c360992fd850612c2a1.tar.gz
chromium_src-414785a5dce34bbe90b08c360992fd850612c2a1.tar.bz2
Ensure global extension events (like bookmarks) are sent to the incognito
extension process for split-mode extensions. Also cleaned up some naming. BUG=58189 TEST=no Review URL: http://codereview.chromium.org/3578017 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@62018 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/all_urls_apitest.cc26
-rw-r--r--chrome/browser/extensions/extension_accessibility_api.cc2
-rw-r--r--chrome/browser/extensions/extension_bookmark_manager_api.cc2
-rw-r--r--chrome/browser/extensions/extension_bookmarks_module.cc2
-rw-r--r--chrome/browser/extensions/extension_context_menu_browsertest.cc14
-rw-r--r--chrome/browser/extensions/extension_incognito_apitest.cc9
-rw-r--r--chrome/browser/extensions/extension_management_api.cc2
-rw-r--r--chrome/browser/extensions/extension_management_api_browsertest.cc8
-rw-r--r--chrome/browser/extensions/extension_management_browsertest.cc4
-rw-r--r--chrome/browser/extensions/extension_message_service.cc18
-rw-r--r--chrome/browser/extensions/extension_message_service.h14
-rw-r--r--chrome/browser/extensions/extension_test_api.cc10
-rw-r--r--chrome/browser/extensions/extension_test_api.h8
-rw-r--r--chrome/browser/extensions/extension_test_message_listener.cc23
-rw-r--r--chrome/browser/extensions/extension_test_message_listener.h35
-rw-r--r--chrome/common/extensions/api/extension_api.json10
-rw-r--r--chrome/renderer/extensions/event_bindings.cc13
-rw-r--r--chrome/renderer/extensions/event_bindings.h2
-rw-r--r--chrome/renderer/extensions/extension_process_bindings.cc15
-rw-r--r--chrome/renderer/extensions/extension_process_bindings.h2
-rw-r--r--chrome/renderer/extensions/renderer_extension_bindings.cc4
-rw-r--r--chrome/renderer/extensions/renderer_extension_bindings.h2
-rw-r--r--chrome/renderer/render_thread.cc4
-rw-r--r--chrome/renderer/render_thread.h2
-rw-r--r--chrome/renderer/render_view.cc4
-rw-r--r--chrome/renderer/render_view.h2
-rw-r--r--chrome/test/data/extensions/api_test/incognito/split/background.html51
-rw-r--r--chrome/test/data/extensions/api_test/incognito/split/manifest.json2
28 files changed, 203 insertions, 87 deletions
diff --git a/chrome/browser/extensions/all_urls_apitest.cc b/chrome/browser/extensions/all_urls_apitest.cc
index 24166fc..ff82075 100644
--- a/chrome/browser/extensions/all_urls_apitest.cc
+++ b/chrome/browser/extensions/all_urls_apitest.cc
@@ -46,32 +46,32 @@ IN_PROC_BROWSER_TEST_F(AllUrlsApiTest, WhitelistedExtension) {
// Now verify we run content scripts on chrome://newtab/.
url = "chrome://newtab/";
- ExtensionTestMessageListener listener1a("content script: " + url);
- ExtensionTestMessageListener listener1b("execute: " + url);
+ ExtensionTestMessageListener listener1a("content script: " + url, false);
+ ExtensionTestMessageListener listener1b("execute: " + url, false);
ui_test_utils::NavigateToURL(browser(), GURL(url));
ASSERT_TRUE(listener1a.WaitUntilSatisfied());
ASSERT_TRUE(listener1b.WaitUntilSatisfied());
// Now verify data: urls.
url = "data:text/html;charset=utf-8,<html>asdf</html>";
- ExtensionTestMessageListener listener2a("content script: " + url);
- ExtensionTestMessageListener listener2b("execute: " + url);
+ ExtensionTestMessageListener listener2a("content script: " + url, false);
+ ExtensionTestMessageListener listener2b("execute: " + url, false);
ui_test_utils::NavigateToURL(browser(), GURL(url));
ASSERT_TRUE(listener2a.WaitUntilSatisfied());
ASSERT_TRUE(listener2b.WaitUntilSatisfied());
// Now verify about:version.
url = "about:version";
- ExtensionTestMessageListener listener3a("content script: " + url);
- ExtensionTestMessageListener listener3b("execute: " + url);
+ ExtensionTestMessageListener listener3a("content script: " + url, false);
+ ExtensionTestMessageListener listener3b("execute: " + url, false);
ui_test_utils::NavigateToURL(browser(), GURL(url));
ASSERT_TRUE(listener3a.WaitUntilSatisfied());
ASSERT_TRUE(listener3b.WaitUntilSatisfied());
// Now verify about:blank.
url = "about:blank";
- ExtensionTestMessageListener listener4a("content script: " + url);
- ExtensionTestMessageListener listener4b("execute: " + url);
+ ExtensionTestMessageListener listener4a("content script: " + url, false);
+ ExtensionTestMessageListener listener4b("execute: " + url, false);
ui_test_utils::NavigateToURL(browser(), GURL(url));
ASSERT_TRUE(listener4a.WaitUntilSatisfied());
ASSERT_TRUE(listener4b.WaitUntilSatisfied());
@@ -79,8 +79,9 @@ IN_PROC_BROWSER_TEST_F(AllUrlsApiTest, WhitelistedExtension) {
// Now verify we can script a regular http page.
ASSERT_TRUE(test_server()->Start());
GURL page_url = test_server()->GetURL(kAllUrlsTarget);
- ExtensionTestMessageListener listener5a("content script: " + page_url.spec());
- ExtensionTestMessageListener listener5b("execute: " + page_url.spec());
+ ExtensionTestMessageListener listener5a("content script: " + page_url.spec(),
+ false);
+ ExtensionTestMessageListener listener5b("execute: " + page_url.spec(), false);
ui_test_utils::NavigateToURL(browser(), page_url);
ASSERT_TRUE(listener5a.WaitUntilSatisfied());
ASSERT_TRUE(listener5b.WaitUntilSatisfied());
@@ -104,8 +105,9 @@ IN_PROC_BROWSER_TEST_F(AllUrlsApiTest, RegularExtensions) {
// Now verify we can script a regular http page.
ASSERT_TRUE(test_server()->Start());
GURL page_url = test_server()->GetURL(kAllUrlsTarget);
- ExtensionTestMessageListener listener1a("content script: " + page_url.spec());
- ExtensionTestMessageListener listener1b("execute: " + page_url.spec());
+ ExtensionTestMessageListener listener1a("content script: " + page_url.spec(),
+ false);
+ ExtensionTestMessageListener listener1b("execute: " + page_url.spec(), false);
ui_test_utils::NavigateToURL(browser(), page_url);
ASSERT_TRUE(listener1a.WaitUntilSatisfied());
ASSERT_TRUE(listener1b.WaitUntilSatisfied());
diff --git a/chrome/browser/extensions/extension_accessibility_api.cc b/chrome/browser/extensions/extension_accessibility_api.cc
index 83a6194..235a521 100644
--- a/chrome/browser/extensions/extension_accessibility_api.cc
+++ b/chrome/browser/extensions/extension_accessibility_api.cc
@@ -183,7 +183,7 @@ void ExtensionAccessibilityEventRouter::DispatchEvent(
const std::string& json_args) {
if (enabled_ && profile && profile->GetExtensionMessageService()) {
profile->GetExtensionMessageService()->DispatchEventToRenderers(
- event_name, json_args, profile, GURL());
+ event_name, json_args, NULL, GURL());
}
}
diff --git a/chrome/browser/extensions/extension_bookmark_manager_api.cc b/chrome/browser/extensions/extension_bookmark_manager_api.cc
index 0b0dc0f..f5db93f 100644
--- a/chrome/browser/extensions/extension_bookmark_manager_api.cc
+++ b/chrome/browser/extensions/extension_bookmark_manager_api.cc
@@ -161,7 +161,7 @@ void ExtensionBookmarkManagerEventRouter::DispatchEvent(const char* event_name,
std::string json_args;
base::JSONWriter::Write(args, false, &json_args);
profile_->GetExtensionMessageService()->DispatchEventToRenderers(
- event_name, json_args, profile_, GURL());
+ event_name, json_args, NULL, GURL());
}
void ExtensionBookmarkManagerEventRouter::DispatchDragEvent(
diff --git a/chrome/browser/extensions/extension_bookmarks_module.cc b/chrome/browser/extensions/extension_bookmarks_module.cc
index 4044bfc..991ea2d 100644
--- a/chrome/browser/extensions/extension_bookmarks_module.cc
+++ b/chrome/browser/extensions/extension_bookmarks_module.cc
@@ -97,7 +97,7 @@ void ExtensionBookmarkEventRouter::DispatchEvent(Profile *profile,
const std::string json_args) {
if (profile->GetExtensionMessageService()) {
profile->GetExtensionMessageService()->DispatchEventToRenderers(
- event_name, json_args, profile, GURL());
+ event_name, json_args, NULL, GURL());
}
}
diff --git a/chrome/browser/extensions/extension_context_menu_browsertest.cc b/chrome/browser/extensions/extension_context_menu_browsertest.cc
index 427a7fc..62221e1 100644
--- a/chrome/browser/extensions/extension_context_menu_browsertest.cc
+++ b/chrome/browser/extensions/extension_context_menu_browsertest.cc
@@ -180,8 +180,8 @@ class ExtensionContextMenuBrowserTest : public ExtensionBrowserTest {
// Tests adding a simple context menu item.
IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, Simple) {
- ExtensionTestMessageListener listener1("created item");
- ExtensionTestMessageListener listener2("onclick fired");
+ ExtensionTestMessageListener listener1("created item", false);
+ ExtensionTestMessageListener listener2("onclick fired", false);
ASSERT_TRUE(LoadContextMenuExtension("simple"));
// Wait for the extension to tell us it's created an item.
@@ -204,7 +204,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, Simple) {
// Tests that setting "documentUrlPatterns" for an item properly restricts
// those items to matching pages.
IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, Patterns) {
- ExtensionTestMessageListener listener("created items");
+ ExtensionTestMessageListener listener("created items", false);
ASSERT_TRUE(LoadContextMenuExtension("patterns"));
@@ -233,7 +233,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, Patterns) {
// Tests registering an item with a very long title that should get truncated in
// the actual menu displayed.
IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, LongTitle) {
- ExtensionTestMessageListener listener("created");
+ ExtensionTestMessageListener listener("created", false);
// Load the extension and wait until it's created a menu item.
ASSERT_TRUE(LoadContextMenuExtension("long_title"));
@@ -307,7 +307,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, Separators) {
// Navigate to test1.html inside the extension, which should create a bunch
// of items at the top-level (but they'll get pushed into an auto-generated
// parent).
- ExtensionTestMessageListener listener1("test1 create finished");
+ ExtensionTestMessageListener listener1("test1 create finished", false);
ui_test_utils::NavigateToURL(browser(),
GURL(extension->GetResourceURL("test1.html")));
listener1.WaitUntilSatisfied();
@@ -332,7 +332,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, Separators) {
// Now run our second test - navigate to test2.html which creates an explicit
// parent node and populates that with the same items as in test1.
- ExtensionTestMessageListener listener2("test2 create finished");
+ ExtensionTestMessageListener listener2("test2 create finished", false);
ui_test_utils::NavigateToURL(browser(),
GURL(extension->GetResourceURL("test2.html")));
listener2.WaitUntilSatisfied();
@@ -348,7 +348,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, Separators) {
// Tests that targetUrlPattern keeps items from appearing when there is no
// target url.
IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, TargetURLs) {
- ExtensionTestMessageListener listener("created items");
+ ExtensionTestMessageListener listener("created items", false);
ASSERT_TRUE(LoadContextMenuExtension("target_urls"));
ASSERT_TRUE(listener.WaitUntilSatisfied());
diff --git a/chrome/browser/extensions/extension_incognito_apitest.cc b/chrome/browser/extensions/extension_incognito_apitest.cc
index 51742e8..675e2bb 100644
--- a/chrome/browser/extensions/extension_incognito_apitest.cc
+++ b/chrome/browser/extensions/extension_incognito_apitest.cc
@@ -7,6 +7,7 @@
#include "chrome/browser/browser_window.h"
#include "chrome/browser/extensions/browser_action_test_util.h"
#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/extensions/user_script_master.h"
#include "chrome/browser/profile.h"
@@ -132,6 +133,14 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_IncognitoSplitMode) {
ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
.AppendASCII("incognito").AppendASCII("split")));
+ // Wait for both extensions to be ready before telling them to proceed.
+ ExtensionTestMessageListener listener("waiting", true);
+ EXPECT_TRUE(listener.WaitUntilSatisfied());
+ ExtensionTestMessageListener listener_incognito("waiting", true);
+ EXPECT_TRUE(listener_incognito.WaitUntilSatisfied());
+ listener.Reply("go");
+ listener_incognito.Reply("go");
+
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
EXPECT_TRUE(catcher_incognito.GetNextResult()) << catcher.message();
}
diff --git a/chrome/browser/extensions/extension_management_api.cc b/chrome/browser/extensions/extension_management_api.cc
index fe6888a..e42764d 100644
--- a/chrome/browser/extensions/extension_management_api.cc
+++ b/chrome/browser/extensions/extension_management_api.cc
@@ -233,6 +233,6 @@ void ExtensionManagementEventRouter::Observe(
profile->GetExtensionMessageService();
message_service->DispatchEventToRenderers(event_name,
args_json,
- profile,
+ NULL,
GURL());
}
diff --git a/chrome/browser/extensions/extension_management_api_browsertest.cc b/chrome/browser/extensions/extension_management_api_browsertest.cc
index 7061637..80955ba 100644
--- a/chrome/browser/extensions/extension_management_api_browsertest.cc
+++ b/chrome/browser/extensions/extension_management_api_browsertest.cc
@@ -10,20 +10,20 @@ class ExtensionManagementApiBrowserTest : public ExtensionBrowserTest {};
// We test this here instead of in an ExtensionApiTest because normal extensions
// are not allowed to call the install function.
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest, InstallEvent) {
- ExtensionTestMessageListener listener1("ready");
+ ExtensionTestMessageListener listener1("ready", false);
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("management/install_event")));
ASSERT_TRUE(listener1.WaitUntilSatisfied());
- ExtensionTestMessageListener listener2("got_event");
+ ExtensionTestMessageListener listener2("got_event", false);
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("api_test/management/enabled_extension")));
ASSERT_TRUE(listener2.WaitUntilSatisfied());
}
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest, LaunchApp) {
- ExtensionTestMessageListener listener1("app_launched");
- ExtensionTestMessageListener listener2("got_expected_error");
+ ExtensionTestMessageListener listener1("app_launched", false);
+ ExtensionTestMessageListener listener2("got_expected_error", false);
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("management/simple_extension")));
ASSERT_TRUE(LoadExtension(
diff --git a/chrome/browser/extensions/extension_management_browsertest.cc b/chrome/browser/extensions/extension_management_browsertest.cc
index 1c6fb68b..2e528b5 100644
--- a/chrome/browser/extensions/extension_management_browsertest.cc
+++ b/chrome/browser/extensions/extension_management_browsertest.cc
@@ -209,7 +209,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, AutoUpdate) {
basedir.AppendASCII("v2.crx"));
// Install version 1 of the extension.
- ExtensionTestMessageListener listener1("v1 installed");
+ ExtensionTestMessageListener listener1("v1 installed", false);
ExtensionsService* service = browser()->profile()->GetExtensionsService();
const size_t size_before = service->extensions()->size();
ASSERT_TRUE(service->disabled_extensions()->empty());
@@ -226,7 +226,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, AutoUpdate) {
service->updater()->set_blacklist_checks_enabled(false);
// Run autoupdate and make sure version 2 of the extension was installed.
- ExtensionTestMessageListener listener2("v2 installed");
+ ExtensionTestMessageListener listener2("v2 installed", false);
service->updater()->CheckNow();
ASSERT_TRUE(WaitForExtensionInstall());
listener2.WaitUntilSatisfied();
diff --git a/chrome/browser/extensions/extension_message_service.cc b/chrome/browser/extensions/extension_message_service.cc
index 40bfc32..6a615ff 100644
--- a/chrome/browser/extensions/extension_message_service.cc
+++ b/chrome/browser/extensions/extension_message_service.cc
@@ -96,13 +96,13 @@ static void DispatchOnMessage(const ExtensionMessageService::MessagePort& port,
static void DispatchEvent(const ExtensionMessageService::MessagePort& port,
const std::string& event_name,
const std::string& event_args,
- bool has_incognito_data,
+ bool cross_incognito,
const GURL& event_url) {
ListValue args;
args.Set(0, Value::CreateStringValue(event_name));
args.Set(1, Value::CreateStringValue(event_args));
port.sender->Send(new ViewMsg_ExtensionMessageInvoke(port.routing_id,
- ExtensionMessageService::kDispatchEvent, args, has_incognito_data,
+ ExtensionMessageService::kDispatchEvent, args, cross_incognito,
event_url));
}
@@ -392,12 +392,12 @@ void ExtensionMessageService::PostMessageFromRenderer(
void ExtensionMessageService::DispatchEventToRenderers(
const std::string& event_name, const std::string& event_args,
- Profile* source_profile, const GURL& event_url) {
+ Profile* restrict_to_profile, const GURL& event_url) {
if (!profile_)
return;
// We don't expect to get events from a completely different profile.
- DCHECK(!source_profile || profile_->IsSameProfile(source_profile));
+ DCHECK(!restrict_to_profile || profile_->IsSameProfile(restrict_to_profile));
ListenerMap::iterator it = listeners_.find(event_name);
if (it == listeners_.end())
@@ -418,18 +418,18 @@ void ExtensionMessageService::DispatchEventToRenderers(
// Is this event from a different profile than the renderer (ie, an
// incognito tab event sent to a normal process, or vice versa).
- bool cross_profile =
- source_profile && renderer->profile() != source_profile;
- DispatchEvent(renderer, event_name, event_args, cross_profile, event_url);
+ bool cross_incognito =
+ restrict_to_profile && renderer->profile() != restrict_to_profile;
+ DispatchEvent(renderer, event_name, event_args, cross_incognito, event_url);
}
}
void ExtensionMessageService::DispatchEventToExtension(
const std::string& extension_id,
const std::string& event_name, const std::string& event_args,
- Profile* source_profile, const GURL& event_url) {
+ Profile* restrict_to_profile, const GURL& event_url) {
DispatchEventToRenderers(GetPerExtensionEventName(event_name, extension_id),
- event_args, source_profile, event_url);
+ event_args, restrict_to_profile, event_url);
}
void ExtensionMessageService::Observe(NotificationType type,
diff --git a/chrome/browser/extensions/extension_message_service.h b/chrome/browser/extensions/extension_message_service.h
index 9d8c038..79ef344 100644
--- a/chrome/browser/extensions/extension_message_service.h
+++ b/chrome/browser/extensions/extension_message_service.h
@@ -81,20 +81,22 @@ class ExtensionMessageService
// Returns true if there is at least one listener for the given event.
bool HasEventListener(const std::string& event_name);
- // Send an event to every registered extension renderer. If
- // |has_incognito_data| is true, the event is only sent to extension with the
- // permission to access incognito data. If |event_url| is not empty, the
- // event is only sent to extension with host permissions for this url.
+ // Send an event to every registered extension renderer. If
+ // |restrict_to_profile| is non-NULL, then the event will not be sent to other
+ // profiles unless the extension has permission (e.g. incognito tab update ->
+ // normal profile only works if extension is allowed incognito access). If
+ // |event_url| is not empty, the event is only sent to extension with host
+ // permissions for this url.
virtual void DispatchEventToRenderers(
const std::string& event_name, const std::string& event_args,
- Profile* source_profile, const GURL& event_url);
+ Profile* restrict_to_profile, const GURL& event_url);
// Same as above, except use the extension-specific naming scheme for the
// event. This is used by events that are per-extension.
void DispatchEventToExtension(
const std::string& extension_id,
const std::string& event_name, const std::string& event_args,
- Profile* source_profile, const GURL& event_url);
+ Profile* restrict_to_profile, const GURL& event_url);
// Given an extension's ID, opens a channel between the given renderer "port"
// and every listening context owned by that extension. |channel_name| is
diff --git a/chrome/browser/extensions/extension_test_api.cc b/chrome/browser/extensions/extension_test_api.cc
index 858d25b..b5f64ba 100644
--- a/chrome/browser/extensions/extension_test_api.cc
+++ b/chrome/browser/extensions/extension_test_api.cc
@@ -54,10 +54,16 @@ bool ExtensionTestCreateIncognitoTabFunction::RunImpl() {
bool ExtensionTestSendMessageFunction::RunImpl() {
std::string message;
EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &message));
- std::string id = extension_id();
+ AddRef(); // balanced in Reply
NotificationService::current()->Notify(
NotificationType::EXTENSION_TEST_MESSAGE,
- Source<std::string>(&id),
+ Source<ExtensionTestSendMessageFunction>(this),
Details<std::string>(&message));
return true;
}
+
+void ExtensionTestSendMessageFunction::Reply(const std::string& message) {
+ result_.reset(Value::CreateStringValue(message));
+ SendResponse(true);
+ Release(); // balanced in RunImpl
+}
diff --git a/chrome/browser/extensions/extension_test_api.h b/chrome/browser/extensions/extension_test_api.h
index f59d0b5..e0b8dce 100644
--- a/chrome/browser/extensions/extension_test_api.h
+++ b/chrome/browser/extensions/extension_test_api.h
@@ -38,7 +38,13 @@ class ExtensionTestCreateIncognitoTabFunction : public SyncExtensionFunction {
DECLARE_EXTENSION_FUNCTION_NAME("test.createIncognitoTab")
};
-class ExtensionTestSendMessageFunction : public SyncExtensionFunction {
+class ExtensionTestSendMessageFunction : public AsyncExtensionFunction {
+ public:
+ // Sends a reply back to the calling extension. Many extensions don't need
+ // a reply and will just ignore it.
+ void Reply(const std::string& message);
+
+ private:
~ExtensionTestSendMessageFunction() {}
virtual bool RunImpl();
DECLARE_EXTENSION_FUNCTION_NAME("test.sendMessage")
diff --git a/chrome/browser/extensions/extension_test_message_listener.cc b/chrome/browser/extensions/extension_test_message_listener.cc
index bfa9db7..423bf3b 100644
--- a/chrome/browser/extensions/extension_test_message_listener.cc
+++ b/chrome/browser/extensions/extension_test_message_listener.cc
@@ -4,14 +4,18 @@
#include "chrome/browser/extensions/extension_test_message_listener.h"
+#include "chrome/browser/extensions/extension_test_api.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "chrome/test/ui_test_utils.h"
ExtensionTestMessageListener::ExtensionTestMessageListener(
- const std::string& expected_message)
- : expected_message_(expected_message), satisfied_(false),
- waiting_(false) {
+ const std::string& expected_message,
+ bool will_reply)
+ : expected_message_(expected_message),
+ satisfied_(false),
+ waiting_(false),
+ will_reply_(will_reply) {
registrar_.Add(this, NotificationType::EXTENSION_TEST_MESSAGE,
NotificationService::AllSources());
}
@@ -26,14 +30,27 @@ bool ExtensionTestMessageListener::WaitUntilSatisfied() {
return satisfied_;
}
+void ExtensionTestMessageListener::Reply(const std::string& message) {
+ DCHECK(satisfied_);
+ DCHECK(will_reply_);
+ function_->Reply(message);
+ function_ = NULL;
+ will_reply_ = false;
+}
+
void ExtensionTestMessageListener::Observe(
NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
const std::string& content = *Details<std::string>(details).ptr();
+ function_ = Source<ExtensionTestSendMessageFunction>(source).ptr();
if (!satisfied_ && content == expected_message_) {
satisfied_ = true;
registrar_.RemoveAll(); // Stop listening for more messages.
+ if (!will_reply_) {
+ function_->Reply("");
+ function_ = NULL;
+ }
if (waiting_) {
waiting_ = false;
MessageLoopForUI::current()->Quit();
diff --git a/chrome/browser/extensions/extension_test_message_listener.h b/chrome/browser/extensions/extension_test_message_listener.h
index 2aeedd8..bead446 100644
--- a/chrome/browser/extensions/extension_test_message_listener.h
+++ b/chrome/browser/extensions/extension_test_message_listener.h
@@ -11,14 +11,7 @@
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
-// A message from javascript sent via chrome.test.sendMessage().
-struct ExtensionTestMessage {
- // The sender's extension id.
- std::string extension_id;
-
- // The message content.
- std::string content;
-};
+class ExtensionTestSendMessageFunction;
// This class helps us wait for incoming messages sent from javascript via
// chrome.test.sendMessage(). A sample usage would be:
@@ -27,6 +20,18 @@ struct ExtensionTestMessage {
// ... do some work
// ASSERT_TRUE(listener.WaitUntilSatisfied());
//
+// It is also possible to have the extension wait for our reply. This is
+// useful for coordinating multiple pages/processes and having them wait on
+// each other. Example:
+//
+// ExtensionTestMessageListener listener1("foo1");
+// ExtensionTestMessageListener listener2("foo2");
+// ASSERT_TRUE(listener1.WaitUntilSatisfied());
+// ASSERT_TRUE(listener2.WaitUntilSatisfied());
+// ... do some work
+// listener1.Reply("foo2 is ready");
+// listener2.Reply("foo1 is ready");
+//
// TODO(asargent) - In the future we may want to add the ability to listen for
// multiple messages, and/or to wait for "any" message and then retrieve the
// contents of that message. We may also want to specify an extension id as
@@ -40,7 +45,8 @@ struct ExtensionTestMessage {
class ExtensionTestMessageListener : public NotificationObserver {
public:
// We immediately start listening for |expected_message|.
- explicit ExtensionTestMessageListener(const std::string& expected_message);
+ ExtensionTestMessageListener(const std::string& expected_message,
+ bool will_reply);
~ExtensionTestMessageListener();
// This returns true immediately if we've already gotten the expected
@@ -48,6 +54,10 @@ class ExtensionTestMessageListener : public NotificationObserver {
// interrupted and we still haven't gotten the message.
bool WaitUntilSatisfied();
+ // Send the given message as a reply. It is only valid to call this after
+ // WaitUntilSatisfied has returned true, and if will_reply is true.
+ void Reply(const std::string& message);
+
// Implements the NotificationObserver interface.
virtual void Observe(NotificationType type,
const NotificationSource& source,
@@ -65,6 +75,13 @@ class ExtensionTestMessageListener : public NotificationObserver {
// If we're waiting, then we want to post a quit task when the expected
// message arrives.
bool waiting_;
+
+ // If true, we expect the calling code to manually send a reply. Otherwise,
+ // we send an automatic empty reply to the extension.
+ bool will_reply_;
+
+ // The function we need to reply to.
+ ExtensionTestSendMessageFunction* function_;
};
#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_TEST_MESSAGE_LISTENER_H_
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index 142b3a4..860f94d 100644
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -3431,7 +3431,15 @@
"type": "function",
"description": "Sends a string message to the browser process, generating a Notification that C++ test code can wait for.",
"parameters": [
- {"type": "string", "name": "message"}
+ {"type": "string", "name": "message"},
+ {
+ "type": "function",
+ "name": "callback",
+ "optional": true,
+ "parameters": [
+ {"type": "string", "name": "response"}
+ ]
+ }
]
}
],
diff --git a/chrome/renderer/extensions/event_bindings.cc b/chrome/renderer/extensions/event_bindings.cc
index 6f3b7e3..9c3f421 100644
--- a/chrome/renderer/extensions/event_bindings.cc
+++ b/chrome/renderer/extensions/event_bindings.cc
@@ -140,12 +140,12 @@ class ExtensionImpl : public ExtensionBase {
// Returns true if the extension running in the given |context| has sufficient
// permissions to access the data.
static bool HasSufficientPermissions(ContextInfo* context,
- bool requires_incognito_access,
+ bool cross_incognito,
const GURL& event_url) {
v8::Context::Scope context_scope(context->context);
- bool cross_profile_ok = (!requires_incognito_access ||
- ExtensionProcessBindings::AllowCrossProfile(context->extension_id));
+ bool cross_profile_ok = (!cross_incognito ||
+ ExtensionProcessBindings::AllowCrossIncognito(context->extension_id));
if (!cross_profile_ok)
return false;
@@ -338,7 +338,7 @@ void EventBindings::HandleContextDestroyed(WebFrame* frame) {
void EventBindings::CallFunction(const std::string& function_name,
int argc, v8::Handle<v8::Value>* argv,
RenderView* render_view,
- bool requires_incognito_access,
+ bool cross_incognito,
const GURL& event_url) {
// We copy the context list, because calling into javascript may modify it
// out from under us. We also guard against deleted contexts by checking if
@@ -353,11 +353,8 @@ void EventBindings::CallFunction(const std::string& function_name,
if ((*it)->context.IsEmpty())
continue;
- if (!HasSufficientPermissions(it->get(),
- requires_incognito_access,
- event_url)) {
+ if (!HasSufficientPermissions(it->get(), cross_incognito, event_url))
continue;
- }
v8::Handle<v8::Value> retval = CallFunctionInContext((*it)->context,
function_name, argc, argv);
diff --git a/chrome/renderer/extensions/event_bindings.h b/chrome/renderer/extensions/event_bindings.h
index 037a1eb..788a25c 100644
--- a/chrome/renderer/extensions/event_bindings.h
+++ b/chrome/renderer/extensions/event_bindings.h
@@ -44,7 +44,7 @@ class EventBindings {
static void CallFunction(const std::string& function_name, int argc,
v8::Handle<v8::Value>* argv,
RenderView* render_view,
- bool requires_incognito_access,
+ bool cross_incognito,
const GURL& event_url);
};
diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc
index a5b9fe5..fed2fe3 100644
--- a/chrome/renderer/extensions/extension_process_bindings.cc
+++ b/chrome/renderer/extensions/extension_process_bindings.cc
@@ -65,7 +65,7 @@ typedef std::map<std::string, PermissionsList> ExtensionPermissionsList;
// A map of extension ID to whether this extension can access data from other
// profiles.
-typedef std::map<std::string, bool> CrossProfileAccessMap;
+typedef std::map<std::string, bool> CrossIncognitoAccessMap;
const char kExtensionName[] = "chrome/ExtensionProcessBindings";
const char* kExtensionDeps[] = {
@@ -80,7 +80,7 @@ struct SingletonData {
std::set<std::string> function_names_;
PageActionIdMap page_action_ids_;
ExtensionPermissionsList permissions_;
- CrossProfileAccessMap cross_profile_access_map_;
+ CrossIncognitoAccessMap cross_incognito_access_map_;
};
static std::set<std::string>* GetFunctionNameSet() {
@@ -95,8 +95,8 @@ static PermissionsList* GetPermissionsList(const std::string& extension_id) {
return &Singleton<SingletonData>()->permissions_[extension_id];
}
-static CrossProfileAccessMap* GetCrossProfileAccessMap() {
- return &Singleton<SingletonData>()->cross_profile_access_map_;
+static CrossIncognitoAccessMap* GetCrossIncognitoAccessMap() {
+ return &Singleton<SingletonData>()->cross_incognito_access_map_;
}
static void GetActiveExtensionIDs(std::set<std::string>* extension_ids) {
@@ -586,14 +586,15 @@ void ExtensionProcessBindings::SetIncognitoEnabled(
// We allow the extension to see events and data from another profile iff it
// uses "spanning" behavior and it has incognito access. "split" mode
// extensions only see events for a matching profile.
- (*GetCrossProfileAccessMap())[extension_id] =
+ (*GetCrossIncognitoAccessMap())[extension_id] =
enabled && !incognito_split_mode;
}
// static
-bool ExtensionProcessBindings::AllowCrossProfile(
+bool ExtensionProcessBindings::AllowCrossIncognito(
const std::string& extension_id) {
- return (!extension_id.empty() && (*GetCrossProfileAccessMap())[extension_id]);
+ return (!extension_id.empty() &&
+ (*GetCrossIncognitoAccessMap())[extension_id]);
}
// static
diff --git a/chrome/renderer/extensions/extension_process_bindings.h b/chrome/renderer/extensions/extension_process_bindings.h
index 2cbbf4c..251cdd9 100644
--- a/chrome/renderer/extensions/extension_process_bindings.h
+++ b/chrome/renderer/extensions/extension_process_bindings.h
@@ -54,7 +54,7 @@ class ExtensionProcessBindings {
// Checks whether the given extension can see events/data from another
// profile (normal to incognito or vice versa).
- static bool AllowCrossProfile(const std::string& extension_id);
+ static bool AllowCrossIncognito(const std::string& extension_id);
// Check if the extension in the currently running context has permission to
// access the given extension function. Must be called with a valid V8
diff --git a/chrome/renderer/extensions/renderer_extension_bindings.cc b/chrome/renderer/extensions/renderer_extension_bindings.cc
index e3d820a..2e21c56 100644
--- a/chrome/renderer/extensions/renderer_extension_bindings.cc
+++ b/chrome/renderer/extensions/renderer_extension_bindings.cc
@@ -298,7 +298,7 @@ v8::Extension* RendererExtensionBindings::Get() {
void RendererExtensionBindings::Invoke(const std::string& function_name,
const ListValue& args,
RenderView* renderview,
- bool requires_incognito_access,
+ bool cross_incognito,
const GURL& event_url) {
v8::HandleScope handle_scope;
std::vector< v8::Handle<v8::Value> > argv = ListValueToV8(args);
@@ -306,6 +306,6 @@ void RendererExtensionBindings::Invoke(const std::string& function_name,
argv.size(),
&argv[0],
renderview,
- requires_incognito_access,
+ cross_incognito,
event_url);
}
diff --git a/chrome/renderer/extensions/renderer_extension_bindings.h b/chrome/renderer/extensions/renderer_extension_bindings.h
index 15fe532..7b4280f 100644
--- a/chrome/renderer/extensions/renderer_extension_bindings.h
+++ b/chrome/renderer/extensions/renderer_extension_bindings.h
@@ -26,7 +26,7 @@ class RendererExtensionBindings {
// Call the given javascript function with the specified arguments.
static void Invoke(const std::string& function_name, const ListValue& args,
- RenderView* renderview, bool requires_incognito_access,
+ RenderView* renderview, bool cross_incognito,
const GURL& event_url);
};
diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc
index a0cdd5f..5b1b6c2 100644
--- a/chrome/renderer/render_thread.cc
+++ b/chrome/renderer/render_thread.cc
@@ -976,10 +976,10 @@ void RenderThread::ScheduleIdleHandler(double initial_delay_s) {
void RenderThread::OnExtensionMessageInvoke(const std::string& function_name,
const ListValue& args,
- bool requires_incognito_access,
+ bool cross_incognito,
const GURL& event_url) {
RendererExtensionBindings::Invoke(
- function_name, args, NULL, requires_incognito_access, event_url);
+ function_name, args, NULL, cross_incognito, event_url);
// Reset the idle handler each time there's any activity like event or message
// dispatch, for which Invoke is the chokepoint.
diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h
index c0d5964..9f2c4c0 100644
--- a/chrome/renderer/render_thread.h
+++ b/chrome/renderer/render_thread.h
@@ -291,7 +291,7 @@ class RenderThread : public RenderThreadBase,
void OnExtensionMessageInvoke(const std::string& function_name,
const ListValue& args,
- bool requires_incognito_access,
+ bool cross_incognito,
const GURL& event_url);
void OnPurgeMemory();
void OnPurgePluginListCache(bool reload_pages);
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 1e8a533..2c84869 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -4869,10 +4869,10 @@ void RenderView::OnExtensionResponse(int request_id,
void RenderView::OnExtensionMessageInvoke(const std::string& function_name,
const ListValue& args,
- bool requires_incognito_access,
+ bool cross_incognito,
const GURL& event_url) {
RendererExtensionBindings::Invoke(
- function_name, args, this, requires_incognito_access, event_url);
+ function_name, args, this, cross_incognito, event_url);
}
// Dump all load time histograms.
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index 2fb488c..a09e9f1 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -797,7 +797,7 @@ class RenderView : public RenderWidget,
void OnExecuteEditCommand(const std::string& name, const std::string& value);
void OnExtensionMessageInvoke(const std::string& function_name,
const ListValue& args,
- bool requires_incognito_access,
+ bool cross_incognito,
const GURL& event_url);
void OnFileChooserResponse(const std::vector<FilePath>& paths);
void OnFind(int request_id, const string16&, const WebKit::WebFindOptions&);
diff --git a/chrome/test/data/extensions/api_test/incognito/split/background.html b/chrome/test/data/extensions/api_test/incognito/split/background.html
index 32fec55..50ebea6 100644
--- a/chrome/test/data/extensions/api_test/incognito/split/background.html
+++ b/chrome/test/data/extensions/api_test/incognito/split/background.html
@@ -6,6 +6,27 @@ var assertTrue = chrome.test.assertTrue;
var win, tab;
var inIncognitoContext = chrome.extension.inIncognitoContext;
+// Lifted from the bookmarks api_test.
+function compareNode(left, right) {
+ //chrome.test.log("compareNode()");
+ //chrome.test.log(JSON.stringify(left, null, 2));
+ //chrome.test.log(JSON.stringify(right, null, 2));
+ // TODO(erikkay): do some comparison of dateAdded
+ if (left.id != right.id)
+ return "id mismatch: " + left.id + " != " + right.id;
+ if (left.title != right.title) {
+ // TODO(erikkay): This resource dependency still isn't working reliably.
+ // See bug 19866.
+ // return "title mismatch: " + left.title + " != " + right.title;
+ chrome.test.log("title mismatch: " + left.title + " != " + right.title);
+ }
+ if (left.url != right.url)
+ return "url mismatch: " + left.url + " != " + right.url;
+ if (left.index != right.index)
+ return "index mismatch: " + left.index + " != " + right.index;
+ return true;
+}
+
// Listen to some events to make sure we don't get events from the other
// profile.
@@ -84,6 +105,36 @@ chrome.test.runTests([
sendResponse();
done();
});
+ },
+
+ // Tests that we can receive bookmarks events in both extension processes.
+ function bookmarkCreate() {
+ // Each process will create 1 bookmark, but expects to see updates from the
+ // other process.
+ var nodeNormal = {parentId:"1", title:"normal", url:"http://google.com/"};
+ var nodeIncog = {parentId:"1", title:"incog", url:"http://google.com/"};
+ var node = inIncognitoContext ? nodeIncog : nodeNormal;
+ var count = 0;
+ var done = chrome.test.listenForever(chrome.bookmarks.onCreated,
+ function(id, created) {
+ node = (created.title == nodeNormal.title) ? nodeNormal : nodeIncog;
+ node.id = created.id;
+ node.index = created.index;
+ chrome.test.assertEq(id, node.id);
+ chrome.test.assertTrue(compareNode(node, created));
+ if (++count == 2) {
+ chrome.test.log("Bookmarks created. Incognito=" + inIncognitoContext);
+ done();
+ }
+ });
+ chrome.test.sendMessage("waiting", pass(function() {
+ chrome.bookmarks.create(node, pass(function(results) {
+ node.id = results.id; // since we couldn't know this going in
+ node.index = results.index;
+ chrome.test.assertTrue(compareNode(node, results),
+ "created node != source");
+ }));
+ }));
}
]);
</script>
diff --git a/chrome/test/data/extensions/api_test/incognito/split/manifest.json b/chrome/test/data/extensions/api_test/incognito/split/manifest.json
index b3a9206..38efa71 100644
--- a/chrome/test/data/extensions/api_test/incognito/split/manifest.json
+++ b/chrome/test/data/extensions/api_test/incognito/split/manifest.json
@@ -4,5 +4,5 @@
"description": "test that an incognito extension in split mode behaves properly",
"background_page": "background.html",
"incognito": "split",
- "permissions": ["tabs", "http://*/*"]
+ "permissions": ["tabs", "bookmarks", "http://*/*"]
}