diff options
author | fsamuel@chromium.org <fsamuel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-23 01:49:31 +0000 |
---|---|---|
committer | fsamuel@chromium.org <fsamuel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-23 01:49:31 +0000 |
commit | 468e49044631580483bd15dd2ff9a548bd886968 (patch) | |
tree | 1d760140ddc8779799ef6e981e88e0fe4d9a6339 /content/renderer/browser_plugin | |
parent | 28599f4802c403c4d362f734ba37f81b552be977 (diff) | |
download | chromium_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')
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_ |