fixup! [M120 Migration] Notify media device state to webbrowser
[platform/framework/web/chromium-efl.git] / base / supports_user_data.cc
1 // Copyright 2012 The Chromium Authors
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 "base/supports_user_data.h"
6
7 #include "base/feature_list.h"
8 #include "base/sequence_checker.h"
9
10 namespace base {
11
12 std::unique_ptr<SupportsUserData::Data> SupportsUserData::Data::Clone() {
13   return nullptr;
14 }
15
16 SupportsUserData::SupportsUserData() {
17   // Harmless to construct on a different execution sequence to subsequent
18   // usage.
19   DETACH_FROM_SEQUENCE(sequence_checker_);
20 }
21
22 SupportsUserData::SupportsUserData(SupportsUserData&&) = default;
23 SupportsUserData& SupportsUserData::operator=(SupportsUserData&&) = default;
24
25 SupportsUserData::Data* SupportsUserData::GetUserData(const void* key) const {
26   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
27   // Avoid null keys; they are too vulnerable to collision.
28   DCHECK(key);
29   auto found = user_data_.find(key);
30   if (found != user_data_.end()) {
31     return found->second.get();
32   }
33   return nullptr;
34 }
35
36 std::unique_ptr<SupportsUserData::Data> SupportsUserData::TakeUserData(
37     const void* key) {
38   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
39   // Null keys are too vulnerable to collision.
40   CHECK(key);
41   auto found = user_data_.find(key);
42   if (found != user_data_.end()) {
43     std::unique_ptr<SupportsUserData::Data> deowned;
44     deowned.swap(found->second);
45     user_data_.erase(key);
46     return deowned;
47   }
48   return nullptr;
49 }
50
51 void SupportsUserData::SetUserData(const void* key,
52                                    std::unique_ptr<Data> data) {
53   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
54   CHECK(!in_destructor_) << "Calling SetUserData() when SupportsUserData is "
55                             "being destroyed is not supported.";
56   // Avoid null keys; they are too vulnerable to collision.
57   DCHECK(key);
58   if (data.get()) {
59     user_data_[key] = std::move(data);
60   } else {
61     RemoveUserData(key);
62   }
63 }
64
65 void SupportsUserData::RemoveUserData(const void* key) {
66   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
67   auto it = user_data_.find(key);
68   if (it != user_data_.end()) {
69     // Remove the entry from the map before deleting `owned_data` to avoid
70     // reentrancy issues when `owned_data` owns `this`. Otherwise:
71     //
72     // 1. `RemoveUserData()` calls `erase()`.
73     // 2. `erase()` deletes `owned_data`.
74     // 3. `owned_data` deletes `this`.
75     //
76     // At this point, `erase()` is still on the stack even though the
77     // backing map (owned by `this`) has already been destroyed, and it
78     // may simply crash, cause a use-after-free, or any other number of
79     // interesting things.
80     auto owned_data = std::move(it->second);
81     user_data_.erase(it);
82   }
83 }
84
85 void SupportsUserData::DetachFromSequence() {
86   DETACH_FROM_SEQUENCE(sequence_checker_);
87 }
88
89 void SupportsUserData::CloneDataFrom(const SupportsUserData& other) {
90   for (const auto& data_pair : other.user_data_) {
91     auto cloned_data = data_pair.second->Clone();
92     if (cloned_data) {
93       SetUserData(data_pair.first, std::move(cloned_data));
94     }
95   }
96 }
97
98 SupportsUserData::~SupportsUserData() {
99   if (!user_data_.empty()) {
100     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
101   }
102   in_destructor_ = true;
103   absl::flat_hash_map<const void*, std::unique_ptr<Data>> user_data;
104   user_data_.swap(user_data);
105   // Now this->user_data_ is empty, and any destructors called transitively from
106   // the destruction of |local_user_data| will see it that way instead of
107   // examining a being-destroyed object.
108 }
109
110 void SupportsUserData::ClearAllUserData() {
111   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
112   user_data_.clear();
113 }
114
115 }  // namespace base