summaryrefslogtreecommitdiffstats
path: root/content/renderer/browser_plugin
diff options
context:
space:
mode:
authorfsamuel@chromium.org <fsamuel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-23 01:49:31 +0000
committerfsamuel@chromium.org <fsamuel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-23 01:49:31 +0000
commit468e49044631580483bd15dd2ff9a548bd886968 (patch)
tree1d760140ddc8779799ef6e981e88e0fe4d9a6339 /content/renderer/browser_plugin
parent28599f4802c403c4d362f734ba37f81b552be977 (diff)
downloadchromium_src-468e49044631580483bd15dd2ff9a548bd886968.zip
chromium_src-468e49044631580483bd15dd2ff9a548bd886968.tar.gz
chromium_src-468e49044631580483bd15dd2ff9a548bd886968.tar.bz2
Renderer-side changes for browser plugin
Major Classes: BrowserPluginChannelManager: Manages GuestToEmbedderChannels. It essentially wraps a map that is keyed on channel names. GuestToEmbedderChannel: Is a Dispatcher. Receives/Sends Ppapi messages. Keeps track of all RenderViews that have an associated PP_Instance in a map (RenderViews that are guests). brettw@ might want to have a look here? BrowserPluginRegistry: Wrapper around map that keeps track of Browser Plugin PluginModules keyed on the guest process id. This is similar to the PepperPluginRegistry but has a different key type. BrowserPluginVarSerializationRules: Temporary do nothing class as suggested by brettw@ BrowserPlugin: Towards becoming a wrapper around a WebPluginContainerImpl that swaps out WebPluginImpl/WebViewPlugin on navigation. We get a blank WebViewPlugin (is this a best thing to do to get a blank placeholder?) if we have an empty src attribute or while we're navigating for the first time. Otherwise, on cross-process navigations, we substitute one WebPluginImpl for another WebPluginImpl. TODO: BrowserPlugin should track the lifetime of WebPluginContainerImpl, but right now it lives forever which is bad. Will fix this in a subsequent patch. This requires some WebKit changes first. BUG=117897 TEST=manually Review URL: https://chromiumcodereview.appspot.com/9968097 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@138416 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/renderer/browser_plugin')
-rw-r--r--content/renderer/browser_plugin/browser_plugin.cc167
-rw-r--r--content/renderer/browser_plugin/browser_plugin.h91
-rw-r--r--content/renderer/browser_plugin/browser_plugin_channel_manager.cc122
-rw-r--r--content/renderer/browser_plugin/browser_plugin_channel_manager.h73
-rw-r--r--content/renderer/browser_plugin/browser_plugin_placeholder.cc143
-rw-r--r--content/renderer/browser_plugin/browser_plugin_placeholder.h89
-rw-r--r--content/renderer/browser_plugin/browser_plugin_registry.cc45
-rw-r--r--content/renderer/browser_plugin/browser_plugin_registry.h37
-rw-r--r--content/renderer/browser_plugin/browser_plugin_var_serialization_rules.cc51
-rw-r--r--content/renderer/browser_plugin/browser_plugin_var_serialization_rules.h35
-rw-r--r--content/renderer/browser_plugin/guest_to_embedder_channel.cc280
-rw-r--r--content/renderer/browser_plugin/guest_to_embedder_channel.h126
12 files changed, 1027 insertions, 232 deletions
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc
new file mode 100644
index 0000000..9f8a9b1
--- /dev/null
+++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -0,0 +1,167 @@
+// Copyright (c) 2012 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 "content/renderer/browser_plugin/browser_plugin.h"
+
+#include "base/atomic_sequence_num.h"
+#include "base/id_map.h"
+#include "base/lazy_instance.h"
+#include "base/process.h"
+#include "base/string_number_conversions.h"
+#include "base/string_piece.h"
+#include "base/string_util.h"
+#include "base/values.h"
+#include "content/common/browser_plugin_messages.h"
+#include "content/public/common/url_constants.h"
+#include "content/renderer/render_view_impl.h"
+#include "ipc/ipc_channel_handle.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPlugin.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/ppapi_webplugin_impl.h"
+#include "webkit/plugins/webview_plugin.h"
+
+static int g_next_id = 0;
+
+// The global list of all Browser Plugin Placeholders within a process.
+base::LazyInstance<IDMap<BrowserPlugin> >::Leaky
+ g_all_browser_plugins = LAZY_INSTANCE_INITIALIZER;
+
+using WebKit::WebPlugin;
+using WebKit::WebPluginContainer;
+using webkit::WebViewPlugin;
+
+void Register(int id, BrowserPlugin* browser_plugin) {
+ g_all_browser_plugins.Get().AddWithID(browser_plugin, id);
+}
+
+void Unregister(int id) {
+ if (g_all_browser_plugins.Get().Lookup(id))
+ g_all_browser_plugins.Get().Remove(id);
+}
+
+// static
+WebKit::WebPlugin* BrowserPlugin::Create(
+ RenderViewImpl* render_view,
+ WebKit::WebFrame* frame,
+ const WebKit::WebPluginParams& params) {
+ // TODO(fsamuel): Figure out what the lifetime is of this class.
+ // It seems we need to blow away this object once a WebPluginContainer is
+ // gone. How do we detect it's gone? A WebKit change perhaps?
+ BrowserPlugin* browser_plugin = new BrowserPlugin(
+ render_view, frame, params, "");
+ return browser_plugin->placeholder();
+}
+
+// static
+BrowserPlugin* BrowserPlugin::FromID(int id) {
+ return g_all_browser_plugins.Get().Lookup(id);
+}
+
+BrowserPlugin::BrowserPlugin(
+ RenderViewImpl* render_view,
+ WebKit::WebFrame* frame,
+ const WebKit::WebPluginParams& params,
+ const std::string& html_data)
+ : render_view_(render_view),
+ plugin_params_(params),
+ placeholder_(webkit::WebViewPlugin::Create(
+ NULL,
+ render_view->GetWebkitPreferences(),
+ html_data,
+ GURL(chrome::kAboutBlankURL))),
+ plugin_(NULL) {
+ id_ = ++g_next_id;
+ Register(id_, this);
+
+ // By default we do not navigate and simply stay with an
+ // about:blank placeholder.
+ gfx::Size size;
+ std::string src;
+ ParsePluginParameters(0, 0, "", &size, &src);
+
+ if (!src.empty()) {
+ render_view->Send(new BrowserPluginHostMsg_NavigateFromEmbedder(
+ render_view->GetRoutingID(),
+ id_,
+ frame->identifier(),
+ src,
+ size));
+ }
+}
+
+BrowserPlugin::~BrowserPlugin() {
+ Unregister(id_);
+}
+
+void BrowserPlugin::ParsePluginParameters(
+ int default_width,
+ int default_height,
+ const std::string& default_src,
+ gfx::Size* size,
+ std::string* src) {
+ int width = default_width;
+ int height = default_height;
+
+ // Get the plugin parameters from the attributes vector
+ for (unsigned i = 0; i < plugin_params_.attributeNames.size(); ++i) {
+ std::string attributeName = plugin_params_.attributeNames[i].utf8();
+ if (LowerCaseEqualsASCII(attributeName, "width")) {
+ std::string attributeValue = plugin_params_.attributeValues[i].utf8();
+ CHECK(base::StringToInt(attributeValue, &width));
+ } else if (LowerCaseEqualsASCII(attributeName, "height")) {
+ std::string attributeValue = plugin_params_.attributeValues[i].utf8();
+ CHECK(base::StringToInt(attributeValue, &height));
+ } else if (LowerCaseEqualsASCII(attributeName, "src")) {
+ *src = plugin_params_.attributeValues[i].utf8();
+ }
+ }
+ // If we didn't find the attributes set or they're not sensible,
+ // we reset our attributes to the default.
+ if (src->empty()) {
+ *src = default_src;
+ }
+
+ size->SetSize(width, height);
+}
+
+void BrowserPlugin::LoadGuest(
+ int guest_process_id,
+ const IPC::ChannelHandle& channel_handle) {
+ webkit::ppapi::WebPluginImpl* new_guest =
+ render_view()->CreateBrowserPlugin(channel_handle,
+ guest_process_id,
+ plugin_params());
+ Replace(new_guest);
+}
+
+void BrowserPlugin::Replace(
+ webkit::ppapi::WebPluginImpl* new_plugin) {
+ WebKit::WebPlugin* current_plugin =
+ plugin_ ? static_cast<WebKit::WebPlugin*>(plugin_) : placeholder_;
+ WebKit::WebPluginContainer* container = current_plugin->container();
+ if (!new_plugin || !new_plugin->initialize(container))
+ return;
+
+ // Clear the container's backing texture ID and the script objects.
+ if (plugin_)
+ plugin_->instance()->BindGraphics(plugin_->instance()->pp_instance(), 0);
+
+ // Inform the browser process of the association between the browser plugin's
+ // instance ID and the pepper channel's PP_Instance identifier.
+ render_view()->Send(new BrowserPluginHostMsg_MapInstance(
+ render_view()->GetRoutingID(),
+ id_,
+ new_plugin->instance()->pp_instance()));
+ // TODO(fsamuel): We should delay the swapping out of the current plugin
+ // until after the guest's WebGraphicsContext3D has been initialized. That
+ // way, we immediately have something to render onto the screen.
+ container->setPlugin(new_plugin);
+ container->invalidate();
+ container->reportGeometry();
+ if (plugin_)
+ plugin_->destroy();
+ plugin_ = new_plugin;
+}
diff --git a/content/renderer/browser_plugin/browser_plugin.h b/content/renderer/browser_plugin/browser_plugin.h
new file mode 100644
index 0000000..206a317
--- /dev/null
+++ b/content/renderer/browser_plugin/browser_plugin.h
@@ -0,0 +1,91 @@
+// Copyright (c) 2012 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 CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_H_
+#define CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_H_
+#pragma once
+
+#include "base/process.h"
+#include "content/renderer/render_view_impl.h"
+#include "ipc/ipc_channel_handle.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginParams.h"
+#include "ui/gfx/size.h"
+#include "webkit/plugins/webview_plugin.h"
+
+namespace content {
+class RenderView;
+}
+
+namespace WebKit {
+class WebPlugin;
+}
+
+// A browser plugin is a plugin container that hosts an out-of-process "guest"
+// RenderView. Loading up a new process, creating a new RenderView, navigating
+// to a given URL, and establishing a guest-to-embedder channel can take
+// hundreds of milliseconds. Furthermore, a RenderView's associated browser-side
+// WebContents, RenderViewHost, and SiteInstance must be created and accessed on
+// the UI thread of the browser process.
+//
+// To avoid blocking the embedder RenderView and to avoid introducing the
+// potential for deadlock, BrowserPlugin attaches a placeholder that takes
+// place of the guest RenderView until the guest has established a connection
+// with its embedder RenderView. This permits asynchronously loading of the
+// guest while the embedder RenderView is permitted to continue to receive and
+// process events.
+//
+// Furthermore, certain navigations can swap to a new guest RenderView on an
+// different process. BrowserPlugin is the consistent facade that the embedder's
+// WebKit instance talks to regardless of which process it's communicating with.
+class BrowserPlugin {
+ public:
+ // Creates a new WebViewPlugin with a BrowserPlugin as a delegate.
+ static WebKit::WebPlugin* Create(
+ RenderViewImpl* render_view,
+ WebKit::WebFrame* frame,
+ const WebKit::WebPluginParams& params);
+
+ static BrowserPlugin* FromID(int id);
+
+ webkit::WebViewPlugin* placeholder() { return placeholder_; }
+
+ webkit::ppapi::WebPluginImpl* plugin() { return plugin_; }
+
+ const WebKit::WebPluginParams& plugin_params() const {
+ return plugin_params_;
+ }
+
+ void LoadGuest(int guest_process_id,
+ const IPC::ChannelHandle& channel_handle);
+
+ RenderViewImpl* render_view() { return render_view_; }
+
+ private:
+ BrowserPlugin(RenderViewImpl* render_view,
+ WebKit::WebFrame* frame,
+ const WebKit::WebPluginParams& params,
+ const std::string& html_data);
+ virtual ~BrowserPlugin();
+
+ // Parses the width, height, and source URL of the browser plugin
+ // from the element's attributes and outputs them. If not found, it outputs
+ // the defaults specified here as parameters.
+ void ParsePluginParameters(int default_width, int default_height,
+ const std::string& default_src,
+ gfx::Size* size,
+ std::string* src);
+ // Replace the current guest with a new guest.
+ void Replace(webkit::ppapi::WebPluginImpl* new_plugin);
+
+ RenderViewImpl* render_view_;
+ WebKit::WebPluginParams plugin_params_;
+ webkit::WebViewPlugin* placeholder_;
+ webkit::ppapi::WebPluginImpl* plugin_;
+ int id_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserPlugin);
+};
+
+#endif // CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_H_
diff --git a/content/renderer/browser_plugin/browser_plugin_channel_manager.cc b/content/renderer/browser_plugin/browser_plugin_channel_manager.cc
new file mode 100644
index 0000000..ec6365c
--- /dev/null
+++ b/content/renderer/browser_plugin/browser_plugin_channel_manager.cc
@@ -0,0 +1,122 @@
+// Copyright (c) 2012 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 "content/renderer/browser_plugin/browser_plugin_channel_manager.h"
+
+#include "base/process_util.h"
+#include "content/common/browser_plugin_messages.h"
+#include "content/common/view_messages.h"
+#include "content/renderer/browser_plugin/browser_plugin.h"
+#include "content/renderer/browser_plugin/guest_to_embedder_channel.h"
+#include "content/renderer/render_thread_impl.h"
+#include "content/renderer/render_view_impl.h"
+#include "ppapi/c/pp_instance.h"
+
+namespace content {
+
+BrowserPluginChannelManager::BrowserPluginChannelManager() {
+}
+
+BrowserPluginChannelManager::~BrowserPluginChannelManager() {
+}
+
+void BrowserPluginChannelManager::CreateRenderView(
+ const ViewMsg_New_Params& params) {
+ IPC::ChannelHandle plugin_handle;
+ plugin_handle.name =
+ IPC::Channel::GenerateVerifiedChannelID(params.embedder_channel_name);
+ bool success = true;
+ scoped_refptr<GuestToEmbedderChannel> channel =
+ GetChannelByName(params.embedder_channel_name);
+ if (!channel) {
+ channel = new GuestToEmbedderChannel(params.embedder_channel_name);
+ success = channel->InitChannel(plugin_handle);
+
+#if defined(OS_POSIX)
+ // On POSIX, transfer ownership of the renderer-side (client) FD.
+ // This ensures this process will be notified when it is closed even if a
+ // connection is not established.
+ plugin_handle.socket =
+ base::FileDescriptor(channel->TakeRendererFD(), true);
+ if (plugin_handle.socket.fd == -1)
+ success = false;
+#endif
+ DCHECK(success);
+ embedder_channels_[params.embedder_channel_name] = channel;
+ }
+ DCHECK(pending_guests_.find(params.view_id) ==
+ pending_guests_.end());
+ pending_guests_[params.view_id] =
+ RenderViewImpl::Create(
+ params.parent_window,
+ params.opener_route_id,
+ params.renderer_preferences,
+ params.web_preferences,
+ new SharedRenderViewCounter(0),
+ params.view_id,
+ params.surface_id,
+ params.session_storage_namespace_id,
+ params.frame_name,
+ false,
+ params.swapped_out,
+ params.next_page_id,
+ params.screen_info,
+ channel,
+ params.accessibility_mode)->AsWeakPtr();
+ RenderThreadImpl::current()->Send(
+ new BrowserPluginHostMsg_ConnectToChannel(params.view_id,
+ success ? plugin_handle : IPC::ChannelHandle()));
+}
+
+bool BrowserPluginChannelManager::OnControlMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(BrowserPluginChannelManager, message)
+ IPC_MESSAGE_HANDLER(BrowserPluginMsg_CompleteNavigation,
+ OnCompleteNavigation)
+ IPC_MESSAGE_HANDLER(BrowserPluginMsg_LoadGuest, OnLoadGuest)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+GuestToEmbedderChannel* BrowserPluginChannelManager::GetChannelByName(
+ const std::string& embedder_channel_name) {
+ EmbedderChannelNameToChannelMap::iterator it =
+ embedder_channels_.find(embedder_channel_name);
+ if (it != embedder_channels_.end())
+ return it->second;
+ return NULL;
+}
+
+void BrowserPluginChannelManager::RemoveChannelByName(
+ const std::string& embedder_channel_name) {
+ embedder_channels_.erase(embedder_channel_name);
+}
+
+void BrowserPluginChannelManager::OnCompleteNavigation(
+ int guest_routing_id,
+ PP_Instance instance) {
+ CHECK(pending_guests_.find(guest_routing_id) !=
+ pending_guests_.end());
+ RenderViewImpl* render_view = pending_guests_[guest_routing_id];
+ pending_guests_.erase(guest_routing_id);
+ GuestToEmbedderChannel* channel = render_view->guest_to_embedder_channel();
+ // Associate the RenderView with the provided PP_Instance ID, request the
+ // receipt of events, and initialize the graphics context.
+ channel->AddGuest(instance, render_view);
+ channel->RequestInputEvents(instance);
+ render_view->GuestReady(instance);
+}
+
+void BrowserPluginChannelManager::OnLoadGuest(
+ int instance_id,
+ int guest_process_id,
+ const IPC::ChannelHandle& channel_handle) {
+ BrowserPlugin* browser_plugin = BrowserPlugin::FromID(instance_id);
+ browser_plugin->LoadGuest(guest_process_id, channel_handle);
+}
+
+} // namespace content
diff --git a/content/renderer/browser_plugin/browser_plugin_channel_manager.h b/content/renderer/browser_plugin/browser_plugin_channel_manager.h
new file mode 100644
index 0000000..ab33f0a
--- /dev/null
+++ b/content/renderer/browser_plugin/browser_plugin_channel_manager.h
@@ -0,0 +1,73 @@
+// Copyright (c) 2012 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 CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_CHANNEL_MANAGER_H_
+#define CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_CHANNEL_MANAGER_H_
+#pragma once
+
+#include <set>
+
+#include "base/id_map.h"
+#include "content/public/renderer/render_process_observer.h"
+#include "content/renderer/browser_plugin/guest_to_embedder_channel.h"
+#include "content/renderer/render_view_impl.h"
+
+class GuestToEmbedderChannel;
+struct ViewMsg_New_Params;
+
+namespace content {
+
+// BrowserPluginChannelManager manages the lifetime of GuestToEmbedderChannels.
+// When a new RenderView is requested, it checks the embedder channel name
+// in ViewMsg_New_Params and decides whether to reuse an existing channel or
+// create a new channel. On the guest renderer process, it informs a
+// RenderView once a channel has been established with its embedder.
+// On the embedder side, it tells BrowserPlugin to load the guest
+// PluginInstance once a channel has been established.
+class BrowserPluginChannelManager
+ : public RenderProcessObserver {
+ public:
+ BrowserPluginChannelManager();
+
+ virtual ~BrowserPluginChannelManager();
+
+ void CreateRenderView(const ViewMsg_New_Params& params);
+
+ // Get the GuestToEmbedderChannel associated with the given
+ // embedder_channel_name.
+ GuestToEmbedderChannel* GetChannelByName(
+ const std::string& embedder_channel_name);
+
+ // Remove the pointer to the GuestToEmbedderChannel associated with the given
+ // routing_id.
+ void RemoveChannelByName(const std::string& embedder_channel_name);
+
+ private:
+ typedef std::map<std::string, scoped_refptr<GuestToEmbedderChannel> >
+ EmbedderChannelNameToChannelMap;
+
+ void OnCompleteNavigation(int guest_routing_id,
+ PP_Instance instance);
+
+ void OnLoadGuest(int instance_id,
+ int guest_renderer_id,
+ const IPC::ChannelHandle& channel_handle);
+
+ // RenderProcessObserver override. Call on render thread.
+ virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ // Map from Host process ID to GuestToEmbedderChannel
+ EmbedderChannelNameToChannelMap embedder_channels_;
+
+ // Map from Routing ID to RenderViewImpl that points to RenderViewImpl
+ // guests that have been constructed but don't have a PP_Instance and
+ // so they aren't yet ready to composite.
+ std::map<int, base::WeakPtr<RenderViewImpl> > pending_guests_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserPluginChannelManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_CHANNEL_MANAGER_H_
diff --git a/content/renderer/browser_plugin/browser_plugin_placeholder.cc b/content/renderer/browser_plugin/browser_plugin_placeholder.cc
deleted file mode 100644
index 21ac8ee..0000000
--- a/content/renderer/browser_plugin/browser_plugin_placeholder.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright (c) 2012 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 "content/renderer/browser_plugin/browser_plugin_placeholder.h"
-
-#include "base/atomic_sequence_num.h"
-#include "base/id_map.h"
-#include "base/lazy_instance.h"
-#include "base/process.h"
-#include "base/string_number_conversions.h"
-#include "base/string_piece.h"
-#include "base/string_util.h"
-#include "base/values.h"
-#include "content/common/view_messages.h"
-#include "content/public/renderer/render_view.h"
-#include "ipc/ipc_channel_handle.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebPlugin.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h"
-#include "webkit/plugins/webview_plugin.h"
-
-static base::StaticAtomicSequenceNumber g_next_id;
-
-// The global list of all Browser Plugin Placeholders within a process.
-base::LazyInstance<IDMap<BrowserPluginPlaceholder> >::Leaky
- g_all_placeholders = LAZY_INSTANCE_INITIALIZER;
-
-using webkit::WebViewPlugin;
-using WebKit::WebPlugin;
-using WebKit::WebPluginContainer;
-
-const char* const kPluginPlaceholderDataURL =
- "about:blank";
-
-// static
-webkit::WebViewPlugin* BrowserPluginPlaceholder::Create(
- content::RenderView* render_view,
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params) {
- // TODO(fsamuel): Need a better loading screen at some point. Maybe this can
- // be a part of the <browser> API?
- // |browser_plugin| will destroy itself when its WebViewPlugin is going away.
- BrowserPluginPlaceholder* browser_plugin = new BrowserPluginPlaceholder(
- render_view, frame, params, "");
- return browser_plugin->plugin();
-}
-
-// static
-BrowserPluginPlaceholder* BrowserPluginPlaceholder::FromID(int id) {
- return g_all_placeholders.Get().Lookup(id);
-}
-
-BrowserPluginPlaceholder::BrowserPluginPlaceholder(
- content::RenderView* render_view,
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params,
- const std::string& html_data)
- : render_view_(render_view),
- plugin_params_(params),
- plugin_(webkit::WebViewPlugin::Create(
- this, render_view->GetWebkitPreferences(), html_data,
- GURL(kPluginPlaceholderDataURL))) {
- id_ = g_next_id.GetNext();
- RegisterPlaceholder(GetID(), this);
-
- // By default we navigate to google.com
- GetPluginParameters(0, 0, "http://www.google.com/");
-
- // TODO(fsamuel): Request a browser plugin instance from the
- // browser process.
-}
-
-BrowserPluginPlaceholder::~BrowserPluginPlaceholder() {
- UnregisterPlaceholder(GetID());
-}
-
-void BrowserPluginPlaceholder::RegisterPlaceholder(
- int id,
- BrowserPluginPlaceholder* placeholder) {
- g_all_placeholders.Get().AddWithID(placeholder, id);
-}
-
-void BrowserPluginPlaceholder::UnregisterPlaceholder(int id) {
- if (g_all_placeholders.Get().Lookup(id))
- g_all_placeholders.Get().Remove(id);
-}
-
-const WebKit::WebPluginParams& BrowserPluginPlaceholder::plugin_params() const {
- return plugin_params_;
-}
-
-void BrowserPluginPlaceholder::GetPluginParameters(
- int default_width, int default_height,
- const std::string& default_src) {
- int width = default_width;
- int height = default_height;
-
- // Get the plugin parameters from the attributes vector
- for (unsigned i = 0; i < plugin_params_.attributeNames.size(); ++i) {
- std::string attributeName = plugin_params_.attributeNames[i].utf8();
- if (LowerCaseEqualsASCII(attributeName, "width")) {
- std::string attributeValue = plugin_params_.attributeValues[i].utf8();
- CHECK(base::StringToInt(attributeValue, &width));
- } else if (LowerCaseEqualsASCII(attributeName, "height")) {
- std::string attributeValue = plugin_params_.attributeValues[i].utf8();
- CHECK(base::StringToInt(attributeValue, &height));
- } else if (LowerCaseEqualsASCII(attributeName, "src")) {
- src_ = plugin_params_.attributeValues[i].utf8();
- }
- }
- // If we didn't find the attributes set or they're not sensible,
- // we reset our attributes to the default.
- if (src_.empty())
- src_ = default_src;
-
- size_.SetSize(width, height);
-}
-
-void BrowserPluginPlaceholder::GuestReady(
- base::ProcessHandle process_handle,
- const IPC::ChannelHandle& channel_handle) {
- // TODO(fsamuel): Once the guest renderer is ready,
- // it will inform the host renderer and the BrowserPluginPlaceholder
- // can swap itself out with the guest.
- NOTIMPLEMENTED();
-}
-
-void BrowserPluginPlaceholder::LoadGuest(WebKit::WebPlugin* new_plugin) {
- WebKit::WebPluginContainer* container = plugin_->container();
- if (!new_plugin || !new_plugin->initialize(container))
- return;
- plugin_->RestoreTitleText();
- container->setPlugin(new_plugin);
- container->invalidate();
- container->reportGeometry();
- plugin_->ReplayReceivedData(new_plugin);
- plugin_->destroy();
-}
-
-void BrowserPluginPlaceholder::WillDestroyPlugin() {
- delete this;
-}
diff --git a/content/renderer/browser_plugin/browser_plugin_placeholder.h b/content/renderer/browser_plugin/browser_plugin_placeholder.h
deleted file mode 100644
index b7c229d..0000000
--- a/content/renderer/browser_plugin/browser_plugin_placeholder.h
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_PLACEHOLDER_H_
-#define CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_PLACEHOLDER_H_
-#pragma once
-
-#include "base/process.h"
-#include "ipc/ipc_channel_handle.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginParams.h"
-#include "ui/gfx/size.h"
-#include "webkit/plugins/webview_plugin.h"
-
-namespace content {
-class RenderView;
-}
-
-namespace WebKit {
-class WebPlugin;
-}
-
-// A browser plugin is a plugin container that hosts an out-of-process "guest"
-// RenderView. Loading up a new process, creating a new RenderView, navigating
-// to a given URL, and establishing a guest-to-host channel can take hundreds
-// of milliseconds. Furthermore, a RenderView's associated browser-side
-// WebContents, RenderViewHost, and SiteInstance must be created and accessed on
-// the UI thread of the browser process.
-//
-// To avoid blocking the host RenderView and to avoid introducing the potential
-// for deadlock, the BrowserPluginPlaceholder takes place of the guest
-// RenderView until the guest has established a connection with its host
-// RenderView. This permits loading the guest to happen asynchronously, while
-// the host RenderView is permitted to continue to receive and process events.
-class BrowserPluginPlaceholder: public webkit::WebViewPlugin::Delegate {
- public:
- // Creates a new WebViewPlugin with a BrowserPluginPlaceholder as a delegate.
- static webkit::WebViewPlugin* Create(
- content::RenderView* render_view,
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params);
-
- static BrowserPluginPlaceholder* FromID(int id);
-
- void RegisterPlaceholder(int id, BrowserPluginPlaceholder* placeholder);
- void UnregisterPlaceholder(int id);
-
- int GetID() { return id_; }
-
- webkit::WebViewPlugin* plugin() { return plugin_; }
-
- const WebKit::WebPluginParams& plugin_params() const;
-
- void GuestReady(base::ProcessHandle process_handle,
- const IPC::ChannelHandle& channel_handle);
-
- content::RenderView* render_view() { return render_view_; }
-
- private:
- BrowserPluginPlaceholder(content::RenderView* render_view,
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params,
- const std::string& html_data);
- virtual ~BrowserPluginPlaceholder();
-
- // Grabs the width, height, and source URL of the browser plugin
- // from the element's attributes. If not found, it uses the defaults
- // specified here as parameters.
- void GetPluginParameters(int default_width, int default_height,
- const std::string& default_src);
- // Replace this placeholder with the real browser plugin.
- void LoadGuest(WebKit::WebPlugin* new_plugin);
-
- virtual void BindWebFrame(WebKit::WebFrame* frame) OVERRIDE { }
- virtual void WillDestroyPlugin() OVERRIDE;
- virtual void ShowContextMenu(const WebKit::WebMouseEvent&) OVERRIDE { }
-
- content::RenderView* render_view_;
- WebKit::WebPluginParams plugin_params_;
- webkit::WebViewPlugin* plugin_;
- int id_;
- gfx::Size size_;
- std::string src_;
-
- DISALLOW_COPY_AND_ASSIGN(BrowserPluginPlaceholder);
-};
-
-#endif // CONTNET_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_PLACEHOLDER_H_
diff --git a/content/renderer/browser_plugin/browser_plugin_registry.cc b/content/renderer/browser_plugin/browser_plugin_registry.cc
new file mode 100644
index 0000000..14725e7
--- /dev/null
+++ b/content/renderer/browser_plugin/browser_plugin_registry.cc
@@ -0,0 +1,45 @@
+// Copyright (c) 2012 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 "content/renderer/browser_plugin/browser_plugin_registry.h"
+
+#include "base/logging.h"
+
+namespace content {
+
+BrowserPluginRegistry::BrowserPluginRegistry() {
+}
+
+BrowserPluginRegistry::~BrowserPluginRegistry() {
+}
+
+webkit::ppapi::PluginModule* BrowserPluginRegistry::GetModule(
+ int guest_process_id) {
+ return modules_.Lookup(guest_process_id);
+}
+
+void BrowserPluginRegistry::AddModule(int guest_process_id,
+ webkit::ppapi::PluginModule* module) {
+ modules_.AddWithID(module, guest_process_id);
+}
+
+void BrowserPluginRegistry::PluginModuleDead(
+ webkit::ppapi::PluginModule* dead_module) {
+ // DANGER: Don't dereference the dead_module pointer! It may be in the
+ // process of being deleted.
+
+ // Modules aren't destroyed very often and there are normally at most a
+ // couple of them. So for now we just do a brute-force search.
+ IDMap<webkit::ppapi::PluginModule>::iterator iter(&modules_);
+ while (!iter.IsAtEnd()) {
+ if (iter.GetCurrentValue() == dead_module) {
+ modules_.Remove(iter.GetCurrentKey());
+ return;
+ }
+ iter.Advance();
+ }
+ NOTREACHED(); // Should have always found the module above.
+}
+
+} // namespace content
diff --git a/content/renderer/browser_plugin/browser_plugin_registry.h b/content/renderer/browser_plugin/browser_plugin_registry.h
new file mode 100644
index 0000000..7740015
--- /dev/null
+++ b/content/renderer/browser_plugin/browser_plugin_registry.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2012 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 CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_REGISTRY_H_
+#define CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_REGISTRY_H_
+#pragma once
+
+#include "base/id_map.h"
+#include "base/process.h"
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+
+namespace content {
+
+// This class holds references to all of the known live browser plugin
+// modules. There is one browser plugin module per guest renderer process.
+class BrowserPluginRegistry
+ : public webkit::ppapi::PluginDelegate::ModuleLifetime {
+ public:
+ BrowserPluginRegistry();
+ virtual ~BrowserPluginRegistry();
+
+ webkit::ppapi::PluginModule* GetModule(int guest_process_id);
+ void AddModule(int guest_process_id,
+ webkit::ppapi::PluginModule* module);
+
+ // ModuleLifetime implementation.
+ virtual void PluginModuleDead(
+ webkit::ppapi::PluginModule* dead_module) OVERRIDE;
+
+ private:
+ IDMap<webkit::ppapi::PluginModule> modules_;
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_REGISTRY_H_
diff --git a/content/renderer/browser_plugin/browser_plugin_var_serialization_rules.cc b/content/renderer/browser_plugin/browser_plugin_var_serialization_rules.cc
new file mode 100644
index 0000000..874527c
--- /dev/null
+++ b/content/renderer/browser_plugin/browser_plugin_var_serialization_rules.cc
@@ -0,0 +1,51 @@
+// Copyright (c) 2012 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 "content/renderer/browser_plugin/browser_plugin_var_serialization_rules.h"
+
+#include "base/logging.h"
+
+namespace content {
+
+BrowserPluginVarSerializationRules::BrowserPluginVarSerializationRules() {
+}
+
+BrowserPluginVarSerializationRules::~BrowserPluginVarSerializationRules() {
+}
+
+PP_Var BrowserPluginVarSerializationRules::SendCallerOwned(const PP_Var& var) {
+ DCHECK(var.type != PP_VARTYPE_OBJECT);
+ return var;
+}
+
+PP_Var BrowserPluginVarSerializationRules::BeginReceiveCallerOwned(
+ const PP_Var& var) {
+ DCHECK(var.type != PP_VARTYPE_OBJECT);
+ return var;
+}
+
+void BrowserPluginVarSerializationRules::EndReceiveCallerOwned(
+ const PP_Var& var) {
+ DCHECK(var.type != PP_VARTYPE_OBJECT);
+}
+
+PP_Var BrowserPluginVarSerializationRules::ReceivePassRef(const PP_Var& var) {
+ DCHECK(var.type != PP_VARTYPE_OBJECT);
+ return var;
+}
+
+PP_Var BrowserPluginVarSerializationRules::BeginSendPassRef(const PP_Var& var) {
+ DCHECK(var.type != PP_VARTYPE_OBJECT);
+ return var;
+}
+
+void BrowserPluginVarSerializationRules::EndSendPassRef(const PP_Var& var) {
+ DCHECK(var.type != PP_VARTYPE_OBJECT);
+}
+
+void BrowserPluginVarSerializationRules::ReleaseObjectRef(const PP_Var& var) {
+ DCHECK(var.type != PP_VARTYPE_OBJECT);
+}
+
+} // namespace content
diff --git a/content/renderer/browser_plugin/browser_plugin_var_serialization_rules.h b/content/renderer/browser_plugin/browser_plugin_var_serialization_rules.h
new file mode 100644
index 0000000..f169912
--- /dev/null
+++ b/content/renderer/browser_plugin/browser_plugin_var_serialization_rules.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2012 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 CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_VAR_SERIALIZATION_RULES_H_
+#define CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_VAR_SERIALIZATION_RULES_H_
+
+#include "ppapi/proxy/var_serialization_rules.h"
+
+namespace content {
+
+// Implementation of the VarSerializationRules interface for the browser plugin.
+class BrowserPluginVarSerializationRules :
+ public ppapi::proxy::VarSerializationRules {
+ public:
+ explicit BrowserPluginVarSerializationRules();
+
+ // VarSerialization implementation.
+ virtual PP_Var SendCallerOwned(const PP_Var& var) OVERRIDE;
+ virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var) OVERRIDE;
+ virtual void EndReceiveCallerOwned(const PP_Var& var) OVERRIDE;
+ virtual PP_Var ReceivePassRef(const PP_Var& var) OVERRIDE;
+ virtual PP_Var BeginSendPassRef(const PP_Var& var) OVERRIDE;
+ virtual void EndSendPassRef(const PP_Var& var) OVERRIDE;
+ virtual void ReleaseObjectRef(const PP_Var& var) OVERRIDE;
+
+ private:
+ virtual ~BrowserPluginVarSerializationRules();
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserPluginVarSerializationRules);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_VAR_SERIALIZATION_RULES_H_
diff --git a/content/renderer/browser_plugin/guest_to_embedder_channel.cc b/content/renderer/browser_plugin/guest_to_embedder_channel.cc
new file mode 100644
index 0000000..1f9f6a7
--- /dev/null
+++ b/content/renderer/browser_plugin/guest_to_embedder_channel.cc
@@ -0,0 +1,280 @@
+// Copyright (c) 2012 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 "content/renderer/browser_plugin/guest_to_embedder_channel.h"
+
+#include "base/process_util.h"
+#include "content/common/browser_plugin_messages.h"
+#include "content/common/child_process.h"
+#include "content/renderer/browser_plugin/browser_plugin_channel_manager.h"
+#include "content/renderer/browser_plugin/browser_plugin_var_serialization_rules.h"
+#include "content/renderer/render_thread_impl.h"
+#include "content/renderer/render_view_impl.h"
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_graphics_3d.h"
+#include "ppapi/proxy/ppapi_command_buffer_proxy.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/api_id.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/var.h"
+#include "webkit/plugins/ppapi/event_conversion.h"
+
+namespace content {
+
+GuestToEmbedderChannel::GuestToEmbedderChannel(
+ const std::string& embedder_channel_name)
+ : Dispatcher(NULL),
+ embedder_channel_name_(embedder_channel_name) {
+ SetSerializationRules(new BrowserPluginVarSerializationRules());
+}
+
+GuestToEmbedderChannel::~GuestToEmbedderChannel() {
+}
+
+bool GuestToEmbedderChannel::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(GuestToEmbedderChannel, message)
+ IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnSupportsInterface)
+ IPC_MESSAGE_HANDLER(PpapiMsg_SetPreferences, OnSetPreferences)
+ IPC_MESSAGE_HANDLER(PpapiMsg_ReserveInstanceId, OnReserveInstanceId)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidCreate,
+ OnDidCreate)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidDestroy,
+ OnDidDestroy)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeView,
+ OnDidChangeView)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeFocus,
+ OnDidChangeFocus)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPMessaging_HandleMessage,
+ OnHandleMessage)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInputEvent_HandleFilteredInputEvent,
+ OnHandleFilteredInputEvent)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPGraphics3D_ContextLost,
+ OnContextLost)
+ // Have the super handle all other messages.
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+bool GuestToEmbedderChannel::Send(IPC::Message* message) {
+ // We always want guest->host messages to arrive in-order. If some sync
+ // and some async messages are sent in response to a synchronous
+ // host->guest call, the sync reply will be processed before the async
+ // reply, and everything will be confused.
+ //
+ // Allowing all async messages to unblock the renderer means more reentrancy
+ // there but gives correct ordering.
+ message->set_unblock(true);
+ return ProxyChannel::Send(message);
+}
+
+void GuestToEmbedderChannel::OnChannelError() {
+ // We cannot destroy the GuestToEmbedderChannel here because a
+ // PpapiCommandBufferProxy may still refer to this object.
+ // However, we should not be using this channel again once we get a
+ // channel error so we remove it from the channel manager.
+ RenderThreadImpl::current()->browser_plugin_channel_manager()->
+ RemoveChannelByName(embedder_channel_name_);
+}
+
+bool GuestToEmbedderChannel::IsPlugin() const {
+ return true;
+}
+
+WebGraphicsContext3DCommandBufferImpl*
+ GuestToEmbedderChannel::CreateWebGraphicsContext3D(
+ RenderViewImpl* render_view,
+ const WebKit::WebGraphicsContext3D::Attributes& attributes,
+ bool offscreen) {
+ scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
+ new WebGraphicsContext3DCommandBufferImpl(
+ 0, GURL(), NULL,
+ render_view->AsWeakPtr()));
+
+ // Special case: RenderView initialization has not yet completed.
+ if (!render_view->guest_pp_instance())
+ return context.release();
+
+ if (CreateGraphicsContext(context.get(),
+ attributes,
+ offscreen,
+ render_view))
+ return context.release();
+
+ return NULL;
+}
+
+void GuestToEmbedderChannel::IssueSwapBuffers(
+ const ppapi::HostResource& resource) {
+ Send(new PpapiHostMsg_PPBGraphics3D_SwapBuffers(
+ ppapi::API_ID_PPB_GRAPHICS_3D, resource));
+}
+
+bool GuestToEmbedderChannel::InitChannel(
+ const IPC::ChannelHandle& channel_handle) {
+ return ProxyChannel::InitWithChannel(&delegate_, channel_handle, false);
+}
+
+void GuestToEmbedderChannel::OnSupportsInterface(
+ const std::string& interface_name,
+ bool* result) {
+ // TODO(fsamuel): This is a hack to avoid getting GetInstanceObject messages
+ // and failing a CHECK. A more correct solution is to implement
+ // VarSerializationRules for GuestToEmbedderChannel.
+ *result = interface_name.find("PPP_Instance_Private") == std::string::npos;
+}
+
+void GuestToEmbedderChannel::OnSetPreferences(const ppapi::Preferences& prefs) {
+ // TODO(fsamuel): Do we care about these preferences?
+ // These look like some font stuff from WebPreferences.
+ // Perhaps this should be plumbed into our associated RenderView?
+ NOTIMPLEMENTED();
+}
+
+void GuestToEmbedderChannel::OnReserveInstanceId(PP_Instance instance,
+ bool* usable) {
+ *usable =
+ render_view_instances_.find(instance) == render_view_instances_.end();
+}
+
+void GuestToEmbedderChannel::RequestInputEvents(PP_Instance instance) {
+ // Request receipt of input events
+ Send(new PpapiHostMsg_PPBInstance_RequestInputEvents(
+ ppapi::API_ID_PPB_INSTANCE, instance, true,
+ PP_INPUTEVENT_CLASS_MOUSE |
+ PP_INPUTEVENT_CLASS_KEYBOARD |
+ PP_INPUTEVENT_CLASS_WHEEL |
+ PP_INPUTEVENT_CLASS_TOUCH));
+}
+
+bool GuestToEmbedderChannel::CreateGraphicsContext(
+ WebGraphicsContext3DCommandBufferImpl* context,
+ const WebKit::WebGraphicsContext3D::Attributes& attributes,
+ bool offscreen,
+ RenderViewImpl* render_view) {
+ std::vector<int32_t> attribs;
+ attribs.push_back(PP_GRAPHICS3DATTRIB_NONE);
+
+ ppapi::HostResource resource;
+ DCHECK(render_view->guest_pp_instance());
+ // TODO(fsamuel): Support child contexts.
+ bool success = Send(new PpapiHostMsg_PPBGraphics3D_Create(
+ ppapi::API_ID_PPB_GRAPHICS_3D,
+ render_view->guest_pp_instance(),
+ attribs,
+ &resource));
+ if (!success || resource.is_null())
+ return false;
+ if (!offscreen) {
+ PP_Bool result = PP_FALSE;
+ Send(new PpapiHostMsg_PPBInstance_BindGraphics(
+ ppapi::API_ID_PPB_INSTANCE,
+ render_view->guest_pp_instance(),
+ resource,
+ &result));
+ if (result != PP_TRUE)
+ return false;
+ }
+
+ CommandBufferProxy* command_buffer =
+ new ppapi::proxy::PpapiCommandBufferProxy(resource, this);
+ command_buffer->Initialize();
+ context->InitializeWithCommandBuffer(
+ command_buffer,
+ attributes,
+ false /* bind generates resources */);
+ render_view->set_guest_graphics_resource(resource);
+ return true;
+}
+
+void GuestToEmbedderChannel::AddGuest(
+ PP_Instance instance,
+ RenderViewImpl* render_view) {
+ DCHECK(instance);
+ DCHECK(render_view_instances_.find(instance) == render_view_instances_.end());
+ render_view_instances_[instance] = render_view->AsWeakPtr();
+}
+
+
+void GuestToEmbedderChannel::RemoveGuest(PP_Instance instance) {
+ DCHECK(render_view_instances_.find(instance) != render_view_instances_.end());
+ render_view_instances_.erase(instance);
+}
+
+void GuestToEmbedderChannel::OnDidCreate(PP_Instance instance,
+ const std::vector<std::string>& argn,
+ const std::vector<std::string>& argv,
+ PP_Bool* result) {
+ *result = PP_TRUE;
+}
+
+void GuestToEmbedderChannel::OnDidDestroy(PP_Instance instance) {
+ RemoveGuest(instance);
+}
+
+void GuestToEmbedderChannel::OnDidChangeView(
+ PP_Instance instance,
+ const ppapi::ViewData& new_data,
+ PP_Bool flash_fullscreen) {
+ // We can't do anything with this message if we don't have a render view
+ // yet. If we do have a RenderView then we need to tell the associated
+ // WebContentsObserver to resize.
+ if (render_view_instances_.find(instance) != render_view_instances_.end()) {
+ RenderViewImpl* render_view = render_view_instances_[instance];
+ render_view->Send(
+ new BrowserPluginHostMsg_ResizeGuest(
+ render_view->GetRoutingID(),
+ new_data.rect.size.width,
+ new_data.rect.size.height));
+ }
+}
+
+void GuestToEmbedderChannel::OnDidChangeFocus(PP_Instance instance,
+ PP_Bool has_focus) {
+ NOTIMPLEMENTED();
+}
+
+void GuestToEmbedderChannel::OnHandleMessage(
+ PP_Instance instance,
+ ppapi::proxy::SerializedVarReceiveInput message_data) {
+ InstanceMap::iterator it = render_view_instances_.find(instance);
+ if (it == render_view_instances_.end())
+ return;
+
+ PP_Var received_var(message_data.Get(this));
+ DCHECK(received_var.type == PP_VARTYPE_STRING);
+ ppapi::VarTracker* tracker = ppapi::PpapiGlobals::Get()->GetVarTracker();
+ ppapi::StringVar* var = tracker->GetVar(received_var)->AsStringVar();
+ DCHECK(var);
+
+ RenderViewImpl* render_view = it->second;
+ render_view->Send(
+ new BrowserPluginHostMsg_NavigateFromGuest(
+ render_view->GetRoutingID(),
+ instance,
+ var->value()));
+}
+
+void GuestToEmbedderChannel::OnHandleFilteredInputEvent(
+ PP_Instance instance,
+ const ppapi::InputEventData& data,
+ PP_Bool* result) {
+ DCHECK(render_view_instances_.find(instance) != render_view_instances_.end());
+
+ RenderViewImpl* render_view = render_view_instances_[instance];
+ scoped_ptr<WebKit::WebInputEvent> web_input_event(
+ webkit::ppapi::CreateWebInputEvent(data));
+ *result = PP_FromBool(
+ render_view->GetWebView()->handleInputEvent(*web_input_event));
+}
+
+void GuestToEmbedderChannel::OnContextLost(PP_Instance instance) {
+ DCHECK(render_view_instances_.find(instance) != render_view_instances_.end());
+ RenderViewImpl* render_view = render_view_instances_[instance];
+ render_view->GetWebView()->loseCompositorContext(1);
+}
+
+} // namespace content
diff --git a/content/renderer/browser_plugin/guest_to_embedder_channel.h b/content/renderer/browser_plugin/guest_to_embedder_channel.h
new file mode 100644
index 0000000..7d066be
--- /dev/null
+++ b/content/renderer/browser_plugin/guest_to_embedder_channel.h
@@ -0,0 +1,126 @@
+// Copyright (c) 2012 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 CONTENT_RENDERER_BROWSER_PLUGIN_GUEST_TO_EMBEDDER_CHANNEL_H_
+#define CONTENT_RENDERER_BROWSER_PLUGIN_GUEST_TO_EMBEDDER_CHANNEL_H_
+#pragma once
+
+#include "base/memory/ref_counted.h"
+#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
+#include "content/renderer/pepper/pepper_proxy_channel_delegate_impl.h"
+#include "content/renderer/render_view_impl.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/shared_impl/ppb_view_shared.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/shared_impl/host_resource.h"
+#include "ppapi/shared_impl/ppapi_preferences.h"
+#include "ppapi/shared_impl/ppb_input_event_shared.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebGraphicsContext3D.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
+
+namespace content {
+
+class BrowserPluginChannelManager;
+
+// GuestToEmbedderChannel is a Dispatcher that sends and receives ppapi messages
+// from the browser plugin embedder. It is reference counted because it is held
+// by a RenderViewImpl which (indirectly) owns a PpapiCommandBufferProxy through
+// a WebGraphicsContext3DCommandBufferImpl which is owned by WebKit. Since the
+// lifetime of this context is less than the lifetime of the RenderViewImpl, we
+// keep the GuestToEmbedderChannel alive as long as a RenderViewImpl has access
+// to it. If the context is lost, then the PpapiCommandBufferProxy is destroyed
+// and we can safely release the reference to this GuestToEmbedderChannel held
+// by RenderViewImpl.
+class GuestToEmbedderChannel
+ : public ppapi::proxy::Dispatcher,
+ public base::RefCounted<GuestToEmbedderChannel> {
+ public:
+ explicit GuestToEmbedderChannel(const std::string& embedder_channel_manager);
+
+ // This must be called before anything else. Returns true on success.
+ bool InitChannel(const IPC::ChannelHandle& channel_handle);
+
+ // Creates a new WebGraphicsContext3DCommandBufferImpl and returns it.
+ WebGraphicsContext3DCommandBufferImpl* CreateWebGraphicsContext3D(
+ RenderViewImpl* render_view,
+ const WebKit::WebGraphicsContext3D::Attributes& attributes,
+ bool offscreen);
+
+ // Inform the host to invalidate its plugin container after a swap buffer.
+ void IssueSwapBuffers(const ppapi::HostResource& resource);
+
+ // Request the receipt of events from the embedder renderer.
+ void RequestInputEvents(PP_Instance instance);
+
+ // Request a graphics context from the embedder renderer.
+ bool CreateGraphicsContext(
+ WebGraphicsContext3DCommandBufferImpl* context,
+ const WebKit::WebGraphicsContext3D::Attributes& attributes,
+ bool offscreen,
+ RenderViewImpl* render_view);
+
+ // Register the given RenderView with the given PP_Instance.
+ void AddGuest(PP_Instance instance, RenderViewImpl* render_view);
+
+ // Removes the guest with the given instance identifier from the
+ // InstanceMap.
+ void RemoveGuest(PP_Instance instance);
+
+ // ppapi::proxy::Dispatcher implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ virtual bool Send(IPC::Message* message) OVERRIDE;
+ virtual void OnChannelError() OVERRIDE;
+ virtual bool IsPlugin() const OVERRIDE;
+
+ private:
+ friend class base::RefCounted<GuestToEmbedderChannel>;
+ typedef std::map<PP_Instance, base::WeakPtr<RenderViewImpl> > InstanceMap;
+ typedef std::map<int, int> RoutingIDToInstanceMap;
+
+ virtual ~GuestToEmbedderChannel();
+
+ void OnSupportsInterface(const std::string& interface_name, bool* result);
+ void OnSetPreferences(const ppapi::Preferences& prefs);
+ void OnReserveInstanceId(PP_Instance instance, bool* usable);
+ void OnDidCreate(PP_Instance instance,
+ const std::vector<std::string>& argn,
+ const std::vector<std::string>& argv,
+ PP_Bool* result);
+ void OnDidDestroy(PP_Instance instance);
+ void OnDidChangeView(PP_Instance instance,
+ const ppapi::ViewData& new_data,
+ PP_Bool flash_fullscreen);
+ void OnDidChangeFocus(PP_Instance instance, PP_Bool has_focus);
+ void OnGetInstanceObject(PP_Instance instance,
+ ppapi::proxy::SerializedVarReturnValue result);
+
+ void OnHandleMessage(PP_Instance instance,
+ ppapi::proxy::SerializedVarReceiveInput data);
+
+ void OnHandleFilteredInputEvent(PP_Instance instance,
+ const ppapi::InputEventData& data,
+ PP_Bool* result);
+
+ void OnSwapBuffersACK(const ppapi::HostResource& context,
+ int32_t pp_error);
+
+ void OnContextLost(PP_Instance instance);
+
+ base::WeakPtr<RenderViewImpl> render_view_;
+ BrowserPluginChannelManager* channel_manager_;
+ std::string embedder_channel_name_;
+ PepperProxyChannelDelegateImpl delegate_;
+
+ InstanceMap render_view_instances_;
+ RoutingIDToInstanceMap routing_id_instance_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(GuestToEmbedderChannel);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_BROWSER_PLUGIN_GUEST_TO_EMBEDDER_CHANNEL_H_