blob: a49f4ff942773737777851c549ba042509f5d270 [file] [log] [blame]
[email protected]bbc49122011-12-29 20:16:501// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ppapi/shared_impl/tracked_callback.h"
6
7#include "base/bind.h"
8#include "base/compiler_specific.h"
9#include "base/logging.h"
10#include "base/message_loop.h"
11#include "ppapi/c/pp_completion_callback.h"
12#include "ppapi/c/pp_errors.h"
13#include "ppapi/shared_impl/callback_tracker.h"
14#include "ppapi/shared_impl/ppapi_globals.h"
15#include "ppapi/shared_impl/resource.h"
16
17namespace ppapi {
18
19// TrackedCallback -------------------------------------------------------------
20
21// Note: don't keep a Resource* since it may go out of scope before us.
22TrackedCallback::TrackedCallback(
23 Resource* resource,
24 const PP_CompletionCallback& callback)
25 : ALLOW_THIS_IN_INITIALIZER_LIST(abort_impl_factory_(this)),
26 resource_id_(resource->pp_resource()),
27 completed_(false),
28 aborted_(false),
29 callback_(callback) {
30 tracker_ = PpapiGlobals::Get()->GetCallbackTrackerForInstance(
31 resource->pp_instance()),
32 tracker_->Add(make_scoped_refptr(this));
33}
34
35TrackedCallback::~TrackedCallback() {
36}
37
38void TrackedCallback::Abort() {
39 if (!completed()) {
40 aborted_ = true;
41 Run(PP_ERROR_ABORTED);
42 }
43}
44
45void TrackedCallback::PostAbort() {
46 if (!completed()) {
47 aborted_ = true;
48 // Post a task for the abort (only if necessary).
49 if (!abort_impl_factory_.HasWeakPtrs()) {
50 MessageLoop::current()->PostTask(
51 FROM_HERE,
52 base::Bind(&TrackedCallback::Abort,
53 abort_impl_factory_.GetWeakPtr()));
54 }
55 }
56}
57
58void TrackedCallback::Run(int32_t result) {
59 if (!completed()) {
60 // Cancel any pending calls.
61 abort_impl_factory_.InvalidateWeakPtrs();
62
63 // Copy |callback_| and look at |aborted()| now, since |MarkAsCompleted()|
64 // may delete us.
65 PP_CompletionCallback callback = callback_;
66 if (aborted())
67 result = PP_ERROR_ABORTED;
68
69 // Do this before running the callback in case of reentrancy (which
70 // shouldn't happen, but avoid strange failures).
71 MarkAsCompleted();
72 PP_RunCompletionCallback(&callback, result);
73 }
74}
75
[email protected]19bb6722012-01-04 22:53:0876// static
77bool TrackedCallback::IsPending(
78 const scoped_refptr<TrackedCallback>& callback) {
79 if (!callback.get())
80 return false;
81 return !callback->completed();
82}
83
84// static
85void TrackedCallback::ClearAndRun(scoped_refptr<TrackedCallback>* callback,
86 int32_t result) {
87 scoped_refptr<TrackedCallback> temp;
88 temp.swap(*callback);
89 temp->Run(result);
90}
91
92// static
93void TrackedCallback::ClearAndAbort(scoped_refptr<TrackedCallback>* callback) {
94 scoped_refptr<TrackedCallback> temp;
95 temp.swap(*callback);
96 temp->Abort();
97}
98
[email protected]bbc49122011-12-29 20:16:5099void TrackedCallback::MarkAsCompleted() {
100 DCHECK(!completed());
101
102 // We will be removed; maintain a reference to ensure we won't be deleted
103 // until we're done.
104 scoped_refptr<TrackedCallback> thiz = this;
105 completed_ = true;
106 tracker_->Remove(thiz);
107 tracker_ = NULL;
108}
109
110} // namespace ppapi