| // 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 PPAPI_PROXY_PLUGIN_RESOURCE_H_ |
| #define PPAPI_PROXY_PLUGIN_RESOURCE_H_ |
| |
| #include <map> |
| |
| #include "base/basictypes.h" |
| #include "base/compiler_specific.h" |
| #include "ipc/ipc_message.h" |
| #include "ipc/ipc_sender.h" |
| #include "ppapi/c/pp_errors.h" |
| #include "ppapi/proxy/connection.h" |
| #include "ppapi/proxy/plugin_resource_callback.h" |
| #include "ppapi/proxy/ppapi_message_utils.h" |
| #include "ppapi/proxy/ppapi_proxy_export.h" |
| #include "ppapi/proxy/resource_message_params.h" |
| #include "ppapi/shared_impl/resource.h" |
| |
| namespace ppapi { |
| namespace proxy { |
| |
| class PluginDispatcher; |
| |
| class PPAPI_PROXY_EXPORT PluginResource : public Resource { |
| public: |
| PluginResource(Connection connection, PP_Instance instance); |
| virtual ~PluginResource(); |
| |
| // Returns true if we've previously sent a create message to the browser |
| // or renderer. Generally resources will use these to tell if they should |
| // lazily send create messages. |
| bool sent_create_to_browser() const { return sent_create_to_browser_; } |
| bool sent_create_to_renderer() const { return sent_create_to_renderer_; } |
| |
| // This handles a reply to a resource call. It works by looking up the |
| // callback that was registered when CallBrowser/CallRenderer was called |
| // and calling it with |params| and |msg|. |
| virtual void OnReplyReceived(const proxy::ResourceMessageReplyParams& params, |
| const IPC::Message& msg) OVERRIDE; |
| |
| // Resource overrides. |
| // Note: Subclasses shouldn't override these methods directly. Instead, they |
| // should implement LastPluginRefWasDeleted() or InstanceWasDeleted() to get |
| // notified. |
| virtual void NotifyLastPluginRefWasDeleted() OVERRIDE; |
| virtual void NotifyInstanceWasDeleted() OVERRIDE; |
| |
| protected: |
| enum Destination { |
| RENDERER = 0, |
| BROWSER = 1 |
| }; |
| |
| IPC::Sender* GetSender(Destination dest) { |
| return dest == RENDERER ? connection_.renderer_sender : |
| connection_.browser_sender; |
| } |
| |
| // Sends a create message to the browser or renderer for the current resource. |
| void SendCreate(Destination dest, const IPC::Message& msg); |
| |
| // Sends the given IPC message as a resource request to the host |
| // corresponding to this resource object and does not expect a reply. |
| void Post(Destination dest, const IPC::Message& msg); |
| |
| // Like Post() but expects a response. |callback| is a |base::Callback| that |
| // will be run when a reply message with a sequence number matching that of |
| // the call is received. |ReplyMsgClass| is the type of the reply message that |
| // is expected. An example of usage: |
| // |
| // Call<PpapiPluginMsg_MyResourceType_MyReplyMessage>( |
| // BROWSER, |
| // PpapiHostMsg_MyResourceType_MyRequestMessage(), |
| // base::Bind(&MyPluginResource::ReplyHandler, base::Unretained(this))); |
| // |
| // If a reply message to this call is received whose type does not match |
| // |ReplyMsgClass| (for example, in the case of an error), the callback will |
| // still be invoked but with the default values of the message parameters. |
| // |
| // Returns the new request's sequence number which can be used to identify |
| // the callback. This value will never be 0, which you can use to identify |
| // an invalid callback. |
| // |
| // Note: 1) When all plugin references to this resource are gone or the |
| // corresponding plugin instance is deleted, all pending callbacks |
| // are abandoned. |
| // 2) It is *not* recommended to let |callback| hold any reference to |
| // |this|, in which it will be stored. Otherwise, this object will |
| // live forever if we fail to clean up the callback. It is safe to |
| // use base::Unretained(this) or a weak pointer, because this object |
| // will outlive the callback. |
| template<typename ReplyMsgClass, typename CallbackType> |
| int32_t Call(Destination dest, |
| const IPC::Message& msg, |
| const CallbackType& callback); |
| |
| // Calls the browser/renderer with sync messages. Returns the pepper error |
| // code from the call. |
| // |ReplyMsgClass| is the type of the reply message that is expected. If it |
| // carries x parameters, then the method with x out parameters should be used. |
| // An example of usage: |
| // |
| // // Assuming the reply message carries a string and an integer. |
| // std::string param_1; |
| // int param_2 = 0; |
| // int32_t result = SyncCall<PpapiPluginMsg_MyResourceType_MyReplyMessage>( |
| // RENDERER, PpapiHostMsg_MyResourceType_MyRequestMessage(), |
| // ¶m_1, ¶m_2); |
| template <class ReplyMsgClass> |
| int32_t SyncCall(Destination dest, const IPC::Message& msg); |
| template <class ReplyMsgClass, class A> |
| int32_t SyncCall(Destination dest, const IPC::Message& msg, A* a); |
| template <class ReplyMsgClass, class A, class B> |
| int32_t SyncCall(Destination dest, const IPC::Message& msg, A* a, B* b); |
| template <class ReplyMsgClass, class A, class B, class C> |
| int32_t SyncCall(Destination dest, const IPC::Message& msg, A* a, B* b, C* c); |
| template <class ReplyMsgClass, class A, class B, class C, class D> |
| int32_t SyncCall( |
| Destination dest, const IPC::Message& msg, A* a, B* b, C* c, D* d); |
| template <class ReplyMsgClass, class A, class B, class C, class D, class E> |
| int32_t SyncCall( |
| Destination dest, const IPC::Message& msg, A* a, B* b, C* c, D* d, E* e); |
| |
| private: |
| // Helper function to send a |PpapiHostMsg_ResourceCall| to the given |
| // destination with |nested_msg| and |call_params|. |
| bool SendResourceCall(Destination dest, |
| const ResourceMessageCallParams& call_params, |
| const IPC::Message& nested_msg); |
| |
| int32_t GenericSyncCall(Destination dest, |
| const IPC::Message& msg, |
| IPC::Message* reply_msg); |
| |
| int32_t GetNextSequence(); |
| |
| Connection connection_; |
| |
| // Use GetNextSequence to retrieve the next value. |
| int32_t next_sequence_number_; |
| |
| bool sent_create_to_browser_; |
| bool sent_create_to_renderer_; |
| |
| typedef std::map<int32_t, scoped_refptr<PluginResourceCallbackBase> > |
| CallbackMap; |
| CallbackMap callbacks_; |
| |
| DISALLOW_COPY_AND_ASSIGN(PluginResource); |
| }; |
| |
| template<typename ReplyMsgClass, typename CallbackType> |
| int32_t PluginResource::Call(Destination dest, |
| const IPC::Message& msg, |
| const CallbackType& callback) { |
| ResourceMessageCallParams params(pp_resource(), next_sequence_number_++); |
| // Stash the |callback| in |callbacks_| identified by the sequence number of |
| // the call. |
| scoped_refptr<PluginResourceCallbackBase> plugin_callback( |
| new PluginResourceCallback<ReplyMsgClass, CallbackType>(callback)); |
| callbacks_.insert(std::make_pair(params.sequence(), plugin_callback)); |
| params.set_has_callback(); |
| SendResourceCall(dest, params, msg); |
| return params.sequence(); |
| } |
| |
| template <class ReplyMsgClass> |
| int32_t PluginResource::SyncCall(Destination dest, const IPC::Message& msg) { |
| IPC::Message reply; |
| return GenericSyncCall(dest, msg, &reply); |
| } |
| |
| template <class ReplyMsgClass, class A> |
| int32_t PluginResource::SyncCall( |
| Destination dest, const IPC::Message& msg, A* a) { |
| IPC::Message reply; |
| int32_t result = GenericSyncCall(dest, msg, &reply); |
| |
| if (UnpackMessage<ReplyMsgClass>(reply, a)) |
| return result; |
| return PP_ERROR_FAILED; |
| } |
| |
| template <class ReplyMsgClass, class A, class B> |
| int32_t PluginResource::SyncCall( |
| Destination dest, const IPC::Message& msg, A* a, B* b) { |
| IPC::Message reply; |
| int32_t result = GenericSyncCall(dest, msg, &reply); |
| |
| if (UnpackMessage<ReplyMsgClass>(reply, a, b)) |
| return result; |
| return PP_ERROR_FAILED; |
| } |
| |
| template <class ReplyMsgClass, class A, class B, class C> |
| int32_t PluginResource::SyncCall( |
| Destination dest, const IPC::Message& msg, A* a, B* b, C* c) { |
| IPC::Message reply; |
| int32_t result = GenericSyncCall(dest, msg, &reply); |
| |
| if (UnpackMessage<ReplyMsgClass>(reply, a, b, c)) |
| return result; |
| return PP_ERROR_FAILED; |
| } |
| |
| template <class ReplyMsgClass, class A, class B, class C, class D> |
| int32_t PluginResource::SyncCall( |
| Destination dest, const IPC::Message& msg, A* a, B* b, C* c, D* d) { |
| IPC::Message reply; |
| int32_t result = GenericSyncCall(dest, msg, &reply); |
| |
| if (UnpackMessage<ReplyMsgClass>(reply, a, b, c, d)) |
| return result; |
| return PP_ERROR_FAILED; |
| } |
| |
| template <class ReplyMsgClass, class A, class B, class C, class D, class E> |
| int32_t PluginResource::SyncCall( |
| Destination dest, const IPC::Message& msg, A* a, B* b, C* c, D* d, E* e) { |
| IPC::Message reply; |
| int32_t result = GenericSyncCall(dest, msg, &reply); |
| |
| if (UnpackMessage<ReplyMsgClass>(reply, a, b, c, d, e)) |
| return result; |
| return PP_ERROR_FAILED; |
| } |
| |
| } // namespace proxy |
| } // namespace ppapi |
| |
| #endif // PPAPI_PROXY_PLUGIN_RESOURCE_H_ |