// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/prefs/pref_notifier_impl.h"

#include "base/debug/dump_without_crashing.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "components/prefs/pref_service.h"

PrefNotifierImpl::PrefNotifierImpl() : pref_service_(nullptr) {}

PrefNotifierImpl::PrefNotifierImpl(PrefService* service)
    : pref_service_(service) {}

PrefNotifierImpl::~PrefNotifierImpl() {
  DCHECK(thread_checker_.CalledOnValidThread());

  // Verify that there are no pref observers when we shut down.
  for (const auto& observer_list : pref_observers_) {
    if (observer_list.second->begin() != observer_list.second->end()) {
      // Generally, there should not be any subscribers left when the profile
      // is destroyed because a) those may indicate that the subscriber class
      // maintains an active pointer to the profile that might be used for
      // accessing a destroyed profile and b) those subscribers will try to
      // unsubscribe from a PrefService that has been destroyed with the
      // profile.
      // There is one exception that is safe: Static objects that are leaked
      // on process termination, if these objects just subscribe to preferences
      // and never access the profile after destruction. As these objects are
      // leaked on termination, it is guaranteed that they don't attempt to
      // unsubscribe.
      const auto& pref_name = observer_list.first;
      LOG(WARNING) << "Pref observer for " << pref_name
                   << " found at shutdown.";

      // TODO(crbug.com/942491, 946668, 945772) The following code collects
      // stacktraces that show how the profile is destroyed that owns
      // preferences which are known to have subscriptions outliving the
      // profile.
      if (
          // For GlobalMenuBarX11, crbug.com/946668
          pref_name == "bookmark_bar.show_on_all_tabs" ||
          // For BrowserWindowPropertyManager, crbug.com/942491
          pref_name == "profile.icon_version" ||
          // For BrowserWindowDefaultTouchBar, crbug.com/945772
          pref_name == "default_search_provider_data.template_url_data") {
        base::debug::DumpWithoutCrashing();
      }
    }
  }

  // Same for initialization observers.
  if (!init_observers_.empty())
    LOG(WARNING) << "Init observer found at shutdown.";

  pref_observers_.clear();
  init_observers_.clear();
}

void PrefNotifierImpl::AddPrefObserver(const std::string& path,
                                       PrefObserver* obs) {
  // Get the pref observer list associated with the path.
  PrefObserverList* observer_list = nullptr;
  auto observer_iterator = pref_observers_.find(path);
  if (observer_iterator == pref_observers_.end()) {
    observer_list = new PrefObserverList;
    pref_observers_[path] = base::WrapUnique(observer_list);
  } else {
    observer_list = observer_iterator->second.get();
  }

  // Add the pref observer. ObserverList will DCHECK if it already is
  // in the list.
  observer_list->AddObserver(obs);
}

void PrefNotifierImpl::RemovePrefObserver(const std::string& path,
                                          PrefObserver* obs) {
  DCHECK(thread_checker_.CalledOnValidThread());

  auto observer_iterator = pref_observers_.find(path);
  if (observer_iterator == pref_observers_.end()) {
    return;
  }

  PrefObserverList* observer_list = observer_iterator->second.get();
  observer_list->RemoveObserver(obs);
}

void PrefNotifierImpl::AddPrefObserverAllPrefs(PrefObserver* observer) {
  DCHECK(thread_checker_.CalledOnValidThread());
  all_prefs_pref_observers_.AddObserver(observer);
}

void PrefNotifierImpl::RemovePrefObserverAllPrefs(PrefObserver* observer) {
  DCHECK(thread_checker_.CalledOnValidThread());
  all_prefs_pref_observers_.RemoveObserver(observer);
}

void PrefNotifierImpl::AddInitObserver(base::OnceCallback<void(bool)> obs) {
  init_observers_.push_back(std::move(obs));
}

void PrefNotifierImpl::OnPreferenceChanged(const std::string& path) {
  FireObservers(path);
}

void PrefNotifierImpl::OnInitializationCompleted(bool succeeded) {
  DCHECK(thread_checker_.CalledOnValidThread());

  // We must move init_observers_ to a local variable before we run
  // observers, or we can end up in this method re-entrantly before
  // clearing the observers list.
  PrefInitObserverList observers;
  std::swap(observers, init_observers_);

  for (auto& observer : observers)
    std::move(observer).Run(succeeded);
}

void PrefNotifierImpl::FireObservers(const std::string& path) {
  DCHECK(thread_checker_.CalledOnValidThread());

  // Only send notifications for registered preferences.
  if (!pref_service_->FindPreference(path))
    return;

  // Fire observers for any preference change.
  for (auto& observer : all_prefs_pref_observers_)
    observer.OnPreferenceChanged(pref_service_, path);

  auto observer_iterator = pref_observers_.find(path);
  if (observer_iterator == pref_observers_.end())
    return;

  for (PrefObserver& observer : *(observer_iterator->second))
    observer.OnPreferenceChanged(pref_service_, path);
}

void PrefNotifierImpl::SetPrefService(PrefService* pref_service) {
  DCHECK(pref_service_ == nullptr);
  pref_service_ = pref_service;
}
