1 // Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011 2 // Google Inc. All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above 11 // copyright notice, this list of conditions and the following disclaimer 12 // in the documentation and/or other materials provided with the 13 // distribution. 14 // * Neither the name of Google Inc. nor the name Chromium Embedded 15 // Framework nor the names of its contributors may be used to endorse 16 // or promote products derived from this software without specific prior 17 // written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 // CancelableCallback is a wrapper around base::Callback that allows 32 // cancellation of a callback. CancelableCallback takes a reference on the 33 // wrapped callback until this object is destroyed or Reset()/Cancel() are 34 // called. 35 // 36 // NOTE: 37 // 38 // Calling CancelableCallback::Cancel() brings the object back to its natural, 39 // default-constructed state, i.e., CancelableCallback::callback() will return 40 // a null callback. 41 // 42 // THREAD-SAFETY: 43 // 44 // CancelableCallback objects must be created on, posted to, cancelled on, and 45 // destroyed on the same thread. 46 // 47 // 48 // EXAMPLE USAGE: 49 // 50 // In the following example, the test is verifying that RunIntensiveTest() 51 // Quit()s the message loop within 4 seconds. The cancelable callback is posted 52 // to the message loop, the intensive test runs, the message loop is run, 53 // then the callback is cancelled. 54 // 55 // RunLoop run_loop; 56 // 57 // void TimeoutCallback(const std::string& timeout_message) { 58 // FAIL() << timeout_message; 59 // run_loop.QuitWhenIdle(); 60 // } 61 // 62 // CancelableOnceClosure timeout( 63 // base::BindOnce(&TimeoutCallback, "Test timed out.")); 64 // ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, timeout.callback(), 65 // TimeDelta::FromSeconds(4)); 66 // RunIntensiveTest(); 67 // run_loop.Run(); 68 // timeout.Cancel(); // Hopefully this is hit before the timeout callback runs. 69 70 #ifndef CEF_INCLUDE_BASE_CEF_CANCELABLE_CALLBACK_H_ 71 #define CEF_INCLUDE_BASE_CEF_CANCELABLE_CALLBACK_H_ 72 #pragma once 73 74 #if defined(USING_CHROMIUM_INCLUDES) 75 // When building CEF include the Chromium header directly. 76 #include "base/cancelable_callback.h" 77 #else // !USING_CHROMIUM_INCLUDES 78 // The following is substantially similar to the Chromium implementation. 79 // If the Chromium implementation diverges the below implementation should be 80 // updated to match. 81 82 #include <utility> 83 84 #include "include/base/cef_bind.h" 85 #include "include/base/cef_callback.h" 86 #include "include/base/cef_compiler_specific.h" 87 #include "include/base/cef_logging.h" 88 #include "include/base/cef_weak_ptr.h" 89 #include "include/base/internal/cef_callback_internal.h" 90 91 namespace base { 92 namespace internal { 93 94 template <typename CallbackType> 95 class CancelableCallbackImpl { 96 public: 97 CancelableCallbackImpl() = default; 98 CancelableCallbackImpl(const CancelableCallbackImpl&) = delete; 99 CancelableCallbackImpl& operator=(const CancelableCallbackImpl&) = delete; 100 101 // |callback| must not be null. CancelableCallbackImpl(CallbackType callback)102 explicit CancelableCallbackImpl(CallbackType callback) 103 : callback_(std::move(callback)) { 104 DCHECK(callback_); 105 } 106 107 ~CancelableCallbackImpl() = default; 108 109 // Cancels and drops the reference to the wrapped callback. Cancel()110 void Cancel() { 111 weak_ptr_factory_.InvalidateWeakPtrs(); 112 callback_.Reset(); 113 } 114 115 // Returns true if the wrapped callback has been cancelled. IsCancelled()116 bool IsCancelled() const { return callback_.is_null(); } 117 118 // Sets |callback| as the closure that may be cancelled. |callback| may not 119 // be null. Outstanding and any previously wrapped callbacks are cancelled. Reset(CallbackType callback)120 void Reset(CallbackType callback) { 121 DCHECK(callback); 122 // Outstanding tasks (e.g., posted to a message loop) must not be called. 123 Cancel(); 124 callback_ = std::move(callback); 125 } 126 127 // Returns a callback that can be disabled by calling Cancel(). callback()128 CallbackType callback() const { 129 if (!callback_) 130 return CallbackType(); 131 CallbackType forwarder; 132 MakeForwarder(&forwarder); 133 return forwarder; 134 } 135 136 private: 137 template <typename... Args> MakeForwarder(RepeatingCallback<void (Args...)> * out)138 void MakeForwarder(RepeatingCallback<void(Args...)>* out) const { 139 using ForwarderType = void (CancelableCallbackImpl::*)(Args...); 140 ForwarderType forwarder = &CancelableCallbackImpl::ForwardRepeating; 141 *out = BindRepeating(forwarder, weak_ptr_factory_.GetWeakPtr()); 142 } 143 144 template <typename... Args> MakeForwarder(OnceCallback<void (Args...)> * out)145 void MakeForwarder(OnceCallback<void(Args...)>* out) const { 146 using ForwarderType = void (CancelableCallbackImpl::*)(Args...); 147 ForwarderType forwarder = &CancelableCallbackImpl::ForwardOnce; 148 *out = BindOnce(forwarder, weak_ptr_factory_.GetWeakPtr()); 149 } 150 151 template <typename... Args> ForwardRepeating(Args...args)152 void ForwardRepeating(Args... args) { 153 callback_.Run(std::forward<Args>(args)...); 154 } 155 156 template <typename... Args> ForwardOnce(Args...args)157 void ForwardOnce(Args... args) { 158 weak_ptr_factory_.InvalidateWeakPtrs(); 159 std::move(callback_).Run(std::forward<Args>(args)...); 160 } 161 162 // The stored closure that may be cancelled. 163 CallbackType callback_; 164 mutable base::WeakPtrFactory<CancelableCallbackImpl> weak_ptr_factory_{this}; 165 }; 166 167 } // namespace internal 168 169 // Consider using base::WeakPtr directly instead of base::CancelableCallback for 170 // the task cancellation. 171 template <typename Signature> 172 using CancelableOnceCallback = 173 internal::CancelableCallbackImpl<OnceCallback<Signature>>; 174 using CancelableOnceClosure = CancelableOnceCallback<void()>; 175 176 template <typename Signature> 177 using CancelableRepeatingCallback = 178 internal::CancelableCallbackImpl<RepeatingCallback<Signature>>; 179 using CancelableRepeatingClosure = CancelableRepeatingCallback<void()>; 180 181 } // namespace base 182 183 #endif // !USING_CHROMIUM_INCLUDES 184 185 #endif // CEF_INCLUDE_BASE_CEF_CANCELABLE_CALLBACK_H_ 186