1*6777b538SAndroid Build Coastguard Worker // Copyright 2018 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_WIN_POST_ASYNC_RESULTS_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_WIN_POST_ASYNC_RESULTS_H_
7*6777b538SAndroid Build Coastguard Worker
8*6777b538SAndroid Build Coastguard Worker #include <unknwn.h>
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Worker #include <windows.foundation.h>
11*6777b538SAndroid Build Coastguard Worker #include <wrl/async.h>
12*6777b538SAndroid Build Coastguard Worker #include <wrl/client.h>
13*6777b538SAndroid Build Coastguard Worker
14*6777b538SAndroid Build Coastguard Worker #include <type_traits>
15*6777b538SAndroid Build Coastguard Worker #include <utility>
16*6777b538SAndroid Build Coastguard Worker
17*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/task/bind_post_task.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/task/sequenced_task_runner.h"
23*6777b538SAndroid Build Coastguard Worker
24*6777b538SAndroid Build Coastguard Worker namespace base {
25*6777b538SAndroid Build Coastguard Worker namespace win {
26*6777b538SAndroid Build Coastguard Worker
27*6777b538SAndroid Build Coastguard Worker namespace internal {
28*6777b538SAndroid Build Coastguard Worker
29*6777b538SAndroid Build Coastguard Worker // Utility function to pretty print enum values.
ToCString(AsyncStatus async_status)30*6777b538SAndroid Build Coastguard Worker constexpr const char* ToCString(AsyncStatus async_status) {
31*6777b538SAndroid Build Coastguard Worker switch (async_status) {
32*6777b538SAndroid Build Coastguard Worker case AsyncStatus::Started:
33*6777b538SAndroid Build Coastguard Worker return "AsyncStatus::Started";
34*6777b538SAndroid Build Coastguard Worker case AsyncStatus::Completed:
35*6777b538SAndroid Build Coastguard Worker return "AsyncStatus::Completed";
36*6777b538SAndroid Build Coastguard Worker case AsyncStatus::Canceled:
37*6777b538SAndroid Build Coastguard Worker return "AsyncStatus::Canceled";
38*6777b538SAndroid Build Coastguard Worker case AsyncStatus::Error:
39*6777b538SAndroid Build Coastguard Worker return "AsyncStatus::Error";
40*6777b538SAndroid Build Coastguard Worker }
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker NOTREACHED();
43*6777b538SAndroid Build Coastguard Worker return "";
44*6777b538SAndroid Build Coastguard Worker }
45*6777b538SAndroid Build Coastguard Worker
46*6777b538SAndroid Build Coastguard Worker template <typename T>
47*6777b538SAndroid Build Coastguard Worker using IAsyncOperationT = typename ABI::Windows::Foundation::IAsyncOperation<T>;
48*6777b538SAndroid Build Coastguard Worker
49*6777b538SAndroid Build Coastguard Worker template <typename T>
50*6777b538SAndroid Build Coastguard Worker using IAsyncOperationCompletedHandlerT =
51*6777b538SAndroid Build Coastguard Worker typename base::OnceCallback<void(IAsyncOperationT<T>*, AsyncStatus)>;
52*6777b538SAndroid Build Coastguard Worker
53*6777b538SAndroid Build Coastguard Worker template <typename T>
54*6777b538SAndroid Build Coastguard Worker using AsyncAbiT = typename ABI::Windows::Foundation::Internal::GetAbiType<
55*6777b538SAndroid Build Coastguard Worker typename IAsyncOperationT<T>::TResult_complex>::type;
56*6777b538SAndroid Build Coastguard Worker
57*6777b538SAndroid Build Coastguard Worker // Compile time switch to decide what container to use for the async results for
58*6777b538SAndroid Build Coastguard Worker // |T|. Depends on whether the underlying Abi type is a pointer to IUnknown or
59*6777b538SAndroid Build Coastguard Worker // not. It queries the internals of Windows::Foundation to obtain this
60*6777b538SAndroid Build Coastguard Worker // information.
61*6777b538SAndroid Build Coastguard Worker template <typename T>
62*6777b538SAndroid Build Coastguard Worker using AsyncResultsT = std::conditional_t<
63*6777b538SAndroid Build Coastguard Worker std::is_convertible_v<AsyncAbiT<T>, IUnknown*>,
64*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::ComPtr<std::remove_pointer_t<AsyncAbiT<T>>>,
65*6777b538SAndroid Build Coastguard Worker AsyncAbiT<T>>;
66*6777b538SAndroid Build Coastguard Worker
67*6777b538SAndroid Build Coastguard Worker // Fetches the result of the provided |async_operation| and corresponding
68*6777b538SAndroid Build Coastguard Worker // |async_status| and assigns that value to |result|. Returns an HRESULT
69*6777b538SAndroid Build Coastguard Worker // indicating the success of the operation.
70*6777b538SAndroid Build Coastguard Worker template <typename T>
GetAsyncResultsT(IAsyncOperationT<T> * async_operation,AsyncStatus async_status,AsyncResultsT<T> * results)71*6777b538SAndroid Build Coastguard Worker HRESULT GetAsyncResultsT(IAsyncOperationT<T>* async_operation,
72*6777b538SAndroid Build Coastguard Worker AsyncStatus async_status,
73*6777b538SAndroid Build Coastguard Worker AsyncResultsT<T>* results) {
74*6777b538SAndroid Build Coastguard Worker if (async_status == AsyncStatus::Completed) {
75*6777b538SAndroid Build Coastguard Worker // To expose |results| to GetResults as the expected type, this call first
76*6777b538SAndroid Build Coastguard Worker // dereferences |results| from ComPtr<T>* or T* to ComPtr<T> or T
77*6777b538SAndroid Build Coastguard Worker // respectively, then requests the address, converting to T** or T*
78*6777b538SAndroid Build Coastguard Worker // respectively.
79*6777b538SAndroid Build Coastguard Worker HRESULT hr = async_operation->GetResults(&(*results));
80*6777b538SAndroid Build Coastguard Worker if (FAILED(hr))
81*6777b538SAndroid Build Coastguard Worker *results = AsyncResultsT<T>{};
82*6777b538SAndroid Build Coastguard Worker return hr;
83*6777b538SAndroid Build Coastguard Worker }
84*6777b538SAndroid Build Coastguard Worker
85*6777b538SAndroid Build Coastguard Worker *results = AsyncResultsT<T>{};
86*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> async_info;
87*6777b538SAndroid Build Coastguard Worker HRESULT hr = async_operation->QueryInterface(IID_PPV_ARGS(&async_info));
88*6777b538SAndroid Build Coastguard Worker if (FAILED(hr))
89*6777b538SAndroid Build Coastguard Worker return hr;
90*6777b538SAndroid Build Coastguard Worker
91*6777b538SAndroid Build Coastguard Worker HRESULT operation_hr;
92*6777b538SAndroid Build Coastguard Worker hr = async_info->get_ErrorCode(&operation_hr);
93*6777b538SAndroid Build Coastguard Worker if (FAILED(hr))
94*6777b538SAndroid Build Coastguard Worker return hr;
95*6777b538SAndroid Build Coastguard Worker
96*6777b538SAndroid Build Coastguard Worker DCHECK(FAILED(operation_hr));
97*6777b538SAndroid Build Coastguard Worker return operation_hr;
98*6777b538SAndroid Build Coastguard Worker }
99*6777b538SAndroid Build Coastguard Worker
100*6777b538SAndroid Build Coastguard Worker // Registers an internal completion handler for |async_operation| and upon
101*6777b538SAndroid Build Coastguard Worker // completion, posts the results to the provided |completed_handler|. Returns an
102*6777b538SAndroid Build Coastguard Worker // HRESULT indicating the success of registering the internal completion
103*6777b538SAndroid Build Coastguard Worker // handler.
104*6777b538SAndroid Build Coastguard Worker //
105*6777b538SAndroid Build Coastguard Worker // Callers need to ensure that this method is invoked in the correct COM
106*6777b538SAndroid Build Coastguard Worker // apartment, i.e. the one that created |async_operation|. The
107*6777b538SAndroid Build Coastguard Worker // |completed_handler| will be run on the same sequence that invoked this
108*6777b538SAndroid Build Coastguard Worker // method. This call does not ensure the lifetime of the |async_operation|,
109*6777b538SAndroid Build Coastguard Worker // which must be done by the caller.
110*6777b538SAndroid Build Coastguard Worker template <typename T>
PostAsyncOperationCompletedHandler(IAsyncOperationT<T> * async_operation,IAsyncOperationCompletedHandlerT<T> completed_handler)111*6777b538SAndroid Build Coastguard Worker HRESULT PostAsyncOperationCompletedHandler(
112*6777b538SAndroid Build Coastguard Worker IAsyncOperationT<T>* async_operation,
113*6777b538SAndroid Build Coastguard Worker IAsyncOperationCompletedHandlerT<T> completed_handler) {
114*6777b538SAndroid Build Coastguard Worker using AsyncResult =
115*6777b538SAndroid Build Coastguard Worker std::pair<Microsoft::WRL::ComPtr<IAsyncOperationT<T>>, AsyncStatus>;
116*6777b538SAndroid Build Coastguard Worker
117*6777b538SAndroid Build Coastguard Worker auto internal_completed_handler =
118*6777b538SAndroid Build Coastguard Worker base::BindOnce([](IAsyncOperationT<T>* async_operation,
119*6777b538SAndroid Build Coastguard Worker AsyncStatus async_status) -> AsyncResult {
120*6777b538SAndroid Build Coastguard Worker // Posting the results to the TaskRunner is required, since this
121*6777b538SAndroid Build Coastguard Worker // CompletedHandler might be invoked on an arbitrary thread however
122*6777b538SAndroid Build Coastguard Worker // the raw |async_operation| pointer is only guaranteed to be valid
123*6777b538SAndroid Build Coastguard Worker // for the lifetime of this call, so to ensure it is still valid
124*6777b538SAndroid Build Coastguard Worker // through the lifetime of the call to the |completed_handler| we
125*6777b538SAndroid Build Coastguard Worker // capture it in an appropriate ref-counted pointer.
126*6777b538SAndroid Build Coastguard Worker return std::make_pair(async_operation, async_status);
127*6777b538SAndroid Build Coastguard Worker })
128*6777b538SAndroid Build Coastguard Worker .Then(
129*6777b538SAndroid Build Coastguard Worker base::BindPostTaskToCurrentDefault(base::BindOnce(
130*6777b538SAndroid Build Coastguard Worker [](IAsyncOperationCompletedHandlerT<T> completed_handler,
131*6777b538SAndroid Build Coastguard Worker AsyncResult async_result) {
132*6777b538SAndroid Build Coastguard Worker std::move(completed_handler)
133*6777b538SAndroid Build Coastguard Worker .Run(async_result.first.Get(), async_result.second);
134*6777b538SAndroid Build Coastguard Worker },
135*6777b538SAndroid Build Coastguard Worker std::move(completed_handler))));
136*6777b538SAndroid Build Coastguard Worker
137*6777b538SAndroid Build Coastguard Worker using CompletedHandler = Microsoft::WRL::Implements<
138*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
139*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>,
140*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::FtmBase>;
141*6777b538SAndroid Build Coastguard Worker
142*6777b538SAndroid Build Coastguard Worker return async_operation->put_Completed(
143*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::Callback<CompletedHandler>(
144*6777b538SAndroid Build Coastguard Worker [internal_completed_handler(std::move(internal_completed_handler))](
145*6777b538SAndroid Build Coastguard Worker IAsyncOperationT<T>* async_operation,
146*6777b538SAndroid Build Coastguard Worker AsyncStatus async_status) mutable {
147*6777b538SAndroid Build Coastguard Worker std::move(internal_completed_handler)
148*6777b538SAndroid Build Coastguard Worker .Run(async_operation, async_status);
149*6777b538SAndroid Build Coastguard Worker return S_OK;
150*6777b538SAndroid Build Coastguard Worker })
151*6777b538SAndroid Build Coastguard Worker .Get());
152*6777b538SAndroid Build Coastguard Worker }
153*6777b538SAndroid Build Coastguard Worker
154*6777b538SAndroid Build Coastguard Worker } // namespace internal
155*6777b538SAndroid Build Coastguard Worker
156*6777b538SAndroid Build Coastguard Worker // Registers an internal completion handler for |async_operation| and upon
157*6777b538SAndroid Build Coastguard Worker // successful completion invokes the |success_callback| with the result. If the
158*6777b538SAndroid Build Coastguard Worker // |async_operation| encounters an error no callback will be invoked. Returns
159*6777b538SAndroid Build Coastguard Worker // an HRESULT indicating the success of registering the internal completion
160*6777b538SAndroid Build Coastguard Worker // handler.
161*6777b538SAndroid Build Coastguard Worker //
162*6777b538SAndroid Build Coastguard Worker // Callers need to ensure that this method is invoked in the correct COM
163*6777b538SAndroid Build Coastguard Worker // apartment, i.e. the one that created |async_operation|. The resulting
164*6777b538SAndroid Build Coastguard Worker // callback (i.e. |success_callback|) will be run on the same sequence that
165*6777b538SAndroid Build Coastguard Worker // invoked this method. This call does not ensure the lifetime of the
166*6777b538SAndroid Build Coastguard Worker // |async_operation|, which must be done by the caller.
167*6777b538SAndroid Build Coastguard Worker template <typename T>
PostAsyncHandlers(internal::IAsyncOperationT<T> * async_operation,base::OnceCallback<void (internal::AsyncResultsT<T>)> success_callback)168*6777b538SAndroid Build Coastguard Worker HRESULT PostAsyncHandlers(
169*6777b538SAndroid Build Coastguard Worker internal::IAsyncOperationT<T>* async_operation,
170*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(internal::AsyncResultsT<T>)> success_callback) {
171*6777b538SAndroid Build Coastguard Worker return internal::PostAsyncOperationCompletedHandler(
172*6777b538SAndroid Build Coastguard Worker async_operation,
173*6777b538SAndroid Build Coastguard Worker base::BindOnce(
174*6777b538SAndroid Build Coastguard Worker [](base::OnceCallback<void(internal::AsyncResultsT<T>)>
175*6777b538SAndroid Build Coastguard Worker success_callback,
176*6777b538SAndroid Build Coastguard Worker internal::IAsyncOperationT<T>* async_operation,
177*6777b538SAndroid Build Coastguard Worker AsyncStatus async_status) {
178*6777b538SAndroid Build Coastguard Worker internal::AsyncResultsT<T> results;
179*6777b538SAndroid Build Coastguard Worker HRESULT hr = internal::GetAsyncResultsT(async_operation,
180*6777b538SAndroid Build Coastguard Worker async_status, &results);
181*6777b538SAndroid Build Coastguard Worker if (SUCCEEDED(hr))
182*6777b538SAndroid Build Coastguard Worker std::move(success_callback).Run(results);
183*6777b538SAndroid Build Coastguard Worker },
184*6777b538SAndroid Build Coastguard Worker std::move(success_callback)));
185*6777b538SAndroid Build Coastguard Worker }
186*6777b538SAndroid Build Coastguard Worker
187*6777b538SAndroid Build Coastguard Worker // Registers an internal completion handler for |async_operation| and upon
188*6777b538SAndroid Build Coastguard Worker // successful completion invokes the |success_callback| with the result. If the
189*6777b538SAndroid Build Coastguard Worker // |async_operation| encounters an error the |failure_callback| will instead be
190*6777b538SAndroid Build Coastguard Worker // invoked. Returns an HRESULT indicating the success of registering the
191*6777b538SAndroid Build Coastguard Worker // internal completion handler.
192*6777b538SAndroid Build Coastguard Worker //
193*6777b538SAndroid Build Coastguard Worker // Callers need to ensure that this method is invoked in the correct COM
194*6777b538SAndroid Build Coastguard Worker // apartment, i.e. the one that created |async_operation|. The resulting
195*6777b538SAndroid Build Coastguard Worker // callback (|success_callback| or |failure_callback|) will be run on the same
196*6777b538SAndroid Build Coastguard Worker // sequence that invoked this method. This call does not ensure the lifetime of
197*6777b538SAndroid Build Coastguard Worker // the |async_operation|, which must be done by the caller.
198*6777b538SAndroid Build Coastguard Worker template <typename T>
PostAsyncHandlers(internal::IAsyncOperationT<T> * async_operation,base::OnceCallback<void (internal::AsyncResultsT<T>)> success_callback,base::OnceCallback<void ()> failure_callback)199*6777b538SAndroid Build Coastguard Worker HRESULT PostAsyncHandlers(
200*6777b538SAndroid Build Coastguard Worker internal::IAsyncOperationT<T>* async_operation,
201*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(internal::AsyncResultsT<T>)> success_callback,
202*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void()> failure_callback) {
203*6777b538SAndroid Build Coastguard Worker return internal::PostAsyncOperationCompletedHandler(
204*6777b538SAndroid Build Coastguard Worker async_operation,
205*6777b538SAndroid Build Coastguard Worker base::BindOnce(
206*6777b538SAndroid Build Coastguard Worker [](base::OnceCallback<void(internal::AsyncResultsT<T>)>
207*6777b538SAndroid Build Coastguard Worker success_callback,
208*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void()> failure_callback,
209*6777b538SAndroid Build Coastguard Worker internal::IAsyncOperationT<T>* async_operation,
210*6777b538SAndroid Build Coastguard Worker AsyncStatus async_status) {
211*6777b538SAndroid Build Coastguard Worker internal::AsyncResultsT<T> results;
212*6777b538SAndroid Build Coastguard Worker HRESULT hr = internal::GetAsyncResultsT(async_operation,
213*6777b538SAndroid Build Coastguard Worker async_status, &results);
214*6777b538SAndroid Build Coastguard Worker if (SUCCEEDED(hr))
215*6777b538SAndroid Build Coastguard Worker std::move(success_callback).Run(results);
216*6777b538SAndroid Build Coastguard Worker else
217*6777b538SAndroid Build Coastguard Worker std::move(failure_callback).Run();
218*6777b538SAndroid Build Coastguard Worker },
219*6777b538SAndroid Build Coastguard Worker std::move(success_callback), std::move(failure_callback)));
220*6777b538SAndroid Build Coastguard Worker }
221*6777b538SAndroid Build Coastguard Worker
222*6777b538SAndroid Build Coastguard Worker // Registers an internal completion handler for |async_operation| and upon
223*6777b538SAndroid Build Coastguard Worker // successful completion invokes the |success_callback| with the result. If the
224*6777b538SAndroid Build Coastguard Worker // |async_operation| encounters an error the |failure_callback| will instead be
225*6777b538SAndroid Build Coastguard Worker // invoked with the failing HRESULT. Returns an HRESULT indicating the success
226*6777b538SAndroid Build Coastguard Worker // of registering the internal completion handler.
227*6777b538SAndroid Build Coastguard Worker //
228*6777b538SAndroid Build Coastguard Worker // Callers need to ensure that this method is invoked in the correct COM
229*6777b538SAndroid Build Coastguard Worker // apartment, i.e. the one that created |async_operation|. The resulting
230*6777b538SAndroid Build Coastguard Worker // callback (|success_callback| or |failure_callback|) will be run on the same
231*6777b538SAndroid Build Coastguard Worker // sequence that invoked this method. This call does not ensure the lifetime of
232*6777b538SAndroid Build Coastguard Worker // the |async_operation|, which must be done by the caller.
233*6777b538SAndroid Build Coastguard Worker template <typename T>
PostAsyncHandlers(internal::IAsyncOperationT<T> * async_operation,base::OnceCallback<void (internal::AsyncResultsT<T>)> success_callback,base::OnceCallback<void (HRESULT)> failure_callback)234*6777b538SAndroid Build Coastguard Worker HRESULT PostAsyncHandlers(
235*6777b538SAndroid Build Coastguard Worker internal::IAsyncOperationT<T>* async_operation,
236*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(internal::AsyncResultsT<T>)> success_callback,
237*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(HRESULT)> failure_callback) {
238*6777b538SAndroid Build Coastguard Worker return internal::PostAsyncOperationCompletedHandler(
239*6777b538SAndroid Build Coastguard Worker async_operation,
240*6777b538SAndroid Build Coastguard Worker base::BindOnce(
241*6777b538SAndroid Build Coastguard Worker [](base::OnceCallback<void(internal::AsyncResultsT<T>)>
242*6777b538SAndroid Build Coastguard Worker success_callback,
243*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(HRESULT)> failure_callback,
244*6777b538SAndroid Build Coastguard Worker internal::IAsyncOperationT<T>* async_operation,
245*6777b538SAndroid Build Coastguard Worker AsyncStatus async_status) {
246*6777b538SAndroid Build Coastguard Worker internal::AsyncResultsT<T> results;
247*6777b538SAndroid Build Coastguard Worker HRESULT hr = internal::GetAsyncResultsT(async_operation,
248*6777b538SAndroid Build Coastguard Worker async_status, &results);
249*6777b538SAndroid Build Coastguard Worker if (SUCCEEDED(hr))
250*6777b538SAndroid Build Coastguard Worker std::move(success_callback).Run(results);
251*6777b538SAndroid Build Coastguard Worker else
252*6777b538SAndroid Build Coastguard Worker std::move(failure_callback).Run(hr);
253*6777b538SAndroid Build Coastguard Worker },
254*6777b538SAndroid Build Coastguard Worker std::move(success_callback), std::move(failure_callback)));
255*6777b538SAndroid Build Coastguard Worker }
256*6777b538SAndroid Build Coastguard Worker
257*6777b538SAndroid Build Coastguard Worker // Registers an internal completion handler for |async_operation| and upon
258*6777b538SAndroid Build Coastguard Worker // successful completion invokes the |success_callback| with the result. If the
259*6777b538SAndroid Build Coastguard Worker // |async_operation| encounters an error the |failure_callback| will instead be
260*6777b538SAndroid Build Coastguard Worker // invoked with the result and an HRESULT indicating the success of fetching
261*6777b538SAndroid Build Coastguard Worker // that result (NOT an HRESULT expressing the failure of the operation). Returns
262*6777b538SAndroid Build Coastguard Worker // an HRESULT indicating the success of registering the internal completion
263*6777b538SAndroid Build Coastguard Worker // handler.
264*6777b538SAndroid Build Coastguard Worker //
265*6777b538SAndroid Build Coastguard Worker // This overload is designed for (uncommon) operations whose results encapsulate
266*6777b538SAndroid Build Coastguard Worker // success and failure information (and as a result of that are expected to be
267*6777b538SAndroid Build Coastguard Worker // available under both success and failure conditions).
268*6777b538SAndroid Build Coastguard Worker //
269*6777b538SAndroid Build Coastguard Worker // Callers need to ensure that this method is invoked in the correct COM
270*6777b538SAndroid Build Coastguard Worker // apartment, i.e. the one that created |async_operation|. The resulting
271*6777b538SAndroid Build Coastguard Worker // callback (|success_callback| or |failure_callback|) will be run on the same
272*6777b538SAndroid Build Coastguard Worker // sequence that invoked this method. This call does not ensure the lifetime of
273*6777b538SAndroid Build Coastguard Worker // the |async_operation|, which must be done by the caller.
274*6777b538SAndroid Build Coastguard Worker template <typename T>
PostAsyncHandlers(internal::IAsyncOperationT<T> * async_operation,base::OnceCallback<void (internal::AsyncResultsT<T>)> success_callback,base::OnceCallback<void (HRESULT,internal::AsyncResultsT<T>)> failure_callback)275*6777b538SAndroid Build Coastguard Worker HRESULT PostAsyncHandlers(
276*6777b538SAndroid Build Coastguard Worker internal::IAsyncOperationT<T>* async_operation,
277*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(internal::AsyncResultsT<T>)> success_callback,
278*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(HRESULT, internal::AsyncResultsT<T>)>
279*6777b538SAndroid Build Coastguard Worker failure_callback) {
280*6777b538SAndroid Build Coastguard Worker return internal::PostAsyncOperationCompletedHandler(
281*6777b538SAndroid Build Coastguard Worker async_operation,
282*6777b538SAndroid Build Coastguard Worker base::BindOnce(
283*6777b538SAndroid Build Coastguard Worker [](base::OnceCallback<void(internal::AsyncResultsT<T>)>
284*6777b538SAndroid Build Coastguard Worker success_callback,
285*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(HRESULT, internal::AsyncResultsT<T>)>
286*6777b538SAndroid Build Coastguard Worker failure_callback,
287*6777b538SAndroid Build Coastguard Worker internal::IAsyncOperationT<T>* async_operation,
288*6777b538SAndroid Build Coastguard Worker AsyncStatus async_status) {
289*6777b538SAndroid Build Coastguard Worker internal::AsyncResultsT<T> results;
290*6777b538SAndroid Build Coastguard Worker HRESULT hr = internal::GetAsyncResultsT(
291*6777b538SAndroid Build Coastguard Worker async_operation,
292*6777b538SAndroid Build Coastguard Worker async_status == AsyncStatus::Error ? AsyncStatus::Completed
293*6777b538SAndroid Build Coastguard Worker : async_status,
294*6777b538SAndroid Build Coastguard Worker &results);
295*6777b538SAndroid Build Coastguard Worker if (SUCCEEDED(hr) && async_status == AsyncStatus::Completed)
296*6777b538SAndroid Build Coastguard Worker std::move(success_callback).Run(results);
297*6777b538SAndroid Build Coastguard Worker else
298*6777b538SAndroid Build Coastguard Worker std::move(failure_callback).Run(hr, results);
299*6777b538SAndroid Build Coastguard Worker },
300*6777b538SAndroid Build Coastguard Worker std::move(success_callback), std::move(failure_callback)));
301*6777b538SAndroid Build Coastguard Worker }
302*6777b538SAndroid Build Coastguard Worker
303*6777b538SAndroid Build Coastguard Worker // Deprecated.
304*6777b538SAndroid Build Coastguard Worker //
305*6777b538SAndroid Build Coastguard Worker // Registers an internal completion handler for |async_operation| and upon
306*6777b538SAndroid Build Coastguard Worker // invocation, posts the results to the provided |callback|. Returns an HRESULT
307*6777b538SAndroid Build Coastguard Worker // indicating the success of registering the internal completion handler.
308*6777b538SAndroid Build Coastguard Worker //
309*6777b538SAndroid Build Coastguard Worker // Callers need to ensure that this method is invoked in the correct COM
310*6777b538SAndroid Build Coastguard Worker // apartment, i.e. the one that created |async_operation|. The |callback| will
311*6777b538SAndroid Build Coastguard Worker // be run on the same sequence that invoked this method.
312*6777b538SAndroid Build Coastguard Worker //
313*6777b538SAndroid Build Coastguard Worker // WARNING: This call holds a reference to the provided |async_operation| until
314*6777b538SAndroid Build Coastguard Worker // it completes.
315*6777b538SAndroid Build Coastguard Worker template <typename T>
PostAsyncResults(Microsoft::WRL::ComPtr<internal::IAsyncOperationT<T>> async_operation,base::OnceCallback<void (internal::AsyncResultsT<T>)> callback)316*6777b538SAndroid Build Coastguard Worker HRESULT PostAsyncResults(
317*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::ComPtr<internal::IAsyncOperationT<T>> async_operation,
318*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(internal::AsyncResultsT<T>)> callback) {
319*6777b538SAndroid Build Coastguard Worker return internal::PostAsyncOperationCompletedHandler(
320*6777b538SAndroid Build Coastguard Worker async_operation.Get(),
321*6777b538SAndroid Build Coastguard Worker base::BindOnce(
322*6777b538SAndroid Build Coastguard Worker [](Microsoft::WRL::ComPtr<internal::IAsyncOperationT<T>>
323*6777b538SAndroid Build Coastguard Worker original_async_operation,
324*6777b538SAndroid Build Coastguard Worker base::OnceCallback<void(internal::AsyncResultsT<T>)> callback,
325*6777b538SAndroid Build Coastguard Worker internal::IAsyncOperationT<T>* async_operation,
326*6777b538SAndroid Build Coastguard Worker AsyncStatus async_status) {
327*6777b538SAndroid Build Coastguard Worker DCHECK(original_async_operation.Get() == async_operation);
328*6777b538SAndroid Build Coastguard Worker if (async_status != AsyncStatus::Completed) {
329*6777b538SAndroid Build Coastguard Worker VLOG(2) << "Got unexpected AsyncStatus: "
330*6777b538SAndroid Build Coastguard Worker << internal::ToCString(async_status);
331*6777b538SAndroid Build Coastguard Worker }
332*6777b538SAndroid Build Coastguard Worker
333*6777b538SAndroid Build Coastguard Worker internal::AsyncResultsT<T> results;
334*6777b538SAndroid Build Coastguard Worker HRESULT hr = internal::GetAsyncResultsT(async_operation,
335*6777b538SAndroid Build Coastguard Worker async_status, &results);
336*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) {
337*6777b538SAndroid Build Coastguard Worker VLOG(2) << "GetAsyncResultsT failed: "
338*6777b538SAndroid Build Coastguard Worker << logging::SystemErrorCodeToString(hr);
339*6777b538SAndroid Build Coastguard Worker }
340*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(results);
341*6777b538SAndroid Build Coastguard Worker },
342*6777b538SAndroid Build Coastguard Worker async_operation, std::move(callback)));
343*6777b538SAndroid Build Coastguard Worker }
344*6777b538SAndroid Build Coastguard Worker
345*6777b538SAndroid Build Coastguard Worker } // namespace win
346*6777b538SAndroid Build Coastguard Worker } // namespace base
347*6777b538SAndroid Build Coastguard Worker
348*6777b538SAndroid Build Coastguard Worker #endif // BASE_WIN_POST_ASYNC_RESULTS_H_
349