| Index: ppapi/proxy/ppb_var_deprecated_proxy.cc
|
| ===================================================================
|
| --- ppapi/proxy/ppb_var_deprecated_proxy.cc (revision 82683)
|
| +++ ppapi/proxy/ppb_var_deprecated_proxy.cc (working copy)
|
| @@ -7,6 +7,8 @@
|
| #include <stdlib.h> // For malloc
|
|
|
| #include "base/logging.h"
|
| +#include "base/message_loop.h"
|
| +#include "base/task.h"
|
| #include "ppapi/c/dev/ppb_var_deprecated.h"
|
| #include "ppapi/c/pp_var.h"
|
| #include "ppapi/c/ppb_core.h"
|
| @@ -296,7 +298,8 @@
|
| PPB_Var_Deprecated_Proxy::PPB_Var_Deprecated_Proxy(
|
| Dispatcher* dispatcher,
|
| const void* target_interface)
|
| - : InterfaceProxy(dispatcher, target_interface) {
|
| + : InterfaceProxy(dispatcher, target_interface),
|
| + task_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
|
| }
|
|
|
| PPB_Var_Deprecated_Proxy::~PPB_Var_Deprecated_Proxy() {
|
| @@ -361,10 +364,27 @@
|
| }
|
|
|
| void PPB_Var_Deprecated_Proxy::OnMsgReleaseObject(int64 object_id) {
|
| - PP_Var var;
|
| - var.type = PP_VARTYPE_OBJECT;
|
| - var.value.as_id = object_id;
|
| - ppb_var_target()->Release(var);
|
| + // Ok, so this is super subtle.
|
| + // When the browser side sends a sync IPC message that returns a var, and the
|
| + // plugin wants to give ownership of that var to the browser, dropping all
|
| + // references, it may call ReleaseObject right after returning the result.
|
| + // However, the IPC system doesn't enforce strict ordering of messages in that
|
| + // case, where a message that is set to unblock (e.g. a sync message, or in
|
| + // our case all messages coming from the plugin) that is sent *after* the
|
| + // result may be dispatched on the browser side *before* the sync send
|
| + // returned (see ipc_sync_channel.cc). In this case, that means it could
|
| + // release the object before it is AddRef'ed on the browser side.
|
| + // To work around this, we post a task here, that will not execute before
|
| + // control goes back to the main message loop, that will ensure the sync send
|
| + // has returned and the browser side can take its reference before we Release.
|
| + // Note: if the instance is gone by the time the task is executed, then it
|
| + // will Release the objects itself and this Release will be a NOOP (aside of a
|
| + // spurious warning).
|
| + // TODO(piman): See if we can fix the IPC code to enforce strict ordering, and
|
| + // then remove this.
|
| + MessageLoop::current()->PostNonNestableTask(FROM_HERE,
|
| + task_factory_.NewRunnableMethod(
|
| + &PPB_Var_Deprecated_Proxy::DoReleaseObject, object_id));
|
| }
|
|
|
| void PPB_Var_Deprecated_Proxy::OnMsgHasProperty(
|
| @@ -492,5 +512,12 @@
|
| static_cast<HostDispatcher*>(dispatcher())->set_allow_plugin_reentrancy();
|
| }
|
|
|
| +void PPB_Var_Deprecated_Proxy::DoReleaseObject(int64 object_id) {
|
| + PP_Var var;
|
| + var.type = PP_VARTYPE_OBJECT;
|
| + var.value.as_id = object_id;
|
| + ppb_var_target()->Release(var);
|
| +}
|
| +
|
| } // namespace proxy
|
| } // namespace pp
|
|
|