Avi Drissman | 4e1b7bc3 | 2022-09-15 14:03:50 | [diff] [blame] | 1 | // Copyright 2019 The Chromium Authors |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Evan Stade | 1a8d9d4 | 2024-09-10 19:37:19 | [diff] [blame] | 5 | #ifndef CONTENT_BROWSER_INDEXED_DB_INSTANCE_CALLBACK_HELPERS_H_ |
| 6 | #define CONTENT_BROWSER_INDEXED_DB_INSTANCE_CALLBACK_HELPERS_H_ |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 7 | |
| 8 | #include <memory> |
Joshua Bell | 98475ae | 2019-08-15 01:43:36 | [diff] [blame] | 9 | #include <utility> |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 10 | |
Hans Wennborg | f30ad80 | 2020-06-20 16:50:20 | [diff] [blame] | 11 | #include "base/check.h" |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 12 | #include "base/memory/weak_ptr.h" |
Evan Stade | 1a8d9d4 | 2024-09-10 19:37:19 | [diff] [blame] | 13 | #include "content/browser/indexed_db/instance/transaction.h" |
Henrique Ferreiro | da0a55c | 2019-11-12 14:06:04 | [diff] [blame] | 14 | #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-forward.h" |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 15 | #include "third_party/leveldatabase/env_chromium.h" |
| 16 | |
| 17 | // Since functions in this file use templates, they must be in a header file |
| 18 | // and can't be placed in a definition file. Please ensure any including file |
| 19 | // is a definition file, itself, and never include this into a header file. |
| 20 | |
Evan Stade | cbb1e00 | 2024-09-13 20:06:57 | [diff] [blame] | 21 | namespace content::indexed_db { |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 22 | namespace indexed_db_callback_helpers_internal { |
| 23 | |
| 24 | template <typename T> |
Mike Wasserman | 0d5da52 | 2024-09-27 07:47:03 | [diff] [blame] | 25 | Status InvokeOrSucceed(base::WeakPtr<T> ptr, |
| 26 | Transaction::Operation operation, |
| 27 | Transaction* transaction) { |
Evan Stade | 1a8d9d4 | 2024-09-10 19:37:19 | [diff] [blame] | 28 | if (ptr) { |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 29 | return std::move(operation).Run(transaction); |
Evan Stade | 1a8d9d4 | 2024-09-10 19:37:19 | [diff] [blame] | 30 | } |
Mike Wasserman | 0d5da52 | 2024-09-27 07:47:03 | [diff] [blame] | 31 | return Status::OK(); |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 32 | } |
| 33 | |
| 34 | template <typename R> |
Evan Stade | cbb1e00 | 2024-09-13 20:06:57 | [diff] [blame] | 35 | R AbortCallback(base::WeakPtr<Transaction> transaction) { |
Evan Stade | 1a8d9d4 | 2024-09-10 19:37:19 | [diff] [blame] | 36 | if (transaction) { |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 37 | transaction->IncrementNumErrorsSent(); |
Evan Stade | 1a8d9d4 | 2024-09-10 19:37:19 | [diff] [blame] | 38 | } |
Evan Stade | cbb1e00 | 2024-09-13 20:06:57 | [diff] [blame] | 39 | DatabaseError error(blink::mojom::IDBException::kIgnorableAbortError, |
| 40 | "Backend aborted error"); |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 41 | return R::Struct::NewErrorResult( |
| 42 | blink::mojom::IDBError::New(error.code(), error.message())); |
| 43 | } |
| 44 | |
| 45 | template <typename R> |
| 46 | base::OnceCallback<R()> CreateAbortCallback( |
Evan Stade | cbb1e00 | 2024-09-13 20:06:57 | [diff] [blame] | 47 | base::WeakPtr<Transaction> transaction) { |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 48 | return base::BindOnce(&AbortCallback<R>, std::move(transaction)); |
| 49 | } |
| 50 | |
| 51 | // CallbackAbortOnDestruct wraps a callback in a class with a destructor that |
| 52 | // invokes that callback. When the CallbackAbortOnDestruct is instantiated, |
| 53 | // it expects a separate callback that, when called at destruct, will return |
| 54 | // the arguments that should be passed to the wrapped callback. |
| 55 | // |
| 56 | // This class is loosely based on //mojo/public/cpp/bindings/callback_helpers.h |
| 57 | // WrapCallbackWithDefaultInvokeIfNotRun. The difference is that the destructor |
| 58 | // calls |callback_| with args it gets on destruct rather than using static args |
| 59 | // given when the wrapper is created. |
| 60 | template <typename T, typename R> |
| 61 | class CallbackAbortOnDestruct { |
| 62 | public: |
Evan Stade | cbb1e00 | 2024-09-13 20:06:57 | [diff] [blame] | 63 | CallbackAbortOnDestruct(T callback, base::WeakPtr<Transaction> transaction) |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 64 | : callback_(std::move(callback)), |
| 65 | args_at_destroy_(CreateAbortCallback<R>(transaction)), |
| 66 | called_(false) {} |
Peter Boström | 828b902 | 2021-09-21 02:28:43 | [diff] [blame] | 67 | |
| 68 | CallbackAbortOnDestruct(const CallbackAbortOnDestruct&) = delete; |
| 69 | CallbackAbortOnDestruct& operator=(const CallbackAbortOnDestruct&) = delete; |
| 70 | |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 71 | ~CallbackAbortOnDestruct() { |
Evan Stade | 1a8d9d4 | 2024-09-10 19:37:19 | [diff] [blame] | 72 | if (called_) { |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 73 | return; |
Evan Stade | 1a8d9d4 | 2024-09-10 19:37:19 | [diff] [blame] | 74 | } |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 75 | R args = std::move(args_at_destroy_).Run(); |
| 76 | std::move(callback_).Run(std::move(args)); |
| 77 | } |
| 78 | |
| 79 | void Run(R ptr) { |
| 80 | called_ = true; |
| 81 | std::move(callback_).Run(std::move(ptr)); |
| 82 | } |
| 83 | |
| 84 | private: |
| 85 | T callback_; |
| 86 | base::OnceCallback<R()> args_at_destroy_; |
| 87 | bool called_; |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 88 | }; |
| 89 | |
| 90 | } // namespace indexed_db_callback_helpers_internal |
| 91 | |
| 92 | // CreateCallbackAbortOnDestruct is a helper function to create an instance |
| 93 | // of CallbackAbortOnDestruct that returns a callback. By using this helper |
| 94 | // function, the wrapping callback can exist with the same type signature as |
| 95 | // the wrapped callback. |
| 96 | template <typename T, typename R> |
Evan Stade | cbb1e00 | 2024-09-13 20:06:57 | [diff] [blame] | 97 | T CreateCallbackAbortOnDestruct(T cb, base::WeakPtr<Transaction> transaction) { |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 98 | return base::BindOnce( |
| 99 | &indexed_db_callback_helpers_internal::CallbackAbortOnDestruct<T, R>::Run, |
| 100 | std::make_unique< |
| 101 | indexed_db_callback_helpers_internal::CallbackAbortOnDestruct<T, R>>( |
| 102 | std::move(cb), std::move(transaction))); |
| 103 | } |
| 104 | |
| 105 | // This allows us to bind a function with a return value to a weak ptr, and if |
| 106 | // the weak pointer is invalidated then we just return a default (success). |
| 107 | template <typename T, typename Functor, typename... Args> |
Evan Stade | cbb1e00 | 2024-09-13 20:06:57 | [diff] [blame] | 108 | Transaction::Operation BindWeakOperation(Functor&& functor, |
| 109 | base::WeakPtr<T> weak_ptr, |
| 110 | Args&&... args) { |
Arthur Sonzogni | b9db716 | 2023-04-19 07:39:31 | [diff] [blame] | 111 | DCHECK(weak_ptr); |
| 112 | T* ptr = weak_ptr.get(); |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 113 | return base::BindOnce( |
Arthur Sonzogni | b9db716 | 2023-04-19 07:39:31 | [diff] [blame] | 114 | &indexed_db_callback_helpers_internal::InvokeOrSucceed<T>, |
| 115 | std::move(weak_ptr), |
| 116 | base::BindOnce(std::forward<Functor>(functor), base::Unretained(ptr), |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 117 | std::forward<Args>(args)...)); |
| 118 | } |
| 119 | |
Evan Stade | cbb1e00 | 2024-09-13 20:06:57 | [diff] [blame] | 120 | } // namespace content::indexed_db |
Chase Phillips | 091007d | 2019-05-22 22:00:13 | [diff] [blame] | 121 | |
Evan Stade | 1a8d9d4 | 2024-09-10 19:37:19 | [diff] [blame] | 122 | #endif // CONTENT_BROWSER_INDEXED_DB_INSTANCE_CALLBACK_HELPERS_H_ |