Fix emulator build error
[platform/framework/web/chromium-efl.git] / components / prefs / pref_notifier_impl.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 "components/prefs/pref_notifier_impl.h"
6
7 #include "base/debug/alias.h"
8 #include "base/debug/dump_without_crashing.h"
9 #include "base/logging.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/observer_list.h"
12 #include "base/strings/strcat.h"
13 #include "components/prefs/pref_service.h"
14
15 PrefNotifierImpl::PrefNotifierImpl() : pref_service_(nullptr) {}
16
17 PrefNotifierImpl::PrefNotifierImpl(PrefService* service)
18     : pref_service_(service) {
19 }
20
21 PrefNotifierImpl::~PrefNotifierImpl() {
22   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
23
24   // Verify that there are no pref observers when we shut down.
25   for (const auto& observer_list : pref_observers_) {
26     if (observer_list.second->begin() != observer_list.second->end()) {
27       // Generally, there should not be any subscribers left when the profile
28       // is destroyed because a) those may indicate that the subscriber class
29       // maintains an active pointer to the profile that might be used for
30       // accessing a destroyed profile and b) those subscribers will try to
31       // unsubscribe from a PrefService that has been destroyed with the
32       // profile.
33       // There is one exception that is safe: Static objects that are leaked
34       // on process termination, if these objects just subscribe to preferences
35       // and never access the profile after destruction. As these objects are
36       // leaked on termination, it is guaranteed that they don't attempt to
37       // unsubscribe.
38       const auto& pref_name = observer_list.first;
39       std::string message = base::StrCat(
40           {"Pref observer for ", pref_name, " found at shutdown."});
41       LOG(WARNING) << message;
42       DEBUG_ALIAS_FOR_CSTR(aliased_message, message.c_str(), 128);
43
44       // TODO(crbug.com/942491, 946668, 945772) The following code collects
45       // stacktraces that show how the profile is destroyed that owns
46       // preferences which are known to have subscriptions outliving the
47       // profile.
48       if (
49           // For DbusAppmenu, crbug.com/946668
50           pref_name == "bookmark_bar.show_on_all_tabs" ||
51           // For BrowserWindowPropertyManager, crbug.com/942491
52           pref_name == "profile.icon_version") {
53         base::debug::DumpWithoutCrashing();
54       }
55     }
56   }
57
58   // Same for initialization observers.
59   if (!init_observers_.empty())
60     LOG(WARNING) << "Init observer found at shutdown.";
61
62   pref_observers_.clear();
63   init_observers_.clear();
64 }
65
66 void PrefNotifierImpl::AddPrefObserver(const std::string& path,
67                                        PrefObserver* obs) {
68   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
69
70   // Get the pref observer list associated with the path.
71   auto observer_iterator = pref_observers_.find(path);
72   if (observer_iterator == pref_observers_.end()) {
73     observer_iterator =
74         pref_observers_.emplace(path, std::make_unique<PrefObserverList>())
75             .first;
76   }
77
78   PrefObserverList* observer_list = observer_iterator->second.get();
79
80   // Add the pref observer. ObserverList will DCHECK if it already is
81   // in the list.
82   observer_list->AddObserver(obs);
83 }
84
85 void PrefNotifierImpl::RemovePrefObserver(const std::string& path,
86                                           PrefObserver* obs) {
87   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
88
89   auto observer_iterator = pref_observers_.find(path);
90   if (observer_iterator == pref_observers_.end()) {
91     return;
92   }
93
94   PrefObserverList* observer_list = observer_iterator->second.get();
95   observer_list->RemoveObserver(obs);
96 }
97
98 void PrefNotifierImpl::AddPrefObserverAllPrefs(PrefObserver* observer) {
99   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
100   all_prefs_pref_observers_.AddObserver(observer);
101 }
102
103 void PrefNotifierImpl::RemovePrefObserverAllPrefs(PrefObserver* observer) {
104   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
105   all_prefs_pref_observers_.RemoveObserver(observer);
106 }
107
108 void PrefNotifierImpl::AddInitObserver(base::OnceCallback<void(bool)> obs) {
109   init_observers_.push_back(std::move(obs));
110 }
111
112 void PrefNotifierImpl::OnPreferenceChanged(const std::string& path) {
113   FireObservers(path);
114 }
115
116 void PrefNotifierImpl::OnInitializationCompleted(bool succeeded) {
117   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
118
119   // We must move init_observers_ to a local variable before we run
120   // observers, or we can end up in this method re-entrantly before
121   // clearing the observers list.
122   PrefInitObserverList observers;
123   std::swap(observers, init_observers_);
124
125   for (auto& observer : observers)
126     std::move(observer).Run(succeeded);
127 }
128
129 void PrefNotifierImpl::FireObservers(const std::string& path) {
130   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
131
132   // Only send notifications for registered preferences.
133   if (!pref_service_->FindPreference(path))
134     return;
135
136   // Fire observers for any preference change.
137   for (auto& observer : all_prefs_pref_observers_)
138     observer.OnPreferenceChanged(pref_service_, path);
139
140   auto observer_iterator = pref_observers_.find(path);
141   if (observer_iterator == pref_observers_.end())
142     return;
143
144   for (PrefObserver& observer : *(observer_iterator->second))
145     observer.OnPreferenceChanged(pref_service_, path);
146 }
147
148 void PrefNotifierImpl::SetPrefService(PrefService* pref_service) {
149   DCHECK(pref_service_ == nullptr);
150   pref_service_ = pref_service;
151 }