diff options
Diffstat (limited to 'chromium/ppapi/proxy/plugin_resource.cc')
-rw-r--r-- | chromium/ppapi/proxy/plugin_resource.cc | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/chromium/ppapi/proxy/plugin_resource.cc b/chromium/ppapi/proxy/plugin_resource.cc new file mode 100644 index 00000000000..c450f3c29af --- /dev/null +++ b/chromium/ppapi/proxy/plugin_resource.cc @@ -0,0 +1,160 @@ +// 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 "ppapi/proxy/plugin_resource.h" + +#include <limits> + +#include "ppapi/proxy/ppapi_messages.h" + +namespace ppapi { +namespace proxy { + +PluginResource::PluginResource(Connection connection, PP_Instance instance) + : Resource(OBJECT_IS_PROXY, instance), + connection_(connection), + next_sequence_number_(1), + sent_create_to_browser_(false), + sent_create_to_renderer_(false) { +} + +PluginResource::~PluginResource() { + if (sent_create_to_browser_) { + connection_.browser_sender->Send( + new PpapiHostMsg_ResourceDestroyed(pp_resource())); + } + if (sent_create_to_renderer_) { + connection_.renderer_sender->Send( + new PpapiHostMsg_ResourceDestroyed(pp_resource())); + } +} + +void PluginResource::OnReplyReceived( + const proxy::ResourceMessageReplyParams& params, + const IPC::Message& msg) { + TRACE_EVENT2("ppapi proxy", "PluginResource::OnReplyReceived", + "Class", IPC_MESSAGE_ID_CLASS(msg.type()), + "Line", IPC_MESSAGE_ID_LINE(msg.type())); + // Grab the callback for the reply sequence number and run it with |msg|. + CallbackMap::iterator it = callbacks_.find(params.sequence()); + if (it == callbacks_.end()) { + DCHECK(false) << "Callback does not exist for an expected sequence number."; + } else { + scoped_refptr<PluginResourceCallbackBase> callback = it->second; + callbacks_.erase(it); + callback->Run(params, msg); + } +} + +void PluginResource::NotifyLastPluginRefWasDeleted() { + Resource::NotifyLastPluginRefWasDeleted(); + + // The callbacks may hold referrences to this object. Normally, we will get + // reply messages from the host side and remove them. However, it is possible + // that some replies from the host never arrive, e.g., the corresponding + // renderer crashes. In that case, we have to clean up the callbacks, + // otherwise this object will live forever. + callbacks_.clear(); +} + +void PluginResource::NotifyInstanceWasDeleted() { + Resource::NotifyInstanceWasDeleted(); + + // Please see comments in NotifyLastPluginRefWasDeleted() about why we must + // clean up the callbacks. + // It is possible that NotifyLastPluginRefWasDeleted() is never called for a + // resource. For example, those singleton-style resources such as + // GamepadResource never expose references to the plugin and thus won't + // receive a NotifyLastPluginRefWasDeleted() call. For those resources, we + // need to clean up callbacks when the instance goes away. + callbacks_.clear(); +} + +void PluginResource::SendCreate(Destination dest, const IPC::Message& msg) { + TRACE_EVENT2("ppapi proxy", "PluginResource::SendCreate", + "Class", IPC_MESSAGE_ID_CLASS(msg.type()), + "Line", IPC_MESSAGE_ID_LINE(msg.type())); + if (dest == RENDERER) { + DCHECK(!sent_create_to_renderer_); + sent_create_to_renderer_ = true; + } else { + DCHECK(!sent_create_to_browser_); + sent_create_to_browser_ = true; + } + ResourceMessageCallParams params(pp_resource(), GetNextSequence()); + GetSender(dest)->Send( + new PpapiHostMsg_ResourceCreated(params, pp_instance(), msg)); +} + +void PluginResource::AttachToPendingHost(Destination dest, + int pending_host_id) { + // Connecting to a pending host is a replacement for "create". + if (dest == RENDERER) { + DCHECK(!sent_create_to_renderer_); + sent_create_to_renderer_ = true; + } else { + DCHECK(!sent_create_to_browser_); + sent_create_to_browser_ = true; + } + GetSender(dest)->Send( + new PpapiHostMsg_AttachToPendingHost(pp_resource(), pending_host_id)); +} + +void PluginResource::Post(Destination dest, const IPC::Message& msg) { + TRACE_EVENT2("ppapi proxy", "PluginResource::Post", + "Class", IPC_MESSAGE_ID_CLASS(msg.type()), + "Line", IPC_MESSAGE_ID_LINE(msg.type())); + ResourceMessageCallParams params(pp_resource(), GetNextSequence()); + SendResourceCall(dest, params, msg); +} + +bool PluginResource::SendResourceCall( + Destination dest, + const ResourceMessageCallParams& call_params, + const IPC::Message& nested_msg) { + // For in-process plugins, we need to send the routing ID with the request. + // The browser then uses that routing ID when sending the reply so it will be + // routed back to the correct RenderViewImpl. + if (dest == BROWSER && connection_.in_process) { + return GetSender(dest)->Send(new PpapiHostMsg_InProcessResourceCall( + connection_.browser_sender_routing_id, + call_params, + nested_msg)); + } else { + return GetSender(dest)->Send( + new PpapiHostMsg_ResourceCall(call_params, nested_msg)); + } +} + +int32_t PluginResource::GenericSyncCall( + Destination dest, + const IPC::Message& msg, + IPC::Message* reply, + ResourceMessageReplyParams* reply_params) { + TRACE_EVENT2("ppapi proxy", "PluginResource::GenericSyncCall", + "Class", IPC_MESSAGE_ID_CLASS(msg.type()), + "Line", IPC_MESSAGE_ID_LINE(msg.type())); + ResourceMessageCallParams params(pp_resource(), GetNextSequence()); + params.set_has_callback(); + bool success = GetSender(dest)->Send(new PpapiHostMsg_ResourceSyncCall( + params, msg, reply_params, reply)); + if (success) + return reply_params->result(); + return PP_ERROR_FAILED; +} + +int32_t PluginResource::GetNextSequence() { + // Return the value with wraparound, making sure we don't make a sequence + // number with a 0 ID. Note that signed wraparound is undefined in C++ so we + // manually check. + int32_t ret = next_sequence_number_; + if (next_sequence_number_ == std::numeric_limits<int32_t>::max()) + next_sequence_number_ = 1; // Skip 0 which is invalid. + else + next_sequence_number_++; + return ret; +} + +} // namespace proxy +} // namespace ppapi |