diff options
22 files changed, 433 insertions, 71 deletions
diff --git a/chrome/browser/browser.scons b/chrome/browser/browser.scons index 8df9881..69a8ba7 100644 --- a/chrome/browser/browser.scons +++ b/chrome/browser/browser.scons @@ -510,6 +510,8 @@ input_files = ChromeFileList([ 'extensions/extension_view.h', 'extensions/extension_error_reporter.cc', 'extensions/extension_error_reporter.h', + 'extensions/extension_message_service.cc', + 'extensions/extension_message_service.h', 'extensions/extension_protocols.h', 'extensions/extensions_service.cc', 'extensions/extensions_service.h', diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index c48c893..842f44c 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -1914,6 +1914,14 @@ > </File> <File + RelativePath=".\extensions\extension_message_service.cc" + > + </File> + <File + RelativePath=".\extensions\extension_message_service.h" + > + </File> + <File RelativePath=".\extensions\extension_protocols.cc" > </File> diff --git a/chrome/browser/extensions/extension_message_service.cc b/chrome/browser/extensions/extension_message_service.cc new file mode 100755 index 0000000..7b79c9e --- /dev/null +++ b/chrome/browser/extensions/extension_message_service.cc @@ -0,0 +1,133 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/extension_message_service.h" + +#include "base/singleton.h" +#include "chrome/browser/chrome_thread.h" +#include "chrome/browser/extensions/extension.h" +#include "chrome/browser/extensions/extension_view.h" +#include "chrome/browser/renderer_host/render_view_host.h" +#include "chrome/browser/renderer_host/render_process_host.h" +#include "chrome/browser/renderer_host/resource_message_filter.h" +#include "chrome/common/render_messages.h" + +// This class acts as the port to an extension process. It is basically just +// gymnastics to get access to the IPC::Channel (not the ChannelProxy) belonging +// to an ExtensionView. +// Created on the UI thread, but accessed fully on the IO thread. +class ExtensionMessageService::ExtensionFilter : + public IPC::ChannelProxy::MessageFilter { + public: + ExtensionFilter(const std::string& extension_id, int routing_id) : + extension_id_(extension_id), routing_id_(routing_id), channel_(NULL) { + } + ~ExtensionFilter() { + ExtensionMessageService::GetInstance()->OnExtensionUnregistered(this); + } + + virtual void OnFilterAdded(IPC::Channel* channel) { + channel_ = channel; + ExtensionMessageService::GetInstance()->OnExtensionRegistered(this); + } + virtual void OnChannelClosing() { + channel_ = NULL; + } + + bool Send(IPC::Message* message) { + if (!channel_) { + delete message; + return false; + } + return channel_->Send(message); + } + + IPC::Channel* channel() { return channel_; } + const std::string& extension_id() { return extension_id_; } + int routing_id() { return routing_id_; } + + private: + std::string extension_id_; + int routing_id_; + IPC::Channel* channel_; +}; + +ExtensionMessageService* ExtensionMessageService::GetInstance() { + return Singleton<ExtensionMessageService>::get(); +} + +ExtensionMessageService::ExtensionMessageService() + : next_channel_id_(0) { +} + +void ExtensionMessageService::RegisterExtensionView(ExtensionView* view) { + view->render_view_host()->process()->channel()->AddFilter( + new ExtensionFilter(view->extension()->id(), + view->render_view_host()->routing_id())); +} + +void ExtensionMessageService::OnExtensionRegistered(ExtensionFilter* filter) { + extensions_[filter->extension_id()] = filter; +} + +void ExtensionMessageService::OnExtensionUnregistered(ExtensionFilter* filter) { + // TODO(mpcomplete): support multiple filters per extension_id + //DCHECK(extensions_[filter->extension_id()] == filter); + extensions_.erase(filter->extension_id()); + + // Close any channels that share this filter. + for (MessageChannelMap::iterator it = channels_.begin(); + it != channels_.end(); ) { + MessageChannelMap::iterator current = it++; + if (current->second.extension_port == filter) + channels_.erase(current); + } +} + +int ExtensionMessageService::OpenChannelToExtension( + const std::string& extension_id, ResourceMessageFilter* renderer_port) { + DCHECK(MessageLoop::current() == + ChromeThread::GetMessageLoop(ChromeThread::IO)); + + ExtensionMap::iterator extension_port = extensions_.find(extension_id); + if (extension_port == extensions_.end()) + return -1; + + int channel_id = next_channel_id_++; + MessageChannel channel; + channel.renderer_port = renderer_port; + channel.extension_port = extension_port->second; + channels_[channel_id] = channel; + + return channel_id; +} + +void ExtensionMessageService::PostMessage( + int channel_id, const std::string& message) { + DCHECK(MessageLoop::current() == + ChromeThread::GetMessageLoop(ChromeThread::IO)); + + MessageChannelMap::iterator iter = channels_.find(channel_id); + if (iter == channels_.end()) + return; + + MessageChannel& channel = iter->second; + channel.extension_port->Send(new ViewMsg_HandleExtensionMessage( + channel.extension_port->routing_id(), message, channel_id)); +} + +void ExtensionMessageService::RendererShutdown( + ResourceMessageFilter* renderer_port) { + DCHECK(MessageLoop::current() == + ChromeThread::GetMessageLoop(ChromeThread::IO)); + + // Close any channels that share this filter. + // TODO(mpcomplete): should we notify the other side of the port? + for (MessageChannelMap::iterator it = channels_.begin(); + it != channels_.end(); ) { + MessageChannelMap::iterator current = it++; + if (current->second.renderer_port == renderer_port) + channels_.erase(current); + } +} diff --git a/chrome/browser/extensions/extension_message_service.h b/chrome/browser/extensions/extension_message_service.h new file mode 100755 index 0000000..eef1676 --- /dev/null +++ b/chrome/browser/extensions/extension_message_service.h @@ -0,0 +1,73 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_MESSAGE_SERVICE_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_MESSAGE_SERVICE_H_ + +#include <map> +#include <string> + +class ExtensionView; +class ResourceMessageFilter; + +// This class manages message passing to and from extension processes. It +// maintains a list of available extensions, as well as a set of open channels. +// It should only be accessed on the IO thread, with the exception of +// RegisterExtensionView(). +// +// Terminology: +// channel: connection between two ports (one of which belongs to an extension) +// port: an IPC::Message::Sender interface through which we communicate to a +// process. We use MessageFilters for this since that allows us to send our +// messages on the IO thread. +class ExtensionMessageService { + public: + static ExtensionMessageService* GetInstance(); + + ExtensionMessageService(); + + // Registers an extension so that it can be referenced by its ID. This method + // should only be used by the UI thread. + void RegisterExtensionView(ExtensionView* view); + + // Given an extension's ID, opens a channel between the given renderer "port" + // and that extension. Returns a channel ID to be used for posting messages + // between the processes, or -1 if the extension doesn't exist. + int OpenChannelToExtension(const std::string& extension_id, + ResourceMessageFilter* renderer_port); + + // Sends a message to the extension via the given channel. + void PostMessage(int channel_id, const std::string& message); + + // Called to let us know that a renderer is going away. + void RendererShutdown(ResourceMessageFilter* renderer_port); + private: + class ExtensionFilter; + friend class ExtensionFilter; + + // Called when our ExtensionFilter is ready/going away. + void OnExtensionRegistered(ExtensionFilter* extension); + void OnExtensionUnregistered(ExtensionFilter* extension); + + // A map of extension ID to the extension port to communicate through. + // TODO(mpcomplete): Handle the case where there's multiple ExtensionViews + // in a given extension. + typedef std::map<std::string, ExtensionFilter*> ExtensionMap; + ExtensionMap extensions_; + + // The connection between the renderer and extension. + struct MessageChannel { + ExtensionFilter* extension_port; + ResourceMessageFilter* renderer_port; + }; + + // A map of channel ID to its channel object. + typedef std::map<int, MessageChannel> MessageChannelMap; + MessageChannelMap channels_; + + // For generating unique channel IDs. + int next_channel_id_; +}; + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_MESSAGE_SERVICE_H_ diff --git a/chrome/browser/extensions/extension_view.cc b/chrome/browser/extensions/extension_view.cc index 6cd9c97b..0ceb7e4 100755 --- a/chrome/browser/extensions/extension_view.cc +++ b/chrome/browser/extensions/extension_view.cc @@ -4,10 +4,13 @@ #include "chrome/browser/extensions/extension_view.h" +#include "chrome/browser/extensions/extension.h" +#include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/renderer_host/render_view_host.h" -ExtensionView::ExtensionView(const GURL& url, Profile* profile) : - HWNDHtmlView(url, this, false), profile_(profile) { +ExtensionView::ExtensionView( + Extension* extension, const GURL& url, Profile* profile) : + HWNDHtmlView(url, this, false), extension_(extension), profile_(profile) { // TODO(mpcomplete): query this from the renderer somehow? set_preferred_size(gfx::Size(100, 100)); } @@ -16,6 +19,10 @@ void ExtensionView::CreatingRenderer() { render_view_host()->AllowExtensionBindings(); } +void ExtensionView::RenderViewCreated(RenderViewHost* render_view_host) { + ExtensionMessageService::GetInstance()->RegisterExtensionView(this); +} + WebPreferences ExtensionView::GetWebkitPrefs() { // TODO(mpcomplete): return some reasonable prefs. return WebPreferences(); diff --git a/chrome/browser/extensions/extension_view.h b/chrome/browser/extensions/extension_view.h index 6bb9e7a5..3ae3c23 100755 --- a/chrome/browser/extensions/extension_view.h +++ b/chrome/browser/extensions/extension_view.h @@ -14,6 +14,7 @@ #include "chrome/common/temp_scaffolding_stubs.h" #endif +class Extension; class Profile; struct WebPreferences; @@ -24,13 +25,14 @@ struct WebPreferences; class ExtensionView : public HWNDHtmlView, public RenderViewHostDelegate { public: - ExtensionView(const GURL& url, Profile* profile); + ExtensionView(Extension* extension, const GURL& url, Profile* profile); // HWNDHtmlView virtual void CreatingRenderer(); // RenderViewHostDelegate virtual Profile* GetProfile() const { return profile_; } + virtual void RenderViewCreated(RenderViewHost* render_view_host); virtual WebPreferences GetWebkitPrefs(); virtual void RunJavaScriptMessage( const std::wstring& message, @@ -40,7 +42,12 @@ class ExtensionView : public HWNDHtmlView, IPC::Message* reply_msg, bool* did_suppress_message); + Extension* extension() { return extension_; } private: + // The extension that we're hosting in this view. + Extension* extension_; + + // The profile that owns this extension. Profile* profile_; DISALLOW_COPY_AND_ASSIGN(ExtensionView); diff --git a/chrome/browser/extensions/extension_view_unittest.cc b/chrome/browser/extensions/extension_view_unittest.cc index c23cdf7..bc17d4c 100755 --- a/chrome/browser/extensions/extension_view_unittest.cc +++ b/chrome/browser/extensions/extension_view_unittest.cc @@ -30,8 +30,8 @@ const char* kExtensionId = "00123456789abcdef0123456789abcdef0123456"; // up a javascript alert. class MockExtensionView : public ExtensionView { public: - MockExtensionView(const GURL& url, Profile* profile) - : ExtensionView(url, profile), got_message_(false) { + MockExtensionView(Extension* extension, const GURL& url, Profile* profile) + : ExtensionView(extension, url, profile), got_message_(false) { InitHidden(); MessageLoop::current()->PostDelayedTask(FROM_HERE, new MessageLoop::QuitTask, kAlertTimeoutMs); @@ -136,6 +136,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionViewTest, Index) { GURL url = Extension::GetResourceURL(extension->url(), "toolstrip1.html"); // Start the extension process and wait for it to show a javascript alert. - MockExtensionView view(url, profile); + MockExtensionView view(extension, url, profile); EXPECT_TRUE(view.got_message()); } diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index 377bfc7..6d1e68b 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -11,6 +11,7 @@ #include "base/thread.h" #include "chrome/browser/chrome_plugin_browsing_context.h" #include "chrome/browser/chrome_thread.h" +#include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/net/dns_global.h" #include "chrome/browser/plugin_service.h" #include "chrome/browser/profile.h" @@ -126,6 +127,7 @@ ResourceMessageFilter::ResourceMessageFilter( ResourceMessageFilter::~ResourceMessageFilter() { WorkerService::GetInstance()->RendererShutdown(this); + ExtensionMessageService::GetInstance()->RendererShutdown(this); if (handle()) base::CloseProcessHandle(handle()); @@ -256,6 +258,10 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewHostMsg_FreeTransportDIB, OnFreeTransportDIB) #endif + IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToExtension, + OnOpenChannelToExtension) + IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionPostMessage, + OnExtensionPostMessage) IPC_MESSAGE_UNHANDLED( handled = false) IPC_END_MESSAGE_MAP_EX() @@ -786,3 +792,14 @@ void ResourceMessageFilter::OnFreeTransportDIB( render_widget_helper_->FreeTransportDIB(dib_id); } #endif + +void ResourceMessageFilter::OnOpenChannelToExtension( + const std::string& extension_id, int* channel_id) { + *channel_id = ExtensionMessageService::GetInstance()-> + OpenChannelToExtension(extension_id, this); +} + +void ResourceMessageFilter::OnExtensionPostMessage( + int channel_id, const std::string& message) { + ExtensionMessageService::GetInstance()->PostMessage(channel_id, message); +} diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h index 29ae829..94b1e6e 100644 --- a/chrome/browser/renderer_host/resource_message_filter.h +++ b/chrome/browser/renderer_host/resource_message_filter.h @@ -209,6 +209,10 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, TransportDIB::Handle* result); void OnFreeTransportDIB(TransportDIB::Id dib_id); + void OnOpenChannelToExtension(const std::string& extension_id, + int* channel_id); + void OnExtensionPostMessage(int channel_id, const std::string& message); + // We have our own clipboard service because we want to access the clipboard // on the IO thread instead of forwarding (possibly synchronous) messages to // the UI thread. diff --git a/chrome/browser/views/bookmark_bar_view.cc b/chrome/browser/views/bookmark_bar_view.cc index ae6a0de..8542ab9 100644 --- a/chrome/browser/views/bookmark_bar_view.cc +++ b/chrome/browser/views/bookmark_bar_view.cc @@ -299,8 +299,8 @@ class ExtensionToolstrip : public views::View { public: static const int kPadding = 2; - ExtensionToolstrip(const GURL& url, Profile* profile) - : view_(new ExtensionView(url, profile)) { + ExtensionToolstrip(Extension* extension, const GURL& url, Profile* profile) + : view_(new ExtensionView(extension, url, profile)) { AddChildView(view_); set_border(views::Border::CreateEmptyBorder( kPadding, kPadding, kPadding, kPadding)); @@ -1372,8 +1372,9 @@ bool BookmarkBarView::AddExtensionToolstrips(const ExtensionList* extensions) { for (std::vector<std::string>::const_iterator toolstrip = (*extension)->toolstrips().begin(); toolstrip != (*extension)->toolstrips().end(); ++toolstrip) { - ExtensionToolstrip* view = - new ExtensionToolstrip((*extension)->GetResourceURL(*toolstrip), + ExtensionToolstrip* view = + new ExtensionToolstrip(*extension, + (*extension)->GetResourceURL(*toolstrip), profile_); int index = GetBookmarkButtonCount() + num_extension_toolstrips_; AddChildView(index, view); diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 372622d..0475f20 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -614,6 +614,8 @@ 'browser/extensions/extension.h', 'browser/extensions/extension_error_reporter.cc', 'browser/extensions/extension_error_reporter.h', + 'browser/extensions/extension_message_service.cc', + 'browser/extensions/extension_message_service.h', 'browser/extensions/extension_protocols.cc', 'browser/extensions/extension_protocols.h', 'browser/extensions/extension_view.cc', @@ -1355,8 +1357,8 @@ # All .cc, .h, and .mm files under renderer except tests and mocks. 'renderer/automation/dom_automation_controller.cc', 'renderer/automation/dom_automation_controller.h', - 'renderer/extensions/extension_bindings.cc', - 'renderer/extensions/extension_bindings.h', + 'renderer/extensions/renderer_extension_bindings.cc', + 'renderer/extensions/renderer_extension_bindings.h', 'renderer/media/audio_renderer_impl.cc', 'renderer/media/audio_renderer_impl.h', 'renderer/media/data_source_impl.cc', diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index bd13315..d9206d1 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -511,6 +511,12 @@ IPC_BEGIN_MESSAGES(View) // Notification that a move or resize renderer's containing window has // started. IPC_MESSAGE_ROUTED0(ViewMsg_MoveOrResizeStarted) + + // Send a message to an extension process. channel_id is a handle that can + // be used for sending a response. + IPC_MESSAGE_ROUTED2(ViewMsg_HandleExtensionMessage, + std::string /* message */, + int /* channel_id */) IPC_END_MESSAGES(View) @@ -1231,4 +1237,17 @@ IPC_BEGIN_MESSAGES(ViewHost) // Notification when new feeds have been discovered on the page. IPC_MESSAGE_ROUTED1(ViewHostMsg_UpdateFeedList, ViewHostMsg_UpdateFeedList_Params) + + // Get a handle to a currently-running extension process for the extension + // with the given ID. If no such extension is found, -1 is returned. The + // handle can be used for sending messages to the extension. + IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_OpenChannelToExtension, + std::string /* extension_id */, + int /* channel_id */) + + // Send a message to an extension process. The handle is the value returned + // by ViewHostMsg_OpenChannelToExtension. + IPC_MESSAGE_CONTROL2(ViewHostMsg_ExtensionPostMessage, + int /* channel_id */, + std::string /* message */) IPC_END_MESSAGES(ViewHost) diff --git a/chrome/renderer/extensions/extension_bindings.cc b/chrome/renderer/extensions/extension_bindings.cc deleted file mode 100755 index 24c66d3..0000000 --- a/chrome/renderer/extensions/extension_bindings.cc +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/renderer/extensions/extension_bindings.h" - -#include "base/values.h" -#include "chrome/common/render_messages.h" - -#define BIND_METHOD(name) BindMethod(#name, &ExtensionBindings::name) -ExtensionBindings::ExtensionBindings() { - BIND_METHOD(getTestString); -} -#undef BIND_METHOD - -void ExtensionBindings::getTestString( - const CppArgumentList& args, CppVariant* result) { - result->Set("This is a placeholder string. It's here to hold places."); -} diff --git a/chrome/renderer/extensions/extension_bindings.h b/chrome/renderer/extensions/extension_bindings.h deleted file mode 100755 index a4b86cc..0000000 --- a/chrome/renderer/extensions/extension_bindings.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2006-2008 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_RENDERER_EXTENSIONS_EXTENSION_BINDINGS_H__ -#define CHROME_RENDERER_EXTENSIONS_EXTENSION_BINDINGS_H__ - -#include "chrome/common/ipc_message.h" -#include "chrome/renderer/dom_ui_bindings.h" - -// ExtensionBindings is the class backing the "extension" object -// accessible from JavaScript. -class ExtensionBindings : public DOMBoundBrowserObject { - public: - ExtensionBindings(); - virtual ~ExtensionBindings() {} - - // Methods exposed to JavaScript. - void getTestString(const CppArgumentList& args, CppVariant* result); - - private: - DISALLOW_COPY_AND_ASSIGN(ExtensionBindings); -}; - -#endif // CHROME_RENDERER_EXTENSIONS_EXTENSION_BINDINGS_H__ diff --git a/chrome/renderer/extensions/renderer_extension_bindings.cc b/chrome/renderer/extensions/renderer_extension_bindings.cc new file mode 100755 index 0000000..4a095ac --- /dev/null +++ b/chrome/renderer/extensions/renderer_extension_bindings.cc @@ -0,0 +1,100 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/renderer/extensions/renderer_extension_bindings.h" + +#include "chrome/common/render_messages.h" +#include "chrome/renderer/render_thread.h" +#include "webkit/glue/webframe.h" + +namespace { + +const char* kExtensionName = "v8/RendererExtensionBindings"; + +const char* kExtensionScript = + "var chromium = chromium || {};" + "(function () {" + " native function OpenChannelToExtension(id);" + " native function PostMessage(channel_id, msg);" + " chromium.Extension = function(id) {" + " this.channel_id_ = OpenChannelToExtension(id);" + " if (this.channel_id_ == -1)" + " throw new Error('No such extension \"' + id + '\"');" + " chromium.Extension.extensions_[this.channel_id_] = this;" + " };" + " chromium.Extension.extensions_ = {};" + " chromium.Extension.dispatchOnMessage = function(msg, channel_id) {" + // TODO(mpcomplete): port param for onMessage + " var e = chromium.Extension.extensions_[channel_id];" + " if (e && e.onMessage) e.onMessage(msg);" + " if (chromium.Extension.onMessage) chromium.Extension.onMessage(msg);" + " };" + " chromium.Extension.prototype.postMessage = function(msg) {" + " return PostMessage(this.channel_id_, msg);" + " };" + "})();"; + +// Message passing API example (in a content script): +// var extension = +// new chromium.Extension('00123456789abcdef0123456789abcdef0123456'); +// extension.postMessage('Can you hear me now?'); +// extension.onMessage = function(msg) { alert('response=' + msg); } + +class ExtensionImpl : public v8::Extension { + public: + ExtensionImpl() : v8::Extension(kExtensionName, kExtensionScript) {} + ~ExtensionImpl() {} + + virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( + v8::Handle<v8::String> name) { + if (name->Equals(v8::String::New("OpenChannelToExtension"))) { + return v8::FunctionTemplate::New(OpenChannelToExtension); + } else if (name->Equals(v8::String::New("PostMessage"))) { + return v8::FunctionTemplate::New(PostMessage); + } + return v8::Handle<v8::FunctionTemplate>(); + } + static v8::Handle<v8::Value> OpenChannelToExtension( + const v8::Arguments& args) { + if (args.Length() >= 1 && args[0]->IsString()) { + std::string id = *v8::String::Utf8Value(args[0]->ToString()); + int channel_id; + RenderThread::current()->Send( + new ViewHostMsg_OpenChannelToExtension(id, &channel_id)); + return v8::Integer::New(channel_id); + // TODO(mpcomplete): should we associate channel_id with the frame it + // came from, so we can run the onmessage handler in that context for + // responses? + } + return v8::Undefined(); + } + static v8::Handle<v8::Value> PostMessage(const v8::Arguments& args) { + if (args.Length() >= 2 && args[0]->IsInt32() && args[1]->IsString()) { + int channel_id = args[1]->Int32Value(); + std::string message = *v8::String::Utf8Value(args[1]->ToString()); + RenderThread::current()->Send( + new ViewHostMsg_ExtensionPostMessage(channel_id, message)); + } + return v8::Undefined(); + } +}; + +} // namespace + +namespace extensions_v8 { + +v8::Extension* RendererExtensionBindings::Get() { + return new ExtensionImpl(); +} + +void RendererExtensionBindings::HandleExtensionMessage( + WebFrame* webframe, const std::string& message, int channel_id) { + // TODO(mpcomplete): escape message + std::string script = StringPrintf( + "void(chromium.Extension.dispatchOnMessage(\"%s\", %d))", + message.c_str(), channel_id); + webframe->ExecuteScript(webkit_glue::WebScriptSource(script)); +} + +} // namespace extensions_v8 diff --git a/chrome/renderer/extensions/renderer_extension_bindings.h b/chrome/renderer/extensions/renderer_extension_bindings.h new file mode 100755 index 0000000..284f9bb --- /dev/null +++ b/chrome/renderer/extensions/renderer_extension_bindings.h @@ -0,0 +1,26 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_RENDERER_EXTENSIONS_RENDERER_EXTENSION_BINDINGS_H_ +#define CHROME_RENDERER_EXTENSIONS_RENDERER_EXTENSION_BINDINGS_H_ + +#include "v8/include/v8.h" + +#include <string> + +class WebFrame; + +namespace extensions_v8 { + +// This class adds extension-related javascript bindings to a renderer. +class RendererExtensionBindings { + public: + static v8::Extension* Get(); + static void HandleExtensionMessage( + WebFrame* webframe, const std::string& message, int channel_id); +}; + +} // namespace extensions_v8 + +#endif // CHROME_RENDERER_EXTENSIONS_RENDERER_EXTENSION_BINDINGS_H_ diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index fb00145..96e239c 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -23,6 +23,7 @@ #include "chrome/plugin/plugin_channel_base.h" #include "webkit/glue/weburlrequest.h" #endif +#include "chrome/renderer/extensions/renderer_extension_bindings.h" #include "chrome/renderer/net/render_dns_master.h" #include "chrome/renderer/render_process.h" #include "chrome/renderer/render_view.h" @@ -32,7 +33,6 @@ #include "third_party/WebKit/WebKit/chromium/public/WebCache.h" #include "third_party/WebKit/WebKit/chromium/public/WebKit.h" #include "third_party/WebKit/WebKit/chromium/public/WebString.h" -#include "v8/include/v8.h" #include "webkit/extensions/v8/gears_extension.h" #include "webkit/extensions/v8/interval_extension.h" #include "webkit/extensions/v8/playback_extension.h" @@ -248,6 +248,7 @@ void RenderThread::EnsureWebKitInitialized() { WebKit::registerExtension(extensions_v8::GearsExtension::Get()); WebKit::registerExtension(extensions_v8::IntervalExtension::Get()); + WebKit::registerExtension(extensions_v8::RendererExtensionBindings::Get()); const CommandLine& command_line = *CommandLine::ForCurrentProcess(); if (command_line.HasSwitch(switches::kPlaybackMode) || diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 4094ce6..dafb0ad 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -29,6 +29,7 @@ #include "chrome/renderer/debug_message_handler.h" #include "chrome/renderer/devtools_agent.h" #include "chrome/renderer/devtools_client.h" +#include "chrome/renderer/extensions/renderer_extension_bindings.h" #include "chrome/renderer/localized_error.h" #include "chrome/renderer/media/audio_renderer_impl.h" #include "chrome/renderer/render_process.h" @@ -425,6 +426,8 @@ void RenderView::OnMessageReceived(const IPC::Message& message) { OnAudioStreamStateChanged) IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamVolume, OnAudioStreamVolume) IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted) + IPC_MESSAGE_HANDLER(ViewMsg_HandleExtensionMessage, + OnHandleExtensionMessage) // Have the super handle all other messages. IPC_MESSAGE_UNHANDLED(RenderWidget::OnMessageReceived(message)) @@ -1482,11 +1485,6 @@ void RenderView::WindowObjectCleared(WebFrame* webframe) { external_host_bindings_.set_routing_id(routing_id_); external_host_bindings_.BindToJavascript(webframe, L"externalHost"); } - if (BindingsPolicy::is_extension_enabled(enabled_bindings_)) { - extension_bindings_.set_message_sender(this); - extension_bindings_.set_routing_id(routing_id_); - extension_bindings_.BindToJavascript(webframe, L"extension"); - } #ifdef CHROME_PERSONALIZATION Personalization::ConfigureRendererPersonalization(personalization_, this, @@ -2939,3 +2937,10 @@ void RenderView::OnResize(const gfx::Size& new_size, webview()->HideAutofillPopup(); RenderWidget::OnResize(new_size, resizer_rect); } + +void RenderView::OnHandleExtensionMessage(const std::string& message, + int channel_id) { + if (webview() && webview()->GetMainFrame()) + extensions_v8::RendererExtensionBindings::HandleExtensionMessage( + webview()->GetMainFrame(), message, channel_id); +} diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index b6d48a0..da75f93 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -22,7 +22,6 @@ #include "chrome/renderer/automation/dom_automation_controller.h" #include "chrome/renderer/dom_ui_bindings.h" #include "chrome/renderer/external_host_bindings.h" -#include "chrome/renderer/extensions/extension_bindings.h" #include "chrome/renderer/external_js_object.h" #include "chrome/renderer/render_widget.h" #include "media/audio/audio_output.h" @@ -577,6 +576,8 @@ class RenderView : public RenderWidget, // Notification of volume property of an audio output stream. void OnAudioStreamVolume(int stream_id, double left, double right); + void OnHandleExtensionMessage(const std::string& message, int channel_id); + // Prints the page listed in |params|. void PrintPage(const ViewMsg_PrintPage_Params& params, const gfx::Size& canvas_size, @@ -641,9 +642,6 @@ class RenderView : public RenderWidget, // External host exposed through automation controller. ExternalHostBindings external_host_bindings_; - // Extension bindings exposed for script running in the extension process. - ExtensionBindings extension_bindings_; - // The last gotten main frame's encoding. std::wstring last_encoding_name_; diff --git a/chrome/renderer/renderer.scons b/chrome/renderer/renderer.scons index 546db30..9cfa1585 100644 --- a/chrome/renderer/renderer.scons +++ b/chrome/renderer/renderer.scons @@ -58,8 +58,8 @@ input_files = ChromeFileList([ 'net/render_dns_queue.h', ]), MSVSFilter('extensions', [ - 'extensions/extension_bindings.cc', - 'extensions/extension_bindings.h', + 'extensions/renderer_extension_bindings.cc', + 'extensions/renderer_extension_bindings.h', ]), 'about_handler.cc', 'about_handler.h', diff --git a/chrome/renderer/renderer.vcproj b/chrome/renderer/renderer.vcproj index 634c044..db4ec9c 100644 --- a/chrome/renderer/renderer.vcproj +++ b/chrome/renderer/renderer.vcproj @@ -185,11 +185,11 @@ Name="extensions" > <File - RelativePath=".\extensions\extension_bindings.cc" + RelativePath=".\extensions\renderer_extension_bindings.cc" > </File> <File - RelativePath=".\extensions\extension_bindings.h" + RelativePath=".\extensions\renderer_extension_bindings.h" > </File> </Filter> diff --git a/chrome/test/data/extensions/good/extension1/1/toolstrip1.html b/chrome/test/data/extensions/good/extension1/1/toolstrip1.html index 0171859..b4fe99b 100644 --- a/chrome/test/data/extensions/good/extension1/1/toolstrip1.html +++ b/chrome/test/data/extensions/good/extension1/1/toolstrip1.html @@ -14,7 +14,10 @@ body { <body> <div class="content"> <script> - alert(window.extension.getTestString()); + alert('Sir, I exist'); + chromium.Extension.onMessage = function(msg) { + alert('Incoming: ' + msg); + } </script> <button onclick="alert('clicked')">HTML button</button> </div> |