blob: 33eb9e9b1a8631aa855de77cb72b2c5cb1a5d9a1 [file] [log] [blame]
[email protected]42c037e2012-06-26 22:23:321// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]acd78969c2010-12-08 09:49:112// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
brettwf00b9b42016-02-01 22:11:385#include "components/prefs/pref_notifier_impl.h"
[email protected]acd78969c2010-12-08 09:49:116
Dominic Battreaf8b8e42019-08-09 18:17:567#include "base/debug/alias.h"
Dominic Battre343d75122019-03-29 21:47:498#include "base/debug/dump_without_crashing.h"
[email protected]42c037e2012-06-26 22:23:329#include "base/logging.h"
avia92d13b2016-09-21 07:48:4010#include "base/memory/ptr_util.h"
Dominic Battreaf8b8e42019-08-09 18:17:5611#include "base/strings/strcat.h"
brettwf00b9b42016-02-01 22:11:3812#include "components/prefs/pref_service.h"
[email protected]acd78969c2010-12-08 09:49:1113
avia92d13b2016-09-21 07:48:4014PrefNotifierImpl::PrefNotifierImpl() : pref_service_(nullptr) {}
[email protected]361d37f62011-11-22 10:37:0215
[email protected]acd78969c2010-12-08 09:49:1116PrefNotifierImpl::PrefNotifierImpl(PrefService* service)
17 : pref_service_(service) {
18}
19
20PrefNotifierImpl::~PrefNotifierImpl() {
[email protected]5b7238f2013-04-22 15:56:4021 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]acd78969c2010-12-08 09:49:1122
23 // Verify that there are no pref observers when we shut down.
avia92d13b2016-09-21 07:48:4024 for (const auto& observer_list : pref_observers_) {
Dominic Battre343d75122019-03-29 21:47:4925 if (observer_list.second->begin() != observer_list.second->end()) {
26 // Generally, there should not be any subscribers left when the profile
27 // is destroyed because a) those may indicate that the subscriber class
28 // maintains an active pointer to the profile that might be used for
29 // accessing a destroyed profile and b) those subscribers will try to
30 // unsubscribe from a PrefService that has been destroyed with the
31 // profile.
32 // There is one exception that is safe: Static objects that are leaked
33 // on process termination, if these objects just subscribe to preferences
34 // and never access the profile after destruction. As these objects are
35 // leaked on termination, it is guaranteed that they don't attempt to
36 // unsubscribe.
37 const auto& pref_name = observer_list.first;
Dominic Battreaf8b8e42019-08-09 18:17:5638 std::string message = base::StrCat(
39 {"Pref observer for ", pref_name, " found at shutdown."});
40 LOG(WARNING) << message;
41 DEBUG_ALIAS_FOR_CSTR(aliased_message, message.c_str(), 128);
Dominic Battre343d75122019-03-29 21:47:4942
43 // TODO(crbug.com/942491, 946668, 945772) The following code collects
44 // stacktraces that show how the profile is destroyed that owns
45 // preferences which are known to have subscriptions outliving the
46 // profile.
47 if (
48 // For GlobalMenuBarX11, crbug.com/946668
49 pref_name == "bookmark_bar.show_on_all_tabs" ||
50 // For BrowserWindowPropertyManager, crbug.com/942491
51 pref_name == "profile.icon_version" ||
52 // For BrowserWindowDefaultTouchBar, crbug.com/945772
53 pref_name == "default_search_provider_data.template_url_data") {
Dominic Battre343d75122019-03-29 21:47:4954 base::debug::DumpWithoutCrashing();
55 }
56 }
[email protected]acd78969c2010-12-08 09:49:1157 }
58
[email protected]a6a7ced2012-11-01 17:24:1859 // Same for initialization observers.
60 if (!init_observers_.empty())
61 LOG(WARNING) << "Init observer found at shutdown.";
62
[email protected]acd78969c2010-12-08 09:49:1163 pref_observers_.clear();
[email protected]a6a7ced2012-11-01 17:24:1864 init_observers_.clear();
[email protected]acd78969c2010-12-08 09:49:1165}
66
georgesak7da6e9d2014-12-03 01:10:2967void PrefNotifierImpl::AddPrefObserver(const std::string& path,
[email protected]a6a7ced2012-11-01 17:24:1868 PrefObserver* obs) {
Dominic Battre3ee566612019-11-29 18:00:5169 DCHECK(thread_checker_.CalledOnValidThread());
70
[email protected]acd78969c2010-12-08 09:49:1171 // Get the pref observer list associated with the path.
avia92d13b2016-09-21 07:48:4072 PrefObserverList* observer_list = nullptr;
73 auto observer_iterator = pref_observers_.find(path);
[email protected]acd78969c2010-12-08 09:49:1174 if (observer_iterator == pref_observers_.end()) {
[email protected]a6a7ced2012-11-01 17:24:1875 observer_list = new PrefObserverList;
avia92d13b2016-09-21 07:48:4076 pref_observers_[path] = base::WrapUnique(observer_list);
[email protected]acd78969c2010-12-08 09:49:1177 } else {
avia92d13b2016-09-21 07:48:4078 observer_list = observer_iterator->second.get();
[email protected]acd78969c2010-12-08 09:49:1179 }
80
[email protected]a6a7ced2012-11-01 17:24:1881 // Add the pref observer. ObserverList will DCHECK if it already is
82 // in the list.
[email protected]acd78969c2010-12-08 09:49:1183 observer_list->AddObserver(obs);
84}
85
georgesak7da6e9d2014-12-03 01:10:2986void PrefNotifierImpl::RemovePrefObserver(const std::string& path,
[email protected]a6a7ced2012-11-01 17:24:1887 PrefObserver* obs) {
[email protected]5b7238f2013-04-22 15:56:4088 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]acd78969c2010-12-08 09:49:1189
avia92d13b2016-09-21 07:48:4090 auto observer_iterator = pref_observers_.find(path);
[email protected]acd78969c2010-12-08 09:49:1191 if (observer_iterator == pref_observers_.end()) {
92 return;
93 }
94
avia92d13b2016-09-21 07:48:4095 PrefObserverList* observer_list = observer_iterator->second.get();
[email protected]acd78969c2010-12-08 09:49:1196 observer_list->RemoveObserver(obs);
97}
98
Brett Wilson21cf626a2017-09-07 00:30:2099void PrefNotifierImpl::AddPrefObserverAllPrefs(PrefObserver* observer) {
100 DCHECK(thread_checker_.CalledOnValidThread());
101 all_prefs_pref_observers_.AddObserver(observer);
102}
103
104void PrefNotifierImpl::RemovePrefObserverAllPrefs(PrefObserver* observer) {
105 DCHECK(thread_checker_.CalledOnValidThread());
106 all_prefs_pref_observers_.RemoveObserver(observer);
107}
108
Kenichi Ishibashif958ad62017-12-19 02:43:14109void PrefNotifierImpl::AddInitObserver(base::OnceCallback<void(bool)> obs) {
110 init_observers_.push_back(std::move(obs));
[email protected]a6a7ced2012-11-01 17:24:18111}
112
[email protected]acd78969c2010-12-08 09:49:11113void PrefNotifierImpl::OnPreferenceChanged(const std::string& path) {
114 FireObservers(path);
115}
116
[email protected]845b43a82011-05-11 10:14:43117void PrefNotifierImpl::OnInitializationCompleted(bool succeeded) {
[email protected]5b7238f2013-04-22 15:56:40118 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]acd78969c2010-12-08 09:49:11119
Kenichi Ishibashif958ad62017-12-19 02:43:14120 // We must move init_observers_ to a local variable before we run
[email protected]a6a7ced2012-11-01 17:24:18121 // observers, or we can end up in this method re-entrantly before
122 // clearing the observers list.
Kenichi Ishibashif958ad62017-12-19 02:43:14123 PrefInitObserverList observers;
124 std::swap(observers, init_observers_);
[email protected]a6a7ced2012-11-01 17:24:18125
avia92d13b2016-09-21 07:48:40126 for (auto& observer : observers)
Kenichi Ishibashif958ad62017-12-19 02:43:14127 std::move(observer).Run(succeeded);
[email protected]acd78969c2010-12-08 09:49:11128}
129
130void PrefNotifierImpl::FireObservers(const std::string& path) {
[email protected]5b7238f2013-04-22 15:56:40131 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]acd78969c2010-12-08 09:49:11132
133 // Only send notifications for registered preferences.
georgesak7da6e9d2014-12-03 01:10:29134 if (!pref_service_->FindPreference(path))
[email protected]acd78969c2010-12-08 09:49:11135 return;
136
Brett Wilson21cf626a2017-09-07 00:30:20137 // Fire observers for any preference change.
138 for (auto& observer : all_prefs_pref_observers_)
139 observer.OnPreferenceChanged(pref_service_, path);
140
avia92d13b2016-09-21 07:48:40141 auto observer_iterator = pref_observers_.find(path);
[email protected]acd78969c2010-12-08 09:49:11142 if (observer_iterator == pref_observers_.end())
143 return;
144
ericwilligers42b92c12016-10-24 20:21:13145 for (PrefObserver& observer : *(observer_iterator->second))
146 observer.OnPreferenceChanged(pref_service_, path);
[email protected]acd78969c2010-12-08 09:49:11147}
[email protected]361d37f62011-11-22 10:37:02148
149void PrefNotifierImpl::SetPrefService(PrefService* pref_service) {
avia92d13b2016-09-21 07:48:40150 DCHECK(pref_service_ == nullptr);
[email protected]361d37f62011-11-22 10:37:02151 pref_service_ = pref_service;
152}