blob: 9d004dbd8a094e207444c2563f1496c3ab097bc2 [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 Battre343d75122019-03-29 21:47:497#include "base/debug/alias.h"
8#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"
brettwf00b9b42016-02-01 22:11:3811#include "components/prefs/pref_service.h"
[email protected]acd78969c2010-12-08 09:49:1112
avia92d13b2016-09-21 07:48:4013PrefNotifierImpl::PrefNotifierImpl() : pref_service_(nullptr) {}
[email protected]361d37f62011-11-22 10:37:0214
[email protected]acd78969c2010-12-08 09:49:1115PrefNotifierImpl::PrefNotifierImpl(PrefService* service)
16 : pref_service_(service) {
17}
18
19PrefNotifierImpl::~PrefNotifierImpl() {
[email protected]5b7238f2013-04-22 15:56:4020 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]acd78969c2010-12-08 09:49:1121
22 // Verify that there are no pref observers when we shut down.
avia92d13b2016-09-21 07:48:4023 for (const auto& observer_list : pref_observers_) {
Dominic Battre343d75122019-03-29 21:47:4924 if (observer_list.second->begin() != observer_list.second->end()) {
25 // Generally, there should not be any subscribers left when the profile
26 // is destroyed because a) those may indicate that the subscriber class
27 // maintains an active pointer to the profile that might be used for
28 // accessing a destroyed profile and b) those subscribers will try to
29 // unsubscribe from a PrefService that has been destroyed with the
30 // profile.
31 // There is one exception that is safe: Static objects that are leaked
32 // on process termination, if these objects just subscribe to preferences
33 // and never access the profile after destruction. As these objects are
34 // leaked on termination, it is guaranteed that they don't attempt to
35 // unsubscribe.
36 const auto& pref_name = observer_list.first;
37 LOG(WARNING) << "Pref observer for " << pref_name
38 << " found at shutdown.";
39
40 // TODO(crbug.com/942491, 946668, 945772) The following code collects
41 // stacktraces that show how the profile is destroyed that owns
42 // preferences which are known to have subscriptions outliving the
43 // profile.
44 if (
45 // For GlobalMenuBarX11, crbug.com/946668
46 pref_name == "bookmark_bar.show_on_all_tabs" ||
47 // For BrowserWindowPropertyManager, crbug.com/942491
48 pref_name == "profile.icon_version" ||
49 // For BrowserWindowDefaultTouchBar, crbug.com/945772
50 pref_name == "default_search_provider_data.template_url_data") {
51 const bool is_incognito_profile =
52 pref_service_->HasInMemoryUserPrefStore();
53 base::debug::Alias(&is_incognito_profile);
54 // Export value of is_incognito_profile to a string so that `grep`
55 // is a sufficient tool to analyze crashdumps.
56 char is_incognito_profile_string[32];
57 strncpy(is_incognito_profile_string,
58 is_incognito_profile ? "is_incognito: yes" : "is_incognito: no",
59 sizeof(is_incognito_profile_string));
60 base::debug::Alias(&is_incognito_profile_string);
61 base::debug::DumpWithoutCrashing();
62 }
63 }
[email protected]acd78969c2010-12-08 09:49:1164 }
65
[email protected]a6a7ced2012-11-01 17:24:1866 // Same for initialization observers.
67 if (!init_observers_.empty())
68 LOG(WARNING) << "Init observer found at shutdown.";
69
[email protected]acd78969c2010-12-08 09:49:1170 pref_observers_.clear();
[email protected]a6a7ced2012-11-01 17:24:1871 init_observers_.clear();
[email protected]acd78969c2010-12-08 09:49:1172}
73
georgesak7da6e9d2014-12-03 01:10:2974void PrefNotifierImpl::AddPrefObserver(const std::string& path,
[email protected]a6a7ced2012-11-01 17:24:1875 PrefObserver* obs) {
[email protected]acd78969c2010-12-08 09:49:1176 // Get the pref observer list associated with the path.
avia92d13b2016-09-21 07:48:4077 PrefObserverList* observer_list = nullptr;
78 auto observer_iterator = pref_observers_.find(path);
[email protected]acd78969c2010-12-08 09:49:1179 if (observer_iterator == pref_observers_.end()) {
[email protected]a6a7ced2012-11-01 17:24:1880 observer_list = new PrefObserverList;
avia92d13b2016-09-21 07:48:4081 pref_observers_[path] = base::WrapUnique(observer_list);
[email protected]acd78969c2010-12-08 09:49:1182 } else {
avia92d13b2016-09-21 07:48:4083 observer_list = observer_iterator->second.get();
[email protected]acd78969c2010-12-08 09:49:1184 }
85
[email protected]a6a7ced2012-11-01 17:24:1886 // Add the pref observer. ObserverList will DCHECK if it already is
87 // in the list.
[email protected]acd78969c2010-12-08 09:49:1188 observer_list->AddObserver(obs);
89}
90
georgesak7da6e9d2014-12-03 01:10:2991void PrefNotifierImpl::RemovePrefObserver(const std::string& path,
[email protected]a6a7ced2012-11-01 17:24:1892 PrefObserver* obs) {
[email protected]5b7238f2013-04-22 15:56:4093 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]acd78969c2010-12-08 09:49:1194
avia92d13b2016-09-21 07:48:4095 auto observer_iterator = pref_observers_.find(path);
[email protected]acd78969c2010-12-08 09:49:1196 if (observer_iterator == pref_observers_.end()) {
97 return;
98 }
99
avia92d13b2016-09-21 07:48:40100 PrefObserverList* observer_list = observer_iterator->second.get();
[email protected]acd78969c2010-12-08 09:49:11101 observer_list->RemoveObserver(obs);
102}
103
Brett Wilson21cf626a2017-09-07 00:30:20104void PrefNotifierImpl::AddPrefObserverAllPrefs(PrefObserver* observer) {
105 DCHECK(thread_checker_.CalledOnValidThread());
106 all_prefs_pref_observers_.AddObserver(observer);
107}
108
109void PrefNotifierImpl::RemovePrefObserverAllPrefs(PrefObserver* observer) {
110 DCHECK(thread_checker_.CalledOnValidThread());
111 all_prefs_pref_observers_.RemoveObserver(observer);
112}
113
Kenichi Ishibashif958ad62017-12-19 02:43:14114void PrefNotifierImpl::AddInitObserver(base::OnceCallback<void(bool)> obs) {
115 init_observers_.push_back(std::move(obs));
[email protected]a6a7ced2012-11-01 17:24:18116}
117
[email protected]acd78969c2010-12-08 09:49:11118void PrefNotifierImpl::OnPreferenceChanged(const std::string& path) {
119 FireObservers(path);
120}
121
[email protected]845b43a82011-05-11 10:14:43122void PrefNotifierImpl::OnInitializationCompleted(bool succeeded) {
[email protected]5b7238f2013-04-22 15:56:40123 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]acd78969c2010-12-08 09:49:11124
Kenichi Ishibashif958ad62017-12-19 02:43:14125 // We must move init_observers_ to a local variable before we run
[email protected]a6a7ced2012-11-01 17:24:18126 // observers, or we can end up in this method re-entrantly before
127 // clearing the observers list.
Kenichi Ishibashif958ad62017-12-19 02:43:14128 PrefInitObserverList observers;
129 std::swap(observers, init_observers_);
[email protected]a6a7ced2012-11-01 17:24:18130
avia92d13b2016-09-21 07:48:40131 for (auto& observer : observers)
Kenichi Ishibashif958ad62017-12-19 02:43:14132 std::move(observer).Run(succeeded);
[email protected]acd78969c2010-12-08 09:49:11133}
134
135void PrefNotifierImpl::FireObservers(const std::string& path) {
[email protected]5b7238f2013-04-22 15:56:40136 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]acd78969c2010-12-08 09:49:11137
138 // Only send notifications for registered preferences.
georgesak7da6e9d2014-12-03 01:10:29139 if (!pref_service_->FindPreference(path))
[email protected]acd78969c2010-12-08 09:49:11140 return;
141
Brett Wilson21cf626a2017-09-07 00:30:20142 // Fire observers for any preference change.
143 for (auto& observer : all_prefs_pref_observers_)
144 observer.OnPreferenceChanged(pref_service_, path);
145
avia92d13b2016-09-21 07:48:40146 auto observer_iterator = pref_observers_.find(path);
[email protected]acd78969c2010-12-08 09:49:11147 if (observer_iterator == pref_observers_.end())
148 return;
149
ericwilligers42b92c12016-10-24 20:21:13150 for (PrefObserver& observer : *(observer_iterator->second))
151 observer.OnPreferenceChanged(pref_service_, path);
[email protected]acd78969c2010-12-08 09:49:11152}
[email protected]361d37f62011-11-22 10:37:02153
154void PrefNotifierImpl::SetPrefService(PrefService* pref_service) {
avia92d13b2016-09-21 07:48:40155 DCHECK(pref_service_ == nullptr);
[email protected]361d37f62011-11-22 10:37:02156 pref_service_ = pref_service;
157}