summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/browser.scons2
-rw-r--r--chrome/browser/browser.vcproj8
-rwxr-xr-xchrome/browser/extensions/extension_message_service.cc133
-rwxr-xr-xchrome/browser/extensions/extension_message_service.h73
-rwxr-xr-xchrome/browser/extensions/extension_view.cc11
-rwxr-xr-xchrome/browser/extensions/extension_view.h9
-rwxr-xr-xchrome/browser/extensions/extension_view_unittest.cc6
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc17
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h4
-rw-r--r--chrome/browser/views/bookmark_bar_view.cc9
-rw-r--r--chrome/chrome.gyp6
-rw-r--r--chrome/common/render_messages_internal.h19
-rwxr-xr-xchrome/renderer/extensions/extension_bindings.cc19
-rwxr-xr-xchrome/renderer/extensions/extension_bindings.h25
-rwxr-xr-xchrome/renderer/extensions/renderer_extension_bindings.cc100
-rwxr-xr-xchrome/renderer/extensions/renderer_extension_bindings.h26
-rw-r--r--chrome/renderer/render_thread.cc3
-rw-r--r--chrome/renderer/render_view.cc15
-rw-r--r--chrome/renderer/render_view.h6
-rw-r--r--chrome/renderer/renderer.scons4
-rw-r--r--chrome/renderer/renderer.vcproj4
-rw-r--r--chrome/test/data/extensions/good/extension1/1/toolstrip1.html5
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>