| Index: content/renderer/browser_plugin/guest_to_embedder_channel.cc
|
| 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 0000000000000000000000000000000000000000..95008c9920c45b0450ef59dd0fbb95ee1806978b
|
| --- /dev/null
|
| +++ b/content/renderer/browser_plugin/guest_to_embedder_channel.cc
|
| @@ -0,0 +1,276 @@
|
| +// 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());
|
| +}
|
| +
|
| +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
|
|
|