diff options
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(); |