summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/api/messaging/extension_message_port.cc6
-rw-r--r--chrome/browser/extensions/api/messaging/extension_message_port.h2
-rw-r--r--chrome/browser/extensions/api/messaging/message_service.cc10
-rw-r--r--chrome/browser/extensions/api/messaging/message_service.h15
-rw-r--r--chrome/browser/extensions/api/messaging/native_message_port.cc7
-rw-r--r--chrome/browser/extensions/api/messaging/native_message_port.h2
-rw-r--r--chrome/browser/extensions/extension_messages_apitest.cc45
-rw-r--r--chrome/browser/extensions/extension_web_contents_observer.cc3
-rw-r--r--chrome/browser/extensions/extension_web_contents_observer.h3
-rw-r--r--chrome/chrome_common.gypi1
-rw-r--r--chrome/common/extensions/api/messaging/message.h22
-rw-r--r--chrome/common/extensions/api/test.json31
-rw-r--r--chrome/common/extensions/extension_messages.h10
-rw-r--r--chrome/renderer/extensions/dispatcher.cc49
-rw-r--r--chrome/renderer/extensions/dispatcher.h3
-rw-r--r--chrome/renderer/extensions/extension_helper.cc3
-rw-r--r--chrome/renderer/extensions/extension_helper.h3
-rw-r--r--chrome/renderer/extensions/messaging_bindings.cc17
-rw-r--r--chrome/renderer/extensions/messaging_bindings.h3
-rw-r--r--chrome/renderer/resources/extensions/test_custom_bindings.js15
20 files changed, 218 insertions, 32 deletions
diff --git a/chrome/browser/extensions/api/messaging/extension_message_port.cc b/chrome/browser/extensions/api/messaging/extension_message_port.cc
index 9d14a6e..9e0ca61 100644
--- a/chrome/browser/extensions/api/messaging/extension_message_port.cc
+++ b/chrome/browser/extensions/api/messaging/extension_message_port.cc
@@ -47,10 +47,10 @@ void ExtensionMessagePort::DispatchOnDisconnect(
routing_id_, source_port_id, error_message));
}
-void ExtensionMessagePort::DispatchOnMessage(const std::string& message,
+void ExtensionMessagePort::DispatchOnMessage(const Message& message,
int target_port_id) {
- process_->Send(new ExtensionMsg_DeliverMessage(
- routing_id_, target_port_id, message));
+ process_->Send(new ExtensionMsg_DeliverMessage(
+ routing_id_, target_port_id, message));
}
void ExtensionMessagePort::IncrementLazyKeepaliveCount() {
diff --git a/chrome/browser/extensions/api/messaging/extension_message_port.h b/chrome/browser/extensions/api/messaging/extension_message_port.h
index 1e7b788..d0a6273 100644
--- a/chrome/browser/extensions/api/messaging/extension_message_port.h
+++ b/chrome/browser/extensions/api/messaging/extension_message_port.h
@@ -31,7 +31,7 @@ class ExtensionMessagePort : public MessageService::MessagePort {
const std::string& tls_channel_id) OVERRIDE;
virtual void DispatchOnDisconnect(int source_port_id,
const std::string& error_message) OVERRIDE;
- virtual void DispatchOnMessage(const std::string& message,
+ virtual void DispatchOnMessage(const Message& message,
int target_port_id) OVERRIDE;
virtual void IncrementLazyKeepaliveCount() OVERRIDE;
virtual void DecrementLazyKeepaliveCount() OVERRIDE;
diff --git a/chrome/browser/extensions/api/messaging/message_service.cc b/chrome/browser/extensions/api/messaging/message_service.cc
index 754bc10..cdf65278 100644
--- a/chrome/browser/extensions/api/messaging/message_service.cc
+++ b/chrome/browser/extensions/api/messaging/message_service.cc
@@ -530,7 +530,7 @@ void MessageService::CloseChannelImpl(
}
void MessageService::PostMessage(
- int source_port_id, const std::string& message) {
+ int source_port_id, const Message& message) {
int channel_id = GET_CHANNEL_ID(source_port_id);
MessageChannelMap::iterator iter = channels_.find(channel_id);
if (iter == channels_.end()) {
@@ -545,7 +545,7 @@ void MessageService::PostMessage(
void MessageService::PostMessageFromNativeProcess(int port_id,
const std::string& message) {
- PostMessage(port_id, message);
+ PostMessage(port_id, Message(message, false /* user_gesture */));
}
void MessageService::Observe(int type,
@@ -593,7 +593,7 @@ void MessageService::OnProcessClosed(content::RenderProcessHost* process) {
void MessageService::EnqueuePendingMessage(int source_port_id,
int channel_id,
- const std::string& message) {
+ const Message& message) {
PendingTlsChannelIdMap::iterator pending_for_tls_channel_id =
pending_tls_channel_id_channels_.find(channel_id);
if (pending_for_tls_channel_id != pending_tls_channel_id_channels_.end()) {
@@ -611,7 +611,7 @@ void MessageService::EnqueuePendingMessage(int source_port_id,
void MessageService::EnqueuePendingMessageForLazyBackgroundLoad(
int source_port_id,
int channel_id,
- const std::string& message) {
+ const Message& message) {
PendingLazyBackgroundPageChannelMap::iterator pending =
pending_lazy_background_page_channels_.find(channel_id);
if (pending != pending_lazy_background_page_channels_.end()) {
@@ -624,7 +624,7 @@ void MessageService::EnqueuePendingMessageForLazyBackgroundLoad(
void MessageService::DispatchMessage(int source_port_id,
MessageChannel* channel,
- const std::string& message) {
+ const Message& message) {
// Figure out which port the ID corresponds to.
int dest_port_id = GET_OPPOSITE_PORT_ID(source_port_id);
MessagePort* port = IS_OPENER_PORT_ID(dest_port_id) ?
diff --git a/chrome/browser/extensions/api/messaging/message_service.h b/chrome/browser/extensions/api/messaging/message_service.h
index 168da41..ed6eae9 100644
--- a/chrome/browser/extensions/api/messaging/message_service.h
+++ b/chrome/browser/extensions/api/messaging/message_service.h
@@ -16,6 +16,7 @@
#include "chrome/browser/extensions/api/messaging/message_property_provider.h"
#include "chrome/browser/extensions/api/messaging/native_message_process_host.h"
#include "chrome/browser/extensions/api/profile_keyed_api_factory.h"
+#include "chrome/common/extensions/api/messaging/message.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
@@ -85,7 +86,7 @@ class MessageService : public ProfileKeyedAPI,
const std::string& error_message) {}
// Dispatch a message to this end of the communication.
- virtual void DispatchOnMessage(const std::string& message,
+ virtual void DispatchOnMessage(const Message& message,
int target_port_id) = 0;
// MessagPorts that target extensions will need to adjust their keepalive
@@ -149,7 +150,7 @@ class MessageService : public ProfileKeyedAPI,
// Enqueues a message on a pending channel, or sends a message to the given
// port if the channel isn't pending.
- void PostMessage(int port_id, const std::string& message);
+ void PostMessage(int port_id, const Message& message);
// NativeMessageProcessHost::Client
virtual void PostMessageFromNativeProcess(
@@ -164,7 +165,7 @@ class MessageService : public ProfileKeyedAPI,
// A map of channel ID to its channel object.
typedef std::map<int, MessageChannel*> MessageChannelMap;
- typedef std::pair<int, std::string> PendingMessage;
+ typedef std::pair<int, Message> PendingMessage;
typedef std::vector<PendingMessage> PendingMessagesQueue;
// A set of channel IDs waiting for TLS channel IDs to complete opening,
// and any pending messages queued to be sent on those channels.
@@ -202,16 +203,16 @@ class MessageService : public ProfileKeyedAPI,
// Enqueues a message on a pending channel.
void EnqueuePendingMessage(int port_id, int channel_id,
- const std::string& message);
+ const Message& message);
// Enqueues a message on a channel pending on a lazy background page load.
void EnqueuePendingMessageForLazyBackgroundLoad(int port_id,
int channel_id,
- const std::string& message);
+ const Message& message);
// Immediately sends a message to the given port.
void DispatchMessage(int port_id, MessageChannel* channel,
- const std::string& message);
+ const Message& message);
// Potentially registers a pending task with the LazyBackgroundTaskQueue
// to open a channel. Returns true if a task was queued.
@@ -235,7 +236,7 @@ class MessageService : public ProfileKeyedAPI,
CloseChannel(port_id, error_message);
}
void PendingLazyBackgroundPagePostMessage(int port_id,
- const std::string& message,
+ const Message& message,
extensions::ExtensionHost* host) {
if (host)
PostMessage(port_id, message);
diff --git a/chrome/browser/extensions/api/messaging/native_message_port.cc b/chrome/browser/extensions/api/messaging/native_message_port.cc
index e746e29..a0a47d5 100644
--- a/chrome/browser/extensions/api/messaging/native_message_port.cc
+++ b/chrome/browser/extensions/api/messaging/native_message_port.cc
@@ -19,12 +19,13 @@ NativeMessagePort::~NativeMessagePort() {
content::BrowserThread::IO, FROM_HERE, native_process_);
}
-void NativeMessagePort::DispatchOnMessage(const std::string& message,
- int target_port_id) {
+void NativeMessagePort::DispatchOnMessage(
+ const Message& message,
+ int target_port_id) {
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::Bind(&NativeMessageProcessHost::Send,
- base::Unretained(native_process_), message));
+ base::Unretained(native_process_), message.data));
}
} // namespace extensions
diff --git a/chrome/browser/extensions/api/messaging/native_message_port.h b/chrome/browser/extensions/api/messaging/native_message_port.h
index 6afce8a..f94db96 100644
--- a/chrome/browser/extensions/api/messaging/native_message_port.h
+++ b/chrome/browser/extensions/api/messaging/native_message_port.h
@@ -16,7 +16,7 @@ class NativeMessagePort : public MessageService::MessagePort {
// Takes ownership of |native_process|.
explicit NativeMessagePort(NativeMessageProcessHost* native_process);
virtual ~NativeMessagePort();
- virtual void DispatchOnMessage(const std::string& message,
+ virtual void DispatchOnMessage(const Message& message,
int target_port_id) OVERRIDE;
private:
diff --git a/chrome/browser/extensions/extension_messages_apitest.cc b/chrome/browser/extensions/extension_messages_apitest.cc
index 131a743..b47e8ea 100644
--- a/chrome/browser/extensions/extension_messages_apitest.cc
+++ b/chrome/browser/extensions/extension_messages_apitest.cc
@@ -850,5 +850,50 @@ IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingWithTlsChannelIdTest,
EXPECT_EQ(expected_tls_channel_id_value, tls_channel_id);
}
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MessagingUserGesture) {
+ const char kManifest[] = "{"
+ " \"name\": \"user_gesture\","
+ " \"version\": \"1.0\","
+ " \"background\": {"
+ " \"scripts\": [\"background.js\"]"
+ " },"
+ " \"manifest_version\": 2"
+ "}";
+
+ TestExtensionDir receiver_dir;
+ receiver_dir.WriteManifest(kManifest);
+ receiver_dir.WriteFile(FILE_PATH_LITERAL("background.js"),
+ "chrome.runtime.onMessageExternal.addListener(\n"
+ " function(msg, sender, reply) {\n"
+ " reply({result:chrome.test.isProcessingUserGesture()});\n"
+ " });");
+ const Extension* receiver = LoadExtension(receiver_dir.unpacked_path());
+ ASSERT_TRUE(receiver);
+
+ TestExtensionDir sender_dir;
+ sender_dir.WriteManifest(kManifest);
+ sender_dir.WriteFile(FILE_PATH_LITERAL("background.js"), "");
+ const Extension* sender = LoadExtension(sender_dir.unpacked_path());
+ ASSERT_TRUE(sender);
+
+ EXPECT_EQ("false",
+ ExecuteScriptInBackgroundPage(sender->id(),
+ base::StringPrintf(
+ "chrome.test.runWithoutUserGesture(function() {\n"
+ " chrome.runtime.sendMessage('%s', {}, function(response) {\n"
+ " window.domAutomationController.send('' + response.result);\n"
+ " });\n"
+ "});", receiver->id().c_str())));
+
+ EXPECT_EQ("true",
+ ExecuteScriptInBackgroundPage(sender->id(),
+ base::StringPrintf(
+ "chrome.test.runWithUserGesture(function() {\n"
+ " chrome.runtime.sendMessage('%s', {}, function(response) {\n"
+ " window.domAutomationController.send('' + response.result);\n"
+ " });\n"
+ "});", receiver->id().c_str())));
+}
+
} // namespace
}; // namespace extensions
diff --git a/chrome/browser/extensions/extension_web_contents_observer.cc b/chrome/browser/extensions/extension_web_contents_observer.cc
index 8f648b6..fba7f6e 100644
--- a/chrome/browser/extensions/extension_web_contents_observer.cc
+++ b/chrome/browser/extensions/extension_web_contents_observer.cc
@@ -8,6 +8,7 @@
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/extensions/api/messaging/message.h"
#include "chrome/common/extensions/extension_messages.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/child_process_security_policy.h"
@@ -100,7 +101,7 @@ bool ExtensionWebContentsObserver::OnMessageReceived(
}
void ExtensionWebContentsObserver::OnPostMessage(int port_id,
- const std::string& message) {
+ const Message& message) {
MessageService* message_service = MessageService::Get(profile_);
if (message_service) {
message_service->PostMessage(port_id, message);
diff --git a/chrome/browser/extensions/extension_web_contents_observer.h b/chrome/browser/extensions/extension_web_contents_observer.h
index dbac7f9..019dc88 100644
--- a/chrome/browser/extensions/extension_web_contents_observer.h
+++ b/chrome/browser/extensions/extension_web_contents_observer.h
@@ -12,6 +12,7 @@ class Profile;
namespace extensions {
class Extension;
+struct Message;
// A web contents observer that's used for WebContents in renderer and extension
// processes.
@@ -30,7 +31,7 @@ class ExtensionWebContentsObserver
content::RenderViewHost* render_view_host) OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- void OnPostMessage(int port_id, const std::string& message);
+ void OnPostMessage(int port_id, const Message& message);
// Gets the extension or app (if any) that is associated with a RVH.
const Extension* GetExtension(content::RenderViewHost* render_view_host);
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index 2367b4f..aa38210 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -144,6 +144,7 @@
'common/extensions/api/managed_mode_private/managed_mode_handler.h',
'common/extensions/api/media_galleries_private/media_galleries_handler.h',
'common/extensions/api/media_galleries_private/media_galleries_handler.cc',
+ 'common/extensions/api/messaging/message.h',
'common/extensions/api/omnibox/omnibox_handler.cc',
'common/extensions/api/omnibox/omnibox_handler.h',
'common/extensions/api/plugins/plugins_handler.cc',
diff --git a/chrome/common/extensions/api/messaging/message.h b/chrome/common/extensions/api/messaging/message.h
new file mode 100644
index 0000000..5a03224
--- /dev/null
+++ b/chrome/common/extensions/api/messaging/message.h
@@ -0,0 +1,22 @@
+// Copyright 2013 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.
+
+#ifndef CHROME_COMMON_EXTENSIONS_API_MESSAGING_MESSAGE_H_
+#define CHROME_COMMON_EXTENSIONS_API_MESSAGING_MESSAGE_H_
+
+namespace extensions {
+
+// A message consists of both the data itself as well as a user gestur e state.
+struct Message {
+ std::string data;
+ bool user_gesture;
+
+ Message() : data(), user_gesture(false) {}
+ Message(const std::string& data, bool user_gesture)
+ : data(data), user_gesture(user_gesture) {}
+};
+
+} // namespace extensions
+
+#endif // CHROME_COMMON_EXTENSIONS_API_MESSAGING_MESSAGE_H_
diff --git a/chrome/common/extensions/api/test.json b/chrome/common/extensions/api/test.json
index 134a3ed..17780a3 100644
--- a/chrome/common/extensions/api/test.json
+++ b/chrome/common/extensions/api/test.json
@@ -309,6 +309,37 @@
"items": {"type": "string"}
}
]
+ },
+ {
+ "name": "isProcessingUserGesture",
+ "type": "function",
+ "nocompile": true,
+ "parameters": []
+ },
+ {
+ "name": "runWithUserGesture",
+ "type": "function",
+ "description": "Runs the callback in the context of a user gesture.",
+ "nocompile": true,
+ "parameters": [
+ {
+ "type": "function",
+ "name": "callback",
+ "parameters": []
+ }
+ ]
+ },
+ {
+ "name": "runWithoutUserGesture",
+ "type": "function",
+ "nocompile": true,
+ "parameters": [
+ {
+ "type": "function",
+ "name": "callback",
+ "parameters": []
+ }
+ ]
}
],
"events": [
diff --git a/chrome/common/extensions/extension_messages.h b/chrome/common/extensions/extension_messages.h
index e947497..c2b28c1 100644
--- a/chrome/common/extensions/extension_messages.h
+++ b/chrome/common/extensions/extension_messages.h
@@ -11,6 +11,7 @@
#include "base/memory/shared_memory.h"
#include "base/values.h"
#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/api/messaging/message.h"
#include "chrome/common/extensions/permissions/bluetooth_permission_data.h"
#include "chrome/common/extensions/permissions/media_galleries_permission_data.h"
#include "chrome/common/extensions/permissions/permission_set.h"
@@ -193,6 +194,11 @@ IPC_STRUCT_TRAITS_BEGIN(extensions::BluetoothPermissionData)
IPC_STRUCT_TRAITS_MEMBER(uuid())
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(extensions::Message)
+ IPC_STRUCT_TRAITS_MEMBER(data)
+ IPC_STRUCT_TRAITS_MEMBER(user_gesture)
+IPC_STRUCT_TRAITS_END()
+
// Singly-included section for custom IPC traits.
#ifndef CHROME_COMMON_EXTENSIONS_EXTENSION_MESSAGES_H_
#define CHROME_COMMON_EXTENSIONS_EXTENSION_MESSAGES_H_
@@ -436,7 +442,7 @@ IPC_MESSAGE_ROUTED5(ExtensionMsg_DispatchOnConnect,
// Deliver a message sent with ExtensionHostMsg_PostMessage.
IPC_MESSAGE_ROUTED2(ExtensionMsg_DeliverMessage,
int /* target_port_id */,
- std::string /* message */)
+ extensions::Message)
// Dispatch the Port.onDisconnect event for message channels.
IPC_MESSAGE_ROUTED2(ExtensionMsg_DispatchOnDisconnect,
@@ -547,7 +553,7 @@ IPC_SYNC_MESSAGE_CONTROL4_1(ExtensionHostMsg_OpenChannelToTab,
// by ViewHostMsg_OpenChannelTo*.
IPC_MESSAGE_ROUTED2(ExtensionHostMsg_PostMessage,
int /* port_id */,
- std::string /* message */)
+ extensions::Message)
// Send a message to an extension process. The handle is the value returned
// by ViewHostMsg_OpenChannelTo*.
diff --git a/chrome/renderer/extensions/dispatcher.cc b/chrome/renderer/extensions/dispatcher.cc
index ac0f8f5..3d011c6 100644
--- a/chrome/renderer/extensions/dispatcher.cc
+++ b/chrome/renderer/extensions/dispatcher.cc
@@ -18,6 +18,7 @@
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/crash_keys.h"
#include "chrome/common/extensions/api/extension_api.h"
+#include "chrome/common/extensions/api/messaging/message.h"
#include "chrome/common/extensions/background_info.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_messages.h"
@@ -92,6 +93,7 @@
#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
+#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "ui/base/layout.h"
#include "ui/base/resource/resource_bundle.h"
@@ -160,6 +162,49 @@ class TestFeaturesNativeHandler : public ObjectBackedNativeHandler {
}
};
+class UserGesturesNativeHandler : public ObjectBackedNativeHandler {
+ public:
+ explicit UserGesturesNativeHandler(ChromeV8Context* context)
+ : ObjectBackedNativeHandler(context) {
+ RouteFunction("IsProcessingUserGesture",
+ base::Bind(&UserGesturesNativeHandler::IsProcessingUserGesture,
+ base::Unretained(this)));
+ RouteFunction("RunWithUserGesture",
+ base::Bind(&UserGesturesNativeHandler::RunWithUserGesture,
+ base::Unretained(this)));
+ RouteFunction("RunWithoutUserGesture",
+ base::Bind(&UserGesturesNativeHandler::RunWithoutUserGesture,
+ base::Unretained(this)));
+ }
+
+ private:
+ void IsProcessingUserGesture(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ args.GetReturnValue().Set(v8::Boolean::New(
+ WebKit::WebUserGestureIndicator::isProcessingUserGesture()));
+ }
+
+ void RunWithUserGesture(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ WebKit::WebScopedUserGesture user_gesture;
+ CHECK_EQ(args.Length(), 1);
+ CHECK(args[0]->IsFunction());
+ v8::Handle<v8::Value> no_args;
+ context()->CallFunction(v8::Handle<v8::Function>::Cast(args[0]),
+ 0, &no_args);
+ }
+
+ void RunWithoutUserGesture(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ WebKit::WebUserGestureIndicator::consumeUserGesture();
+ CHECK_EQ(args.Length(), 1);
+ CHECK(args[0]->IsFunction());
+ v8::Handle<v8::Value> no_args;
+ context()->CallFunction(v8::Handle<v8::Function>::Cast(args[0]),
+ 0, &no_args);
+ }
+};
+
class V8ContextNativeHandler : public ObjectBackedNativeHandler {
public:
V8ContextNativeHandler(ChromeV8Context* context, Dispatcher* dispatcher)
@@ -539,7 +584,7 @@ void Dispatcher::OnDispatchOnConnect(
}
void Dispatcher::OnDeliverMessage(int target_port_id,
- const std::string& message) {
+ const Message& message) {
MessagingBindings::DeliverMessage(
v8_context_set_.GetAll(),
target_port_id,
@@ -1076,6 +1121,8 @@ void Dispatcher::DidCreateScriptContext(
scoped_ptr<NativeHandler>(new V8ContextNativeHandler(context, this)));
module_system->RegisterNativeHandler("test_features",
scoped_ptr<NativeHandler>(new TestFeaturesNativeHandler(context)));
+ module_system->RegisterNativeHandler("user_gestures",
+ scoped_ptr<NativeHandler>(new UserGesturesNativeHandler(context)));
int manifest_version = extension ? extension->manifest_version() : 1;
bool send_request_disabled =
diff --git a/chrome/renderer/extensions/dispatcher.h b/chrome/renderer/extensions/dispatcher.h
index 7238c4d..e9ba78ca 100644
--- a/chrome/renderer/extensions/dispatcher.h
+++ b/chrome/renderer/extensions/dispatcher.h
@@ -51,6 +51,7 @@ class Extension;
class FilteredEventRouter;
class RequestSender;
class UserScriptSlave;
+struct Message;
// Dispatches extension control messages sent to the renderer and stores
// renderer extension related state.
@@ -163,7 +164,7 @@ class Dispatcher : public content::RenderProcessObserver {
const base::DictionaryValue& source_tab,
const ExtensionMsg_ExternalConnectionInfo& info,
const std::string& tls_channel_id);
- void OnDeliverMessage(int target_port_id, const std::string& message);
+ void OnDeliverMessage(int target_port_id, const Message& message);
void OnDispatchOnDisconnect(int port_id, const std::string& error_message);
void OnSetFunctionNames(const std::vector<std::string>& names);
void OnSetSystemFont(const std::string& font_family,
diff --git a/chrome/renderer/extensions/extension_helper.cc b/chrome/renderer/extensions/extension_helper.cc
index 4eaf7a8..f717a78 100644
--- a/chrome/renderer/extensions/extension_helper.cc
+++ b/chrome/renderer/extensions/extension_helper.cc
@@ -12,6 +12,7 @@
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/api/messaging/message.h"
#include "chrome/common/extensions/extension_messages.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/url_constants.h"
@@ -281,7 +282,7 @@ void ExtensionHelper::OnExtensionDispatchOnConnect(
}
void ExtensionHelper::OnExtensionDeliverMessage(int target_id,
- const std::string& message) {
+ const Message& message) {
MessagingBindings::DeliverMessage(dispatcher_->v8_context_set().GetAll(),
target_id,
message,
diff --git a/chrome/renderer/extensions/extension_helper.h b/chrome/renderer/extensions/extension_helper.h
index 68ac896e..a5f48ab 100644
--- a/chrome/renderer/extensions/extension_helper.h
+++ b/chrome/renderer/extensions/extension_helper.h
@@ -29,6 +29,7 @@ class ListValue;
namespace extensions {
class Dispatcher;
+struct Message;
// RenderView-level plumbing for extension features.
class ExtensionHelper
@@ -87,7 +88,7 @@ class ExtensionHelper
const ExtensionMsg_ExternalConnectionInfo& info,
const std::string& tls_channel_id);
void OnExtensionDeliverMessage(int target_port_id,
- const std::string& message);
+ const Message& message);
void OnExtensionDispatchOnDisconnect(int port_id,
const std::string& error_message);
void OnExecuteCode(const ExtensionMsg_ExecuteCode_Params& params);
diff --git a/chrome/renderer/extensions/messaging_bindings.cc b/chrome/renderer/extensions/messaging_bindings.cc
index 94275e7..c06422f 100644
--- a/chrome/renderer/extensions/messaging_bindings.cc
+++ b/chrome/renderer/extensions/messaging_bindings.cc
@@ -13,6 +13,7 @@
#include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h"
#include "base/values.h"
+#include "chrome/common/extensions/api/messaging/message.h"
#include "chrome/common/extensions/extension_messages.h"
#include "chrome/common/extensions/manifest_handlers/externally_connectable.h"
#include "chrome/common/extensions/message_bundle.h"
@@ -28,6 +29,8 @@
#include "content/public/renderer/v8_value_converter.h"
#include "grit/renderer_resources.h"
#include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h"
+#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
+#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "v8/include/v8.h"
// Message passing API example (in a content script):
@@ -112,7 +115,10 @@ class ExtensionImpl : public extensions::ChromeV8Extension {
}
renderview->Send(new ExtensionHostMsg_PostMessage(
- renderview->GetRoutingID(), port_id, *v8::String::AsciiValue(args[1])));
+ renderview->GetRoutingID(), port_id,
+ extensions::Message(
+ *v8::String::AsciiValue(args[1]),
+ WebKit::WebUserGestureIndicator::isProcessingUserGesture())));
}
// Forcefully disconnects a port.
@@ -314,8 +320,12 @@ void MessagingBindings::DispatchOnConnect(
void MessagingBindings::DeliverMessage(
const ChromeV8ContextSet::ContextSet& contexts,
int target_port_id,
- const std::string& message,
+ const Message& message,
content::RenderView* restrict_to_render_view) {
+ scoped_ptr<WebKit::WebScopedUserGesture> web_user_gesture;
+ if (message.user_gesture)
+ web_user_gesture.reset(new WebKit::WebScopedUserGesture);
+
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
// TODO(kalman): pass in the full ChromeV8ContextSet; call ForEach.
@@ -343,7 +353,8 @@ void MessagingBindings::DeliverMessage(
continue;
std::vector<v8::Handle<v8::Value> > arguments;
- arguments.push_back(v8::String::New(message.c_str(), message.size()));
+ arguments.push_back(v8::String::New(message.data.c_str(),
+ message.data.size()));
arguments.push_back(port_id_handle);
(*it)->module_system()->CallModuleMethod("messaging",
"dispatchOnMessage",
diff --git a/chrome/renderer/extensions/messaging_bindings.h b/chrome/renderer/extensions/messaging_bindings.h
index 12e2096..c9ebd83 100644
--- a/chrome/renderer/extensions/messaging_bindings.h
+++ b/chrome/renderer/extensions/messaging_bindings.h
@@ -24,6 +24,7 @@ class Extension;
namespace extensions {
class ChromeV8Extension;
class Dispatcher;
+struct Message;
// Manually implements JavaScript bindings for extension messaging.
//
@@ -56,7 +57,7 @@ class MessagingBindings {
static void DeliverMessage(
const ChromeV8ContextSet::ContextSet& context_set,
int target_port_id,
- const std::string& message,
+ const Message& message,
content::RenderView* restrict_to_render_view);
// Dispatches the onDisconnect event in response to the channel being closed.
diff --git a/chrome/renderer/resources/extensions/test_custom_bindings.js b/chrome/renderer/resources/extensions/test_custom_bindings.js
index 7df6f5d..fe60eb2 100644
--- a/chrome/renderer/resources/extensions/test_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/test_custom_bindings.js
@@ -12,6 +12,7 @@ var GetExtensionAPIDefinitionsForTest =
requireNative('apiDefinitions').GetExtensionAPIDefinitionsForTest;
var GetAvailability = requireNative('v8_context').GetAvailability;
var GetAPIFeatures = requireNative('test_features').GetAPIFeatures;
+var userGestures = requireNative('user_gestures');
binding.registerCustomHook(function(api) {
var chromeTest = api.compiledApi;
@@ -326,6 +327,20 @@ binding.registerCustomHook(function(api) {
apiFunctions.setHandleRequest('getApiFeatures', function() {
return GetAPIFeatures();
});
+
+ apiFunctions.setHandleRequest('isProcessingUserGesture', function() {
+ return userGestures.IsProcessingUserGesture();
+ });
+
+ apiFunctions.setHandleRequest('runWithUserGesture', function(callback) {
+ chromeTest.assertEq(typeof(callback), 'function');
+ return userGestures.RunWithUserGesture(callback);
+ });
+
+ apiFunctions.setHandleRequest('runWithoutUserGesture', function(callback) {
+ chromeTest.assertEq(typeof(callback), 'function');
+ return userGestures.RunWithoutUserGesture(callback);
+ });
});
exports.binding = binding.generate();