// 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/alias.h"
#include "base/debug/dump_without_crashing.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/strings/strcat.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;
      std::string message = base::StrCat(
          {"Pref observer for ", pref_name, " found at shutdown."});
      LOG(WARNING) << message;
      DEBUG_ALIAS_FOR_CSTR(aliased_message, message.c_str(), 128);

      // 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;
}
