diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-21 04:41:59 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-21 04:41:59 +0000 |
commit | 645ef96b909147f0787f4afa53f39594cb78b211 (patch) | |
tree | fe991fceecfb2b354bd8c096274beb14637fa2c1 | |
parent | 7610cede2a571dcf71b5012c8f77b7cc7f8124e5 (diff) | |
download | chromium_src-645ef96b909147f0787f4afa53f39594cb78b211.zip chromium_src-645ef96b909147f0787f4afa53f39594cb78b211.tar.gz chromium_src-645ef96b909147f0787f4afa53f39594cb78b211.tar.bz2 |
Remove the proxy callback tracker.
This doesn't properly delete callbacks when the corresponding resource goes
away. This can lead to leaks or crashes in the plugin when the callback is
triggered unexpectedly.
BUG=http://crbug.com/86279
Review URL: http://codereview.chromium.org/8226009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@106677 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ppapi/ppapi_proxy.gypi | 2 | ||||
-rw-r--r-- | ppapi/proxy/callback_tracker.cc | 72 | ||||
-rw-r--r-- | ppapi/proxy/callback_tracker.h | 66 | ||||
-rw-r--r-- | ppapi/proxy/dispatcher.cc | 14 | ||||
-rw-r--r-- | ppapi/proxy/dispatcher.h | 7 | ||||
-rw-r--r-- | ppapi/proxy/enter_proxy.h | 76 | ||||
-rw-r--r-- | ppapi/proxy/interface_proxy.cc | 9 | ||||
-rw-r--r-- | ppapi/proxy/interface_proxy.h | 3 | ||||
-rw-r--r-- | ppapi/proxy/plugin_dispatcher.cc | 10 | ||||
-rw-r--r-- | ppapi/proxy/plugin_dispatcher.h | 5 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_messages.h | 48 | ||||
-rw-r--r-- | ppapi/proxy/ppb_file_ref_proxy.cc | 172 | ||||
-rw-r--r-- | ppapi/proxy/ppb_file_ref_proxy.h | 36 | ||||
-rw-r--r-- | ppapi/proxy/ppb_instance_proxy.cc | 56 | ||||
-rw-r--r-- | ppapi/proxy/ppb_instance_proxy.h | 20 | ||||
-rw-r--r-- | ppapi/proxy/ppb_url_loader_proxy.cc | 133 | ||||
-rw-r--r-- | ppapi/proxy/ppb_url_loader_proxy.h | 31 | ||||
-rw-r--r-- | ppapi/thunk/ppb_instance_api.h | 5 |
18 files changed, 434 insertions, 331 deletions
diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi index 257d336..caab99f 100644 --- a/ppapi/ppapi_proxy.gypi +++ b/ppapi/ppapi_proxy.gypi @@ -27,8 +27,6 @@ '../..', # For nacl includes to work. ], 'sources': [ - 'proxy/callback_tracker.cc', - 'proxy/callback_tracker.h', 'proxy/broker_dispatcher.cc', 'proxy/broker_dispatcher.h', 'proxy/dispatcher.cc', diff --git a/ppapi/proxy/callback_tracker.cc b/ppapi/proxy/callback_tracker.cc deleted file mode 100644 index 70b75d6..0000000 --- a/ppapi/proxy/callback_tracker.cc +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2011 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/callback_tracker.h" - -#include "ppapi/proxy/dispatcher.h" -#include "ppapi/proxy/ppapi_messages.h" - -namespace ppapi { -namespace proxy { - -namespace { - -struct CallbackData { - CallbackTracker* tracker; - uint32_t callback_id; -}; - -void CallbackProxy(void* user_data, int32_t result) { - CallbackData* data = static_cast<CallbackData*>(user_data); - data->tracker->SendExecuteSerializedCallback(data->callback_id, result); - delete data; -} - -} // namespace - -CallbackTracker::CallbackTracker(Dispatcher* dispatcher) - : dispatcher_(dispatcher), - next_callback_id_(1) { -} - -CallbackTracker::~CallbackTracker() { -} - -uint32_t CallbackTracker::SendCallback(PP_CompletionCallback callback) { - // Find the next callback ID we can use (being careful about wraparound). - while (callback_map_.find(next_callback_id_) != callback_map_.end()) - next_callback_id_++; - callback_map_[next_callback_id_] = callback; - return next_callback_id_++; -} - -PP_CompletionCallback CallbackTracker::ReceiveCallback( - uint32_t serialized_callback) { - CallbackData* data = new CallbackData; - data->tracker = this; - data->callback_id = serialized_callback; - return PP_MakeCompletionCallback(&CallbackProxy, data); -} - -void CallbackTracker::SendExecuteSerializedCallback( - uint32_t serialized_callback, - int32_t param) { - dispatcher_->Send(new PpapiMsg_ExecuteCallback(serialized_callback, param)); -} - -void CallbackTracker::ReceiveExecuteSerializedCallback( - uint32_t serialized_callback, - int32_t param) { - CallbackMap::iterator found = callback_map_.find(serialized_callback); - if (found == callback_map_.end()) { - NOTREACHED(); - return; - } - - PP_RunCompletionCallback(&found->second, param); - callback_map_.erase(found); -} - -} // namespace proxy -} // namespace ppapi diff --git a/ppapi/proxy/callback_tracker.h b/ppapi/proxy/callback_tracker.h deleted file mode 100644 index 90c324a..0000000 --- a/ppapi/proxy/callback_tracker.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2011 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_CALLBACK_TRACKER_H_ -#define PPAPI_PROXY_CALLBACK_TRACKER_H_ - -#include <map> - -#include "ppapi/c/pp_completion_callback.h" -#include "ppapi/c/pp_stdint.h" - -namespace ppapi { -namespace proxy { - -class Dispatcher; - -// This object tracks cross-process callbacks. When the plugin sends a callback -// object to the renderer, we save the information and pass an identifier -// instead. -// -// On the renderer side, this identifier is converted to a new callback in that -// process. When executed, this new callback sends an IPC message containing the -// previous identifier back to the plugin. -// -// When we receive that message, ExecuteSerializedCallback converts the -// identifier back to the original callback information and runs the callback. -class CallbackTracker { - public: - CallbackTracker(Dispatcher* dispatcher); - ~CallbackTracker(); - - // Converts the given callback in the context of the plugin to a serialized - // ID. This will be passed to ReceiveCallback on the renderer side. - uint32_t SendCallback(PP_CompletionCallback callback); - - // Converts the given serialized callback ID to a new completion callback in - // the context of the current process. This callback actually will represent - // a proxy that will execute the callback in the plugin process. - PP_CompletionCallback ReceiveCallback(uint32_t serialized_callback); - - // Sends a request to the remote process to execute the given callback. - void SendExecuteSerializedCallback(uint32_t serialized_callback, - int32_t param); - - // Executes the given callback ID with the given result in the current - // process. This will also destroy the information associated with the - // callback and the serialized ID won't be valid any more. - void ReceiveExecuteSerializedCallback(uint32_t serialized_callback, - int32_t param); - - private: - // Pointer to the dispatcher that owns us. - Dispatcher* dispatcher_; - - int32_t next_callback_id_; - - // Maps callback IDs to the actual callback objects in the plugin process. - typedef std::map<int32_t, PP_CompletionCallback> CallbackMap; - CallbackMap callback_map_; -}; - -} // namespace proxy -} // namespace ppapi - -#endif // PPAPI_PROXY_CALLBACK_TRACKER_H_ diff --git a/ppapi/proxy/dispatcher.cc b/ppapi/proxy/dispatcher.cc index 1d8614d..8ba7830 100644 --- a/ppapi/proxy/dispatcher.cc +++ b/ppapi/proxy/dispatcher.cc @@ -21,8 +21,7 @@ Dispatcher::Dispatcher(base::ProcessHandle remote_process_handle, GetInterfaceFunc local_get_interface) : ProxyChannel(remote_process_handle), disallow_trusted_interfaces_(false), // TODO(brettw) make this settable. - local_get_interface_(local_get_interface), - callback_tracker_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { + local_get_interface_(local_get_interface) { } Dispatcher::~Dispatcher() { @@ -55,17 +54,6 @@ void Dispatcher::AddIOThreadMessageFilter( } bool Dispatcher::OnMessageReceived(const IPC::Message& msg) { - // Control messages. - if (msg.routing_id() == MSG_ROUTING_CONTROL) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(Dispatcher, msg) - IPC_MESSAGE_FORWARD(PpapiMsg_ExecuteCallback, &callback_tracker_, - CallbackTracker::ReceiveExecuteSerializedCallback) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; - } - if (msg.routing_id() <= 0 || msg.routing_id() >= API_ID_COUNT) { OnInvalidMessageReceived(); return true; diff --git a/ppapi/proxy/dispatcher.h b/ppapi/proxy/dispatcher.h index 9a4395e..988f53d 100644 --- a/ppapi/proxy/dispatcher.h +++ b/ppapi/proxy/dispatcher.h @@ -14,7 +14,6 @@ #include "ipc/ipc_channel_proxy.h" #include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_module.h" -#include "ppapi/proxy/callback_tracker.h" #include "ppapi/proxy/proxy_channel.h" #include "ppapi/proxy/interface_list.h" #include "ppapi/proxy/interface_proxy.h" @@ -83,10 +82,6 @@ class PPAPI_PROXY_EXPORT Dispatcher : public ProxyChannel { // IPC::Channel::Listener implementation. virtual bool OnMessageReceived(const IPC::Message& msg); - CallbackTracker& callback_tracker() { - return callback_tracker_; - } - GetInterfaceFunc local_get_interface() const { return local_get_interface_; } protected: @@ -116,8 +111,6 @@ class PPAPI_PROXY_EXPORT Dispatcher : public ProxyChannel { GetInterfaceFunc local_get_interface_; - CallbackTracker callback_tracker_; - scoped_ptr<VarSerializationRules> serialization_rules_; DISALLOW_COPY_AND_ASSIGN(Dispatcher); diff --git a/ppapi/proxy/enter_proxy.h b/ppapi/proxy/enter_proxy.h index 96ac0c18..3f819ba 100644 --- a/ppapi/proxy/enter_proxy.h +++ b/ppapi/proxy/enter_proxy.h @@ -166,6 +166,82 @@ class EnterHostFromHostResourceForceCallback pp::CompletionCallback callback_; }; +// Like EnterHostFromHostResourceForceCallback but for Function APIs. It takes +// an instance instead of a resource ID. +template<typename FunctionT> +class EnterHostFunctionForceCallback + : public thunk::EnterFunctionNoLock<FunctionT> { + public: + // For callbacks that take no parameters except the "int32_t result". Most + // implementations will use the 1-extra-argument constructor below. + template<class CallbackFactory, typename Method> + EnterHostFunctionForceCallback(PP_Instance instance, + CallbackFactory& factory, + Method method) + : thunk::EnterFunctionNoLock<FunctionT>(instance, false), + needs_running_(true), + callback_(factory.NewOptionalCallback(method)) { + if (this->failed()) + RunCallback(PP_ERROR_BADARGUMENT); + } + + // For callbacks that take an extra parameter as a closure. + template<class CallbackFactory, typename Method, typename A> + EnterHostFunctionForceCallback(PP_Instance instance, + CallbackFactory& factory, + Method method, + const A& a) + : thunk::EnterFunctionNoLock<FunctionT>(instance, false), + needs_running_(true), + callback_(factory.NewOptionalCallback(method, a)) { + if (this->failed()) + RunCallback(PP_ERROR_BADARGUMENT); + } + + // For callbacks that take two extra parameters as a closure. + template<class CallbackFactory, typename Method, typename A, typename B> + EnterHostFunctionForceCallback(PP_Instance instance, + CallbackFactory& factory, + Method method, + const A& a, + const B& b) + : thunk::EnterFunctionNoLock<FunctionT>(instance), + needs_running_(true), + callback_(factory.NewOptionalCallback(method, a, b)) { + if (this->failed()) + RunCallback(PP_ERROR_BADARGUMENT); + } + + ~EnterHostFunctionForceCallback() { + if (needs_running_) { + NOTREACHED() << "Should always call SetResult except in the " + "initialization failed case."; + RunCallback(PP_ERROR_FAILED); + } + } + + void SetResult(int32_t result) { + DCHECK(needs_running_) << "Don't call SetResult when there already is one."; + needs_running_ = false; + if (result != PP_OK_COMPLETIONPENDING) + callback_.Run(result); + } + + PP_CompletionCallback callback() { + return callback_.pp_completion_callback(); + } + + private: + void RunCallback(int32_t result) { + DCHECK(needs_running_); + needs_running_ = false; + callback_.Run(result); + } + + bool needs_running_; + pp::CompletionCallback callback_; +}; + } // namespace proxy } // namespace ppapi diff --git a/ppapi/proxy/interface_proxy.cc b/ppapi/proxy/interface_proxy.cc index 913821a..2de4803 100644 --- a/ppapi/proxy/interface_proxy.cc +++ b/ppapi/proxy/interface_proxy.cc @@ -21,14 +21,5 @@ bool InterfaceProxy::Send(IPC::Message* msg) { return dispatcher_->Send(msg); } -uint32 InterfaceProxy::SendCallback(PP_CompletionCallback callback) { - return dispatcher_->callback_tracker().SendCallback(callback); -} - -PP_CompletionCallback InterfaceProxy::ReceiveCallback( - uint32 serialized_callback) { - return dispatcher_->callback_tracker().ReceiveCallback(serialized_callback); -} - } // namespace proxy } // namespace ppapi diff --git a/ppapi/proxy/interface_proxy.h b/ppapi/proxy/interface_proxy.h index b9891b9..a35c63d 100644 --- a/ppapi/proxy/interface_proxy.h +++ b/ppapi/proxy/interface_proxy.h @@ -60,9 +60,6 @@ class InterfaceProxy : public IPC::Channel::Listener, // dispatcher manages our lifetime. InterfaceProxy(Dispatcher* dispatcher); - uint32 SendCallback(PP_CompletionCallback callback); - PP_CompletionCallback ReceiveCallback(uint32 serialized_callback); - private: Dispatcher* dispatcher_; }; diff --git a/ppapi/proxy/plugin_dispatcher.cc b/ppapi/proxy/plugin_dispatcher.cc index dba5253..3da15e9 100644 --- a/ppapi/proxy/plugin_dispatcher.cc +++ b/ppapi/proxy/plugin_dispatcher.cc @@ -42,10 +42,18 @@ InstanceToDispatcherMap* g_instance_to_dispatcher = NULL; } // namespace InstanceData::InstanceData() - : fullscreen(PP_FALSE), flash_fullscreen(PP_FALSE) { + : fullscreen(PP_FALSE), + flash_fullscreen(PP_FALSE), + mouse_lock_callback(PP_BlockUntilComplete()) { memset(&position, 0, sizeof(position)); } +InstanceData::~InstanceData() { + // Run any pending mouse lock callback to prevent leaks. + if (mouse_lock_callback.func) + PP_RunAndClearCompletionCallback(&mouse_lock_callback, PP_ERROR_ABORTED); +} + PluginDispatcher::PluginDispatcher(base::ProcessHandle remote_process_handle, GetInterfaceFunc get_interface) : Dispatcher(remote_process_handle, get_interface), diff --git a/ppapi/proxy/plugin_dispatcher.h b/ppapi/proxy/plugin_dispatcher.h index 2775463..b16484c 100644 --- a/ppapi/proxy/plugin_dispatcher.h +++ b/ppapi/proxy/plugin_dispatcher.h @@ -34,9 +34,14 @@ namespace proxy { // Used to keep track of per-instance data. struct InstanceData { InstanceData(); + ~InstanceData(); + PP_Rect position; PP_Bool fullscreen; // Used for PPB_Fullscreen. PP_Bool flash_fullscreen; // Used for PPB_FlashFullscreen. + + // When non-0, indicates the callback to execute when mouse lock is lost. + PP_CompletionCallback mouse_lock_callback; }; class PPAPI_PROXY_EXPORT PluginDispatcher : public Dispatcher { diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index 9bf77d6..11ca77a 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -193,10 +193,6 @@ IPC_SYNC_MESSAGE_CONTROL1_1(PpapiMsg_SupportsInterface, std::string /* interface_name */, bool /* result */) -IPC_MESSAGE_CONTROL2(PpapiMsg_ExecuteCallback, - uint32 /* serialized_callback */, - int32 /* param */) - // Broker Process. IPC_SYNC_MESSAGE_CONTROL2_1(PpapiMsg_ConnectToPlugin, @@ -234,6 +230,13 @@ IPC_MESSAGE_ROUTED3( int32_t /* result_code (will be != PP_OK on failure */, std::vector<ppapi::PPB_FileRef_CreateInfo> /* chosen_files */) +// PPB_FileRef. +IPC_MESSAGE_ROUTED3( + PpapiMsg_PPBFileRef_CallbackComplete, + ppapi::HostResource /* resource */, + int /* callback_id */, + int32_t /* result */) + // PPB_FileSystem. IPC_MESSAGE_ROUTED2( PpapiMsg_PPBFileSystem_OpenComplete, @@ -297,6 +300,11 @@ IPC_MESSAGE_ROUTED2(PpapiMsg_PPBGraphics3D_SwapBuffersACK, ppapi::HostResource /* graphics_3d */, int32_t /* pp_error */) +// PPB_Instance. +IPC_MESSAGE_ROUTED2(PpapiMsg_PPBInstance_MouseLockComplete, + PP_Instance /* instance */, + int32_t /* result */) + // PPB_Surface3D. IPC_MESSAGE_ROUTED2(PpapiMsg_PPBSurface3D_SwapBuffersACK, ppapi::HostResource /* surface_3d */, @@ -412,6 +420,9 @@ IPC_MESSAGE_ROUTED3(PpapiMsg_PPBURLLoader_ReadResponseBody_Ack, ppapi::HostResource /* loader */, int32 /* result */, std::string /* data */) +IPC_MESSAGE_ROUTED2(PpapiMsg_PPBURLLoader_CallbackComplete, + ppapi::HostResource /* loader */, + int32_t /* result */) // PPP_VideoCapture_Dev IPC_MESSAGE_ROUTED3( @@ -578,7 +589,6 @@ IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBFileChooser_Show, std::string /* suggested_file_name */, bool /* require_user_gesture */) - // PPB_FileRef. IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBFileRef_Create, ppapi::HostResource /* file_system */, @@ -590,19 +600,19 @@ IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFileRef_GetParent, IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBFileRef_MakeDirectory, ppapi::HostResource /* file_ref */, PP_Bool /* make_ancestors */, - uint32_t /* serialized_callback */) + int /* callback_id */) IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBFileRef_Touch, ppapi::HostResource /* file_ref */, PP_Time /* last_access */, PP_Time /* last_modified */, - uint32_t /* serialized_callback */) + int /* callback_id */) IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBFileRef_Delete, ppapi::HostResource /* file_ref */, - uint32_t /* serialized_callback */) + int /* callback_id */) IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBFileRef_Rename, ppapi::HostResource /* file_ref */, ppapi::HostResource /* new_file_ref */, - uint32_t /* serialized_callback */) + int /* callback_id */) // PPB_FileSystem. IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBFileSystem_Create, @@ -892,9 +902,8 @@ IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBInstance_ClearInputEvents, IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBInstance_PostMessage, PP_Instance /* instance */, ppapi::proxy::SerializedVar /* message */) -IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBInstance_LockMouse, - PP_Instance /* instance */, - uint32_t /* serialized_callback */) +IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBInstance_LockMouse, + PP_Instance /* instance */) IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBInstance_UnlockMouse, PP_Instance /* instance */) IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBInstance_ResolveRelativeToDocument, @@ -963,13 +972,11 @@ IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBTextInput_CancelCompositionText, IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBURLLoader_Create, PP_Instance /* instance */, ppapi::HostResource /* result */) -IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBURLLoader_Open, +IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBURLLoader_Open, ppapi::HostResource /* loader */, - ppapi::PPB_URLRequestInfo_Data /* request_data */, - uint32_t /* serialized_callback */) -IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBURLLoader_FollowRedirect, - ppapi::HostResource /* loader */, - uint32_t /* serialized_callback */) + ppapi::PPB_URLRequestInfo_Data /* request_data */) +IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBURLLoader_FollowRedirect, + ppapi::HostResource /* loader */) IPC_SYNC_MESSAGE_ROUTED1_1( PpapiHostMsg_PPBURLLoader_GetResponseInfo, ppapi::HostResource /* loader */, @@ -977,9 +984,8 @@ IPC_SYNC_MESSAGE_ROUTED1_1( IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBURLLoader_ReadResponseBody, ppapi::HostResource /* loader */, int32_t /* bytes_to_read */) -IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBURLLoader_FinishStreamingToFile, - ppapi::HostResource /* loader */, - uint32_t /* serialized_callback */) +IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBURLLoader_FinishStreamingToFile, + ppapi::HostResource /* loader */) IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBURLLoader_Close, ppapi::HostResource /* loader */) IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBURLLoader_GrantUniversalAccess, diff --git a/ppapi/proxy/ppb_file_ref_proxy.cc b/ppapi/proxy/ppb_file_ref_proxy.cc index 4577a12..047a73b 100644 --- a/ppapi/proxy/ppb_file_ref_proxy.cc +++ b/ppapi/proxy/ppb_file_ref_proxy.cc @@ -4,6 +4,9 @@ #include "ppapi/proxy/ppb_file_ref_proxy.h" +#include <map> + +#include "base/bind.h" #include "ppapi/c/pp_errors.h" #include "ppapi/c/ppb_file_ref.h" #include "ppapi/c/private/ppb_proxy_private.h" @@ -40,19 +43,46 @@ class FileRef : public FileRefImpl { virtual int32_t Rename(PP_Resource new_file_ref, PP_CompletionCallback callback) OVERRIDE; + // Executes the pending callback with the given ID. See pending_callbacks_. + void ExecuteCallback(int callback_id, int32_t result); + private: PluginDispatcher* GetDispatcher() const { return PluginDispatcher::GetForResource(this); } + // Adds a callback to the list and returns its ID. Returns 0 if the callback + // is invalid. + int SendCallback(PP_CompletionCallback callback); + + // This class can have any number of out-standing requests with completion + // callbacks, in contrast to most resources which have one possible pending + // callback pending (like a Flush callback). + // + // To keep track of them, assign integer IDs to the callbacks, which is how + // the callback will be identified when it's passed to the host and then + // back here. + int next_callback_id_; + typedef std::map<int, PP_CompletionCallback> PendingCallbackMap; + PendingCallbackMap pending_callbacks_; + DISALLOW_IMPLICIT_CONSTRUCTORS(FileRef); }; FileRef::FileRef(const PPB_FileRef_CreateInfo& info) - : FileRefImpl(FileRefImpl::InitAsProxy(), info) { + : FileRefImpl(FileRefImpl::InitAsProxy(), info), + next_callback_id_(0) { } FileRef::~FileRef() { + // Abort all pending callbacks. Do this by posting a task to avoid reentering + // the plugin's Release() call that probably deleted this object. + for (PendingCallbackMap::iterator i = pending_callbacks_.begin(); + i != pending_callbacks_.end(); ++i) { + MessageLoop::current()->PostTask(FROM_HERE, base::Bind( + i->second.func, i->second.user_data, + static_cast<int32_t>(PP_ERROR_ABORTED))); + } } PP_Resource FileRef::GetParent() { @@ -64,31 +94,44 @@ PP_Resource FileRef::GetParent() { int32_t FileRef::MakeDirectory(PP_Bool make_ancestors, PP_CompletionCallback callback) { + int callback_id = SendCallback(callback); + if (!callback_id) + return PP_ERROR_BADARGUMENT; + GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_MakeDirectory( - API_ID_PPB_FILE_REF, host_resource(), make_ancestors, - GetDispatcher()->callback_tracker().SendCallback(callback))); + API_ID_PPB_FILE_REF, host_resource(), make_ancestors, callback_id)); return PP_OK_COMPLETIONPENDING; } int32_t FileRef::Touch(PP_Time last_access_time, PP_Time last_modified_time, PP_CompletionCallback callback) { + int callback_id = SendCallback(callback); + if (!callback_id) + return PP_ERROR_BADARGUMENT; + GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Touch( API_ID_PPB_FILE_REF, host_resource(), - last_access_time, last_modified_time, - GetDispatcher()->callback_tracker().SendCallback(callback))); + last_access_time, last_modified_time, callback_id)); return PP_OK_COMPLETIONPENDING; } int32_t FileRef::Delete(PP_CompletionCallback callback) { + int callback_id = SendCallback(callback); + if (!callback_id) + return PP_ERROR_BADARGUMENT; + GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Delete( - API_ID_PPB_FILE_REF, host_resource(), - GetDispatcher()->callback_tracker().SendCallback(callback))); + API_ID_PPB_FILE_REF, host_resource(), callback_id)); return PP_OK_COMPLETIONPENDING; } int32_t FileRef::Rename(PP_Resource new_file_ref, PP_CompletionCallback callback) { + int callback_id = SendCallback(callback); + if (!callback_id) + return PP_ERROR_BADARGUMENT; + Resource* new_file_ref_object = PpapiGlobals::Get()->GetResourceTracker()->GetResource(new_file_ref); if (!new_file_ref_object || @@ -97,13 +140,40 @@ int32_t FileRef::Rename(PP_Resource new_file_ref, GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Rename( API_ID_PPB_FILE_REF, host_resource(), - new_file_ref_object->host_resource(), - GetDispatcher()->callback_tracker().SendCallback(callback))); + new_file_ref_object->host_resource(), callback_id)); return PP_OK_COMPLETIONPENDING; } +void FileRef::ExecuteCallback(int callback_id, int32_t result) { + PendingCallbackMap::iterator found = pending_callbacks_.find(callback_id); + if (found == pending_callbacks_.end()) { + // This will happen when the plugin deletes its resource with a pending + // callback. The callback will be locally issued with an ABORTED call while + // the operation may still be pending in the renderer. + return; + } + + // Executing the callback may mutate the callback list. + PP_CompletionCallback callback = found->second; + pending_callbacks_.erase(found); + PP_RunCompletionCallback(&callback, result); +} + +int FileRef::SendCallback(PP_CompletionCallback callback) { + if (!callback.func) + return 0; + + // In extreme cases the IDs may wrap around, so avoid duplicates. + while (pending_callbacks_.find(next_callback_id_) != pending_callbacks_.end()) + next_callback_id_++; + + pending_callbacks_[next_callback_id_] = callback; + return next_callback_id_++; +} + PPB_FileRef_Proxy::PPB_FileRef_Proxy(Dispatcher* dispatcher) - : InterfaceProxy(dispatcher) { + : InterfaceProxy(dispatcher), + callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { } PPB_FileRef_Proxy::~PPB_FileRef_Proxy() { @@ -177,51 +247,67 @@ void PPB_FileRef_Proxy::OnMsgGetParent(const HostResource& host_resource, void PPB_FileRef_Proxy::OnMsgMakeDirectory(const HostResource& host_resource, PP_Bool make_ancestors, - uint32_t serialized_callback) { - EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource); - if (enter.failed()) - return; - PP_CompletionCallback callback = ReceiveCallback(serialized_callback); - int32_t result = enter.object()->MakeDirectory(make_ancestors, callback); - if (result != PP_OK_COMPLETIONPENDING) - PP_RunCompletionCallback(&callback, result); + int callback_id) { + EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter( + host_resource, callback_factory_, + &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id); + if (enter.succeeded()) { + enter.SetResult(enter.object()->MakeDirectory(make_ancestors, + enter.callback())); + } } void PPB_FileRef_Proxy::OnMsgTouch(const HostResource& host_resource, PP_Time last_access, PP_Time last_modified, - uint32_t serialized_callback) { - EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource); - if (enter.failed()) - return; - PP_CompletionCallback callback = ReceiveCallback(serialized_callback); - int32_t result = enter.object()->Touch(last_access, last_modified, callback); - if (result != PP_OK_COMPLETIONPENDING) - PP_RunCompletionCallback(&callback, result); + int callback_id) { + EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter( + host_resource, callback_factory_, + &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id); + if (enter.succeeded()) { + enter.SetResult(enter.object()->Touch(last_access, last_modified, + enter.callback())); + } } void PPB_FileRef_Proxy::OnMsgDelete(const HostResource& host_resource, - uint32_t serialized_callback) { - EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource); - if (enter.failed()) - return; - PP_CompletionCallback callback = ReceiveCallback(serialized_callback); - int32_t result = enter.object()->Delete(callback); - if (result != PP_OK_COMPLETIONPENDING) - PP_RunCompletionCallback(&callback, result); + int callback_id) { + EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter( + host_resource, callback_factory_, + &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id); + if (enter.succeeded()) + enter.SetResult(enter.object()->Delete(enter.callback())); } void PPB_FileRef_Proxy::OnMsgRename(const HostResource& file_ref, const HostResource& new_file_ref, - uint32_t serialized_callback) { - EnterHostFromHostResource<PPB_FileRef_API> enter(file_ref); - if (enter.failed()) - return; - PP_CompletionCallback callback = ReceiveCallback(serialized_callback); - int32_t result = enter.object()->Rename(new_file_ref.host_resource(), - callback); - if (result != PP_OK_COMPLETIONPENDING) - PP_RunCompletionCallback(&callback, result); + int callback_id) { + EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter( + file_ref, callback_factory_, + &PPB_FileRef_Proxy::OnCallbackCompleteInHost, file_ref, callback_id); + if (enter.succeeded()) { + enter.SetResult(enter.object()->Rename(new_file_ref.host_resource(), + enter.callback())); + } +} + +void PPB_FileRef_Proxy::OnMsgCallbackComplete( + const HostResource& host_resource, + int callback_id, + int32_t result) { + // Forward the callback info to the plugin resource. + EnterPluginFromHostResource<PPB_FileRef_API> enter(host_resource); + if (enter.succeeded()) + static_cast<FileRef*>(enter.object())->ExecuteCallback(callback_id, result); +} + +void PPB_FileRef_Proxy::OnCallbackCompleteInHost( + int32_t result, + const HostResource& host_resource, + int callback_id) { + // Execute OnMsgCallbackComplete in the plugin process. + Send(new PpapiMsg_PPBFileRef_CallbackComplete( + API_ID_PPB_FILE_REF, host_resource, callback_id, result)); } } // namespace proxy diff --git a/ppapi/proxy/ppb_file_ref_proxy.h b/ppapi/proxy/ppb_file_ref_proxy.h index de83e1c..07549c4 100644 --- a/ppapi/proxy/ppb_file_ref_proxy.h +++ b/ppapi/proxy/ppb_file_ref_proxy.h @@ -11,7 +11,9 @@ #include "ppapi/c/pp_module.h" #include "ppapi/c/pp_resource.h" #include "ppapi/c/pp_time.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/proxy/interface_proxy.h" +#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" struct PPB_FileRef_Dev; @@ -59,23 +61,35 @@ class PPB_FileRef_Proxy : public InterfaceProxy { private: // Message handlers. - void OnMsgCreate(const ppapi::HostResource& file_system, + void OnMsgCreate(const HostResource& file_system, const std::string& path, PPB_FileRef_CreateInfo* result); - void OnMsgGetParent(const ppapi::HostResource& host_resource, + void OnMsgGetParent(const HostResource& host_resource, PPB_FileRef_CreateInfo* result); - void OnMsgMakeDirectory(const ppapi::HostResource& host_resource, + void OnMsgMakeDirectory(const HostResource& host_resource, PP_Bool make_ancestors, - uint32_t serialized_callback); - void OnMsgTouch(const ppapi::HostResource& host_resource, + int callback_id); + void OnMsgTouch(const HostResource& host_resource, PP_Time last_access, PP_Time last_modified, - uint32_t serialized_callback); - void OnMsgDelete(const ppapi::HostResource& host_resource, - uint32_t serialized_callback); - void OnMsgRename(const ppapi::HostResource& file_ref, - const ppapi::HostResource& new_file_ref, - uint32_t serialized_callback); + int callback_id); + void OnMsgDelete(const HostResource& host_resource, + int callback_id); + void OnMsgRename(const HostResource& file_ref, + const HostResource& new_file_ref, + int callback_id); + + // Host -> Plugin message handlers. + void OnMsgCallbackComplete(const HostResource& host_resource, + int callback_id, + int32_t result); + + void OnCallbackCompleteInHost(int32_t result, + const HostResource& host_resource, + int callback_id); + + pp::CompletionCallbackFactory<PPB_FileRef_Proxy, + ProxyNonThreadSafeRefCount> callback_factory_; DISALLOW_COPY_AND_ASSIGN(PPB_FileRef_Proxy); }; diff --git a/ppapi/proxy/ppb_instance_proxy.cc b/ppapi/proxy/ppb_instance_proxy.cc index 998ae8b..28bb17e 100644 --- a/ppapi/proxy/ppb_instance_proxy.cc +++ b/ppapi/proxy/ppb_instance_proxy.cc @@ -9,6 +9,7 @@ #include "ppapi/c/ppb_instance.h" #include "ppapi/c/ppb_messaging.h" #include "ppapi/c/ppb_mouse_lock.h" +#include "ppapi/proxy/enter_proxy.h" #include "ppapi/proxy/host_dispatcher.h" #include "ppapi/proxy/plugin_dispatcher.h" #include "ppapi/proxy/ppapi_messages.h" @@ -41,7 +42,8 @@ InterfaceProxy* CreateInstanceProxy(Dispatcher* dispatcher) { } // namespace PPB_Instance_Proxy::PPB_Instance_Proxy(Dispatcher* dispatcher) - : InterfaceProxy(dispatcher) { + : InterfaceProxy(dispatcher), + callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { } PPB_Instance_Proxy::~PPB_Instance_Proxy() { @@ -68,6 +70,7 @@ bool PPB_Instance_Proxy::OnMessageReceived(const IPC::Message& msg) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(PPB_Instance_Proxy, msg) + // Plugin -> Host messages. IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetWindowObject, OnMsgGetWindowObject) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetOwnerElementObject, @@ -112,6 +115,11 @@ bool PPB_Instance_Proxy::OnMessageReceived(const IPC::Message& msg) { OnMsgGetDocumentURL) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetPluginInstanceURL, OnMsgGetPluginInstanceURL) + + // Host -> Plugin messages. + IPC_MESSAGE_HANDLER(PpapiMsg_PPBInstance_MouseLockComplete, + OnMsgMouseLockComplete) + IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -362,8 +370,17 @@ int32_t PPB_Instance_Proxy::LockMouse(PP_Instance instance, if (!callback.func) return PP_ERROR_BADARGUMENT; + // Save the mouse callback on the instance data. + InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())-> + GetInstanceData(instance); + if (!data) + return PP_ERROR_BADARGUMENT; + if (data->mouse_lock_callback.func) + return PP_ERROR_INPROGRESS; // Already have a pending callback. + data->mouse_lock_callback = callback; + dispatcher()->Send(new PpapiHostMsg_PPBInstance_LockMouse( - API_ID_PPB_INSTANCE, instance, SendCallback(callback))); + API_ID_PPB_INSTANCE, instance)); return PP_OK_COMPLETIONPENDING; } @@ -514,15 +531,12 @@ void PPB_Instance_Proxy::OnMsgPostMessage(PP_Instance instance, enter.functions()->PostMessage(instance, message.Get(dispatcher())); } -void PPB_Instance_Proxy::OnMsgLockMouse(PP_Instance instance, - uint32_t serialized_callback) { - EnterFunctionNoLock<PPB_Instance_FunctionAPI> enter(instance, true); - if (enter.failed()) - return; - PP_CompletionCallback callback = ReceiveCallback(serialized_callback); - int32_t result = enter.functions()->LockMouse(instance, callback); - if (result != PP_OK_COMPLETIONPENDING) - PP_RunCompletionCallback(&callback, result); +void PPB_Instance_Proxy::OnMsgLockMouse(PP_Instance instance) { + EnterHostFunctionForceCallback<PPB_Instance_FunctionAPI> enter( + instance, callback_factory_, + &PPB_Instance_Proxy::MouseLockCompleteInHost, instance); + if (enter.succeeded()) + enter.SetResult(enter.functions()->LockMouse(instance, enter.callback())); } void PPB_Instance_Proxy::OnMsgUnlockMouse(PP_Instance instance) { @@ -580,5 +594,25 @@ void PPB_Instance_Proxy::OnMsgGetPluginInstanceURL( } } +void PPB_Instance_Proxy::OnMsgMouseLockComplete(PP_Instance instance, + int32_t result) { + // Save the mouse callback on the instance data. + InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())-> + GetInstanceData(instance); + if (!data) + return; // Instance was probably deleted. + if (!data->mouse_lock_callback.func) { + NOTREACHED(); + return; + } + PP_RunAndClearCompletionCallback(&data->mouse_lock_callback, result); +} + +void PPB_Instance_Proxy::MouseLockCompleteInHost(int32_t result, + PP_Instance instance) { + dispatcher()->Send(new PpapiMsg_PPBInstance_MouseLockComplete( + API_ID_PPB_INSTANCE, instance, result)); +} + } // namespace proxy } // namespace ppapi diff --git a/ppapi/proxy/ppb_instance_proxy.h b/ppapi/proxy/ppb_instance_proxy.h index 8197886..5de8f9e 100644 --- a/ppapi/proxy/ppb_instance_proxy.h +++ b/ppapi/proxy/ppb_instance_proxy.h @@ -8,12 +8,19 @@ #include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_resource.h" #include "ppapi/c/pp_var.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/proxy/interface_proxy.h" +#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" #include "ppapi/shared_impl/function_group_base.h" #include "ppapi/shared_impl/host_resource.h" #include "ppapi/shared_impl/instance_impl.h" #include "ppapi/thunk/ppb_instance_api.h" +// Windows headers interfere with this file. +#ifdef PostMessage +#undef PostMessage +#endif + namespace ppapi { namespace proxy { @@ -98,7 +105,7 @@ class PPB_Instance_Proxy : public InterfaceProxy, static const ApiID kApiID = API_ID_PPB_INSTANCE; private: - // Message handlers. + // Plugin -> Host message handlers. void OnMsgGetWindowObject(PP_Instance instance, SerializedVarReturnValue result); void OnMsgGetOwnerElementObject(PP_Instance instance, @@ -139,8 +146,7 @@ class PPB_Instance_Proxy : public InterfaceProxy, uint32_t event_classes); void OnMsgPostMessage(PP_Instance instance, SerializedVarReceiveInput message); - void OnMsgLockMouse(PP_Instance instance, - uint32_t serialized_callback); + void OnMsgLockMouse(PP_Instance instance); void OnMsgUnlockMouse(PP_Instance instance); void OnMsgResolveRelativeToDocument(PP_Instance instance, SerializedVarReceiveInput relative, @@ -155,6 +161,14 @@ class PPB_Instance_Proxy : public InterfaceProxy, SerializedVarReturnValue result); void OnMsgGetPluginInstanceURL(PP_Instance instance, SerializedVarReturnValue result); + + // Host -> Plugin message handlers. + void OnMsgMouseLockComplete(PP_Instance instance, int32_t result); + + void MouseLockCompleteInHost(int32_t result, PP_Instance instance); + + pp::CompletionCallbackFactory<PPB_Instance_Proxy, + ProxyNonThreadSafeRefCount> callback_factory_; }; } // namespace proxy diff --git a/ppapi/proxy/ppb_url_loader_proxy.cc b/ppapi/proxy/ppb_url_loader_proxy.cc index 6fb43bd..6bd7d87 100644 --- a/ppapi/proxy/ppb_url_loader_proxy.cc +++ b/ppapi/proxy/ppb_url_loader_proxy.cc @@ -111,7 +111,10 @@ class URLLoader : public Resource, public PPB_URLLoader_API { void UpdateProgress(const PPBURLLoader_UpdateProgress_Params& params); // Called when the browser responds to our ReadResponseBody request. - void ReadResponseBodyAck(int32 result, const std::string& data); + void ReadResponseBodyAck(int32_t result, const std::string& data); + + // Called when any callback other than the read callback has been executed. + void CallbackComplete(int32_t result); private: // Reads the give bytes out of the buffer_, placing them in the given output @@ -131,9 +134,12 @@ class URLLoader : public Resource, public PPB_URLLoader_API { int64_t bytes_received_; int64_t total_bytes_to_be_received_; - // When an asynchronous read is pending, this will contain the callback and - // the buffer to put the data. - PP_CompletionCallback current_read_callback_; + // Current completion callback for the current phase of loading. We have only + // one thing (open, follow redirect, read, etc.) outstanding at once. + PP_CompletionCallback current_callback_; + + // When an asynchronous read is pending, this will contain the buffer to put + // the data. The current_callback_ will identify the read callback. void* current_read_buffer_; int32_t current_read_buffer_size_; @@ -155,7 +161,7 @@ URLLoader::URLLoader(const HostResource& resource) total_bytes_to_be_sent_(-1), bytes_received_(-1), total_bytes_to_be_received_(-1), - current_read_callback_(PP_MakeCompletionCallback(NULL, NULL)), + current_callback_(PP_MakeCompletionCallback(NULL, NULL)), current_read_buffer_(NULL), current_read_buffer_size_(0), response_info_(0) { @@ -163,11 +169,11 @@ URLLoader::URLLoader(const HostResource& resource) URLLoader::~URLLoader() { // Always need to fire completion callbacks to prevent a leak in the plugin. - if (current_read_callback_.func) { + if (current_callback_.func) { // TODO(brettw) the callbacks at this level should be refactored with a // more automatic tracking system like we have in the renderer. MessageLoop::current()->PostTask(FROM_HERE, base::Bind( - current_read_callback_.func, current_read_callback_.user_data, + current_callback_.func, current_callback_.user_data, static_cast<int32_t>(PP_ERROR_ABORTED))); } @@ -185,20 +191,28 @@ int32_t URLLoader::Open(PP_Resource request_id, if (enter.failed()) return PP_ERROR_BADRESOURCE; - // TODO(brettw) http://crbug.com/86279: SendCallback doesn't ensure that - // the proper callback semantics happen if the object is deleted. + if (current_callback_.func) + return PP_ERROR_INPROGRESS; + + if (!callback.func) + return PP_ERROR_BLOCKS_MAIN_THREAD; + current_callback_ = callback; + GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_Open( - API_ID_PPB_URL_LOADER, host_resource(), enter.object()->GetData(), - GetDispatcher()->callback_tracker().SendCallback(callback))); + API_ID_PPB_URL_LOADER, host_resource(), enter.object()->GetData())); return PP_OK_COMPLETIONPENDING; } int32_t URLLoader::FollowRedirect(PP_CompletionCallback callback) { - // TODO(brettw) http://crbug.com/86279: SendCallback doesn't ensure that - // the proper callback semantics happen if the object is deleted. + if (current_callback_.func) + return PP_ERROR_INPROGRESS; + + if (!callback.func) + return PP_ERROR_BLOCKS_MAIN_THREAD; + current_callback_ = callback; + GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_FollowRedirect( - API_ID_PPB_URL_LOADER, host_resource(), - GetDispatcher()->callback_tracker().SendCallback(callback))); + API_ID_PPB_URL_LOADER, host_resource())); return PP_OK_COMPLETIONPENDING; } @@ -249,7 +263,7 @@ int32_t URLLoader::ReadResponseBody(void* buffer, PP_CompletionCallback callback) { if (!buffer || bytes_to_read <= 0) return PP_ERROR_BADARGUMENT; // Must specify an output buffer. - if (current_read_callback_.func) + if (current_callback_.func) return PP_ERROR_INPROGRESS; // Can only have one request pending. // Currently we don't support sync calls to read. We'll need to revisit @@ -264,7 +278,7 @@ int32_t URLLoader::ReadResponseBody(void* buffer, return bytes_to_read; } - current_read_callback_ = callback; + current_callback_ = callback; current_read_buffer_ = buffer; current_read_buffer_size_ = bytes_to_read; @@ -274,9 +288,15 @@ int32_t URLLoader::ReadResponseBody(void* buffer, } int32_t URLLoader::FinishStreamingToFile(PP_CompletionCallback callback) { + if (current_callback_.func) + return PP_ERROR_INPROGRESS; + + if (!callback.func) + return PP_ERROR_BLOCKS_MAIN_THREAD; + current_callback_ = callback; + GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_FinishStreamingToFile( - API_ID_PPB_URL_LOADER, host_resource(), - GetDispatcher()->callback_tracker().SendCallback(callback))); + API_ID_PPB_URL_LOADER, host_resource())); return PP_OK_COMPLETIONPENDING; } @@ -306,7 +326,7 @@ void URLLoader::UpdateProgress( } void URLLoader::ReadResponseBodyAck(int32 result, const std::string& data) { - if (!current_read_callback_.func || !current_read_buffer_) { + if (!current_callback_.func || !current_read_buffer_) { NOTREACHED(); return; } @@ -327,7 +347,11 @@ void URLLoader::ReadResponseBodyAck(int32 result, const std::string& data) { // The plugin should be able to make a new request from their callback, so // we have to clear our copy first. - PP_RunAndClearCompletionCallback(¤t_read_callback_, result); + PP_RunAndClearCompletionCallback(¤t_callback_, result); +} + +void URLLoader::CallbackComplete(int32_t result) { + PP_RunAndClearCompletionCallback(¤t_callback_, result); } void URLLoader::PopBuffer(void* output_buffer, int32_t output_size) { @@ -439,37 +463,27 @@ void PPB_URLLoader_Proxy::OnMsgCreate(PP_Instance instance, } void PPB_URLLoader_Proxy::OnMsgOpen(const HostResource& loader, - const PPB_URLRequestInfo_Data& data, - uint32_t serialized_callback) { - // Have to be careful to always issue the callback, so don't return early. - EnterHostFromHostResource<PPB_URLLoader_API> enter(loader); + const PPB_URLRequestInfo_Data& data) { + EnterHostFromHostResourceForceCallback<PPB_URLLoader_API> enter( + loader, callback_factory_, &PPB_URLLoader_Proxy::OnCallback, loader); thunk::EnterResourceCreation enter_creation(loader.instance()); + if (enter.failed() || enter_creation.failed()) + return; - PP_CompletionCallback callback = ReceiveCallback(serialized_callback); - - int32_t result = PP_ERROR_BADRESOURCE; - if (enter.succeeded() && enter_creation.succeeded()) { - ScopedPPResource request_resource( - ScopedPPResource::PassRef(), - enter_creation.functions()->CreateURLRequestInfo(loader.instance(), - data)); - result = enter.object()->Open(request_resource, callback); - } - if (result != PP_OK_COMPLETIONPENDING) - PP_RunCompletionCallback(&callback, result); + ScopedPPResource request_resource( + ScopedPPResource::PassRef(), + enter_creation.functions()->CreateURLRequestInfo(loader.instance(), + data)); + enter.SetResult(enter.object()->Open(request_resource, enter.callback())); // TODO(brettw) bug 73236 register for the status callbacks. } void PPB_URLLoader_Proxy::OnMsgFollowRedirect( - const HostResource& loader, - uint32_t serialized_callback) { - EnterHostFromHostResource<PPB_URLLoader_API> enter(loader); - PP_CompletionCallback callback = ReceiveCallback(serialized_callback); - int32_t result = PP_ERROR_BADRESOURCE; + const HostResource& loader) { + EnterHostFromHostResourceForceCallback<PPB_URLLoader_API> enter( + loader, callback_factory_, &PPB_URLLoader_Proxy::OnCallback, loader); if (enter.succeeded()) - result = enter.object()->FollowRedirect(callback); - if (result != PP_OK_COMPLETIONPENDING) - PP_RunCompletionCallback(&callback, result); + enter.SetResult(enter.object()->FollowRedirect(enter.callback())); } void PPB_URLLoader_Proxy::OnMsgGetResponseInfo(const HostResource& loader, @@ -524,15 +538,11 @@ void PPB_URLLoader_Proxy::OnMsgReadResponseBody( } void PPB_URLLoader_Proxy::OnMsgFinishStreamingToFile( - const HostResource& loader, - uint32_t serialized_callback) { - EnterHostFromHostResource<PPB_URLLoader_API> enter(loader); - PP_CompletionCallback callback = ReceiveCallback(serialized_callback); - int32_t result = PP_ERROR_BADRESOURCE; - if (enter.succeeded()) - result = enter.object()->FinishStreamingToFile(callback); - if (result != PP_OK_COMPLETIONPENDING) - PP_RunCompletionCallback(&callback, result); + const HostResource& loader) { + EnterHostFromHostResourceForceCallback<PPB_URLLoader_API> enter( + loader, callback_factory_, &PPB_URLLoader_Proxy::OnCallback, loader); + if (enter.failed()) + enter.SetResult(enter.object()->FinishStreamingToFile(enter.callback()));; } void PPB_URLLoader_Proxy::OnMsgClose(const HostResource& loader) { @@ -566,6 +576,15 @@ void PPB_URLLoader_Proxy::OnMsgReadResponseBodyAck( static_cast<URLLoader*>(enter.object())->ReadResponseBodyAck(result, data); } +// Called in the plugin. +void PPB_URLLoader_Proxy::OnMsgCallbackComplete( + const HostResource& host_resource, + int32_t result) { + EnterPluginFromHostResource<PPB_URLLoader_API> enter(host_resource); + if (enter.succeeded()) + static_cast<URLLoader*>(enter.object())->CallbackComplete(result); +} + void PPB_URLLoader_Proxy::OnReadCallback(int32_t result, ReadCallbackInfo* info) { int32_t bytes_read = 0; @@ -579,5 +598,11 @@ void PPB_URLLoader_Proxy::OnReadCallback(int32_t result, delete info; } +void PPB_URLLoader_Proxy::OnCallback(int32_t result, + const HostResource& resource) { + dispatcher()->Send(new PpapiMsg_PPBURLLoader_CallbackComplete( + API_ID_PPB_URL_LOADER, resource, result)); +} + } // namespace proxy } // namespace ppapi diff --git a/ppapi/proxy/ppb_url_loader_proxy.h b/ppapi/proxy/ppb_url_loader_proxy.h index 855a965..e13b1a3 100644 --- a/ppapi/proxy/ppb_url_loader_proxy.h +++ b/ppapi/proxy/ppb_url_loader_proxy.h @@ -41,7 +41,7 @@ class PPB_URLLoader_Proxy : public InterfaceProxy { // function allows the proxy for DocumentLoad to create the correct plugin // proxied info for the given browser-supplied URLLoader resource ID. static PP_Resource TrackPluginResource( - const ppapi::HostResource& url_loader_resource); + const HostResource& url_loader_resource); // InterfaceProxy implementation. virtual bool OnMessageReceived(const IPC::Message& msg); @@ -60,32 +60,33 @@ class PPB_URLLoader_Proxy : public InterfaceProxy { // Plugin->renderer message handlers. void OnMsgCreate(PP_Instance instance, - ppapi::HostResource* result); - void OnMsgOpen(const ppapi::HostResource& loader, - const PPB_URLRequestInfo_Data& data, - uint32_t serialized_callback); - void OnMsgFollowRedirect(const ppapi::HostResource& loader, - uint32_t serialized_callback); - void OnMsgGetResponseInfo(const ppapi::HostResource& loader, - ppapi::HostResource* result); - void OnMsgReadResponseBody(const ppapi::HostResource& loader, + HostResource* result); + void OnMsgOpen(const HostResource& loader, + const PPB_URLRequestInfo_Data& data); + void OnMsgFollowRedirect(const HostResource& loader); + void OnMsgGetResponseInfo(const HostResource& loader, + HostResource* result); + void OnMsgReadResponseBody(const HostResource& loader, int32_t bytes_to_read); - void OnMsgFinishStreamingToFile(const ppapi::HostResource& loader, - uint32_t serialized_callback); - void OnMsgClose(const ppapi::HostResource& loader); - void OnMsgGrantUniversalAccess(const ppapi::HostResource& loader); + void OnMsgFinishStreamingToFile(const HostResource& loader); + void OnMsgClose(const HostResource& loader); + void OnMsgGrantUniversalAccess(const HostResource& loader); // Renderer->plugin message handlers. void OnMsgUpdateProgress( const PPBURLLoader_UpdateProgress_Params& params); - void OnMsgReadResponseBodyAck(const ppapi::HostResource& pp_resource, + void OnMsgReadResponseBodyAck(const HostResource& host_resource, int32_t result, const std::string& data); + void OnMsgCallbackComplete(const HostResource& host_resource, int32_t result); // Handles callbacks for read complete messages. Takes ownership of the info // pointer. void OnReadCallback(int32_t result, ReadCallbackInfo* info); + // Handles callback for everything but reads. + void OnCallback(int32_t result, const HostResource& resource); + pp::CompletionCallbackFactory<PPB_URLLoader_Proxy, ProxyNonThreadSafeRefCount> callback_factory_; diff --git a/ppapi/thunk/ppb_instance_api.h b/ppapi/thunk/ppb_instance_api.h index 4a41502..21187c4 100644 --- a/ppapi/thunk/ppb_instance_api.h +++ b/ppapi/thunk/ppb_instance_api.h @@ -13,6 +13,11 @@ #include "ppapi/c/private/ppb_instance_private.h" #include "ppapi/shared_impl/api_id.h" +// Windows headers interfere with this file. +#ifdef PostMessage +#undef PostMessage +#endif + namespace ppapi { namespace thunk { |