// Copyright 2014 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/search_engines/default_search_manager.h"

#include <algorithm>
#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
#include "base/i18n/case_conversion.h"
#include "base/logging.h"
#include "base/prefs/pref_service.h"
#include "base/prefs/pref_value_map.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/search_engines/search_engines_pref_names.h"
#include "components/search_engines/template_url_data.h"
#include "components/search_engines/template_url_prepopulate_data.h"

namespace {

bool g_fallback_search_engines_disabled = false;

}  // namespace

// A dictionary to hold all data related to the Default Search Engine.
// Eventually, this should replace all the data stored in the
// default_search_provider.* prefs.
const char DefaultSearchManager::kDefaultSearchProviderDataPrefName[] =
    "default_search_provider_data.template_url_data";

const char DefaultSearchManager::kID[] = "id";
const char DefaultSearchManager::kShortName[] = "short_name";
const char DefaultSearchManager::kKeyword[] = "keyword";
const char DefaultSearchManager::kPrepopulateID[] = "prepopulate_id";
const char DefaultSearchManager::kSyncGUID[] = "synced_guid";

const char DefaultSearchManager::kURL[] = "url";
const char DefaultSearchManager::kSuggestionsURL[] = "suggestions_url";
const char DefaultSearchManager::kInstantURL[] = "instant_url";
const char DefaultSearchManager::kImageURL[] = "image_url";
const char DefaultSearchManager::kNewTabURL[] = "new_tab_url";
const char DefaultSearchManager::kFaviconURL[] = "favicon_url";
const char DefaultSearchManager::kOriginatingURL[] = "originating_url";

const char DefaultSearchManager::kSearchURLPostParams[] =
    "search_url_post_params";
const char DefaultSearchManager::kSuggestionsURLPostParams[] =
    "suggestions_url_post_params";
const char DefaultSearchManager::kInstantURLPostParams[] =
    "instant_url_post_params";
const char DefaultSearchManager::kImageURLPostParams[] =
    "image_url_post_params";

const char DefaultSearchManager::kSafeForAutoReplace[] = "safe_for_autoreplace";
const char DefaultSearchManager::kInputEncodings[] = "input_encodings";

const char DefaultSearchManager::kDateCreated[] = "date_created";
const char DefaultSearchManager::kLastModified[] = "last_modified";

const char DefaultSearchManager::kUsageCount[] = "usage_count";
const char DefaultSearchManager::kAlternateURLs[] = "alternate_urls";
const char DefaultSearchManager::kSearchTermsReplacementKey[] =
    "search_terms_replacement_key";
const char DefaultSearchManager::kCreatedByPolicy[] = "created_by_policy";
const char DefaultSearchManager::kDisabledByPolicy[] = "disabled_by_policy";

DefaultSearchManager::DefaultSearchManager(
    PrefService* pref_service,
    const ObserverCallback& change_observer)
    : pref_service_(pref_service),
      change_observer_(change_observer),
      default_search_controlled_by_policy_(false) {
  if (pref_service_) {
    pref_change_registrar_.Init(pref_service_);
    pref_change_registrar_.Add(
        kDefaultSearchProviderDataPrefName,
        base::Bind(&DefaultSearchManager::OnDefaultSearchPrefChanged,
                   base::Unretained(this)));
    pref_change_registrar_.Add(
        prefs::kSearchProviderOverrides,
        base::Bind(&DefaultSearchManager::OnOverridesPrefChanged,
                   base::Unretained(this)));
  }
  LoadPrepopulatedDefaultSearch();
  LoadDefaultSearchEngineFromPrefs();
}

DefaultSearchManager::~DefaultSearchManager() {
}

// static
void DefaultSearchManager::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* registry) {
  registry->RegisterDictionaryPref(
      kDefaultSearchProviderDataPrefName,
      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
}

// static
void DefaultSearchManager::AddPrefValueToMap(base::DictionaryValue* value,
                                             PrefValueMap* pref_value_map) {
  pref_value_map->SetValue(kDefaultSearchProviderDataPrefName, value);
}

// static
void DefaultSearchManager::SetFallbackSearchEnginesDisabledForTesting(
    bool disabled) {
  g_fallback_search_engines_disabled = disabled;
}

TemplateURLData* DefaultSearchManager::GetDefaultSearchEngine(
    Source* source) const {
  if (default_search_controlled_by_policy_) {
    if (source)
      *source = FROM_POLICY;
    return prefs_default_search_.get();
  }
  if (extension_default_search_) {
    if (source)
      *source = FROM_EXTENSION;
    return extension_default_search_.get();
  }
  if (prefs_default_search_) {
    if (source)
      *source = FROM_USER;
    return prefs_default_search_.get();
  }

  if (source)
    *source = FROM_FALLBACK;
  return g_fallback_search_engines_disabled ?
      NULL : fallback_default_search_.get();
}

DefaultSearchManager::Source
DefaultSearchManager::GetDefaultSearchEngineSource() const {
  Source source;
  GetDefaultSearchEngine(&source);
  return source;
}

void DefaultSearchManager::SetUserSelectedDefaultSearchEngine(
    const TemplateURLData& data) {
  if (!pref_service_) {
    prefs_default_search_.reset(new TemplateURLData(data));
    MergePrefsDataWithPrepopulated();
    NotifyObserver();
    return;
  }

  base::DictionaryValue url_dict;
  url_dict.SetString(kID, base::Int64ToString(data.id));
  url_dict.SetString(kShortName, data.short_name);
  url_dict.SetString(kKeyword, data.keyword());
  url_dict.SetInteger(kPrepopulateID, data.prepopulate_id);
  url_dict.SetString(kSyncGUID, data.sync_guid);

  url_dict.SetString(kURL, data.url());
  url_dict.SetString(kSuggestionsURL, data.suggestions_url);
  url_dict.SetString(kInstantURL, data.instant_url);
  url_dict.SetString(kImageURL, data.image_url);
  url_dict.SetString(kNewTabURL, data.new_tab_url);
  url_dict.SetString(kFaviconURL, data.favicon_url.spec());
  url_dict.SetString(kOriginatingURL, data.originating_url.spec());

  url_dict.SetString(kSearchURLPostParams, data.search_url_post_params);
  url_dict.SetString(kSuggestionsURLPostParams,
                     data.suggestions_url_post_params);
  url_dict.SetString(kInstantURLPostParams, data.instant_url_post_params);
  url_dict.SetString(kImageURLPostParams, data.image_url_post_params);

  url_dict.SetBoolean(kSafeForAutoReplace, data.safe_for_autoreplace);

  url_dict.SetString(kDateCreated,
                     base::Int64ToString(data.date_created.ToInternalValue()));
  url_dict.SetString(kLastModified,
                     base::Int64ToString(data.last_modified.ToInternalValue()));
  url_dict.SetInteger(kUsageCount, data.usage_count);

  scoped_ptr<base::ListValue> alternate_urls(new base::ListValue);
  for (std::vector<std::string>::const_iterator it =
           data.alternate_urls.begin();
       it != data.alternate_urls.end(); ++it) {
    alternate_urls->AppendString(*it);
  }
  url_dict.Set(kAlternateURLs, alternate_urls.release());

  scoped_ptr<base::ListValue> encodings(new base::ListValue);
  for (std::vector<std::string>::const_iterator it =
           data.input_encodings.begin();
       it != data.input_encodings.end(); ++it) {
    encodings->AppendString(*it);
  }
  url_dict.Set(kInputEncodings, encodings.release());

  url_dict.SetString(kSearchTermsReplacementKey,
                     data.search_terms_replacement_key);

  url_dict.SetBoolean(kCreatedByPolicy, data.created_by_policy);

  pref_service_->Set(kDefaultSearchProviderDataPrefName, url_dict);
}

void DefaultSearchManager::SetExtensionControlledDefaultSearchEngine(
    const TemplateURLData& data) {
  extension_default_search_.reset(new TemplateURLData(data));
  if (GetDefaultSearchEngineSource() == FROM_EXTENSION)
    NotifyObserver();
}

void DefaultSearchManager::ClearExtensionControlledDefaultSearchEngine() {
  Source old_source = GetDefaultSearchEngineSource();
  extension_default_search_.reset();
  if (old_source == FROM_EXTENSION)
    NotifyObserver();
}

void DefaultSearchManager::ClearUserSelectedDefaultSearchEngine() {
  if (pref_service_) {
    pref_service_->ClearPref(kDefaultSearchProviderDataPrefName);
  } else {
    prefs_default_search_.reset();
    NotifyObserver();
  }
}

void DefaultSearchManager::OnDefaultSearchPrefChanged() {
  Source source = GetDefaultSearchEngineSource();
  LoadDefaultSearchEngineFromPrefs();

  // If we were/are FROM_USER or FROM_POLICY the effective DSE may have changed.
  if (source != FROM_USER && source != FROM_POLICY)
    source = GetDefaultSearchEngineSource();
  if (source == FROM_USER || source == FROM_POLICY)
    NotifyObserver();
}

void DefaultSearchManager::OnOverridesPrefChanged() {
  LoadPrepopulatedDefaultSearch();

  TemplateURLData* effective_data = GetDefaultSearchEngine(NULL);
  if (effective_data && effective_data->prepopulate_id) {
    // A user-selected, policy-selected or fallback pre-populated engine is
    // active and may have changed with this event.
    NotifyObserver();
  }
}

void DefaultSearchManager::MergePrefsDataWithPrepopulated() {
  if (!prefs_default_search_ || !prefs_default_search_->prepopulate_id)
    return;

  size_t default_search_index;
  ScopedVector<TemplateURLData> prepopulated_urls =
      TemplateURLPrepopulateData::GetPrepopulatedEngines(pref_service_,
                                                         &default_search_index);

  for (size_t i = 0; i < prepopulated_urls.size(); ++i) {
    if (prepopulated_urls[i]->prepopulate_id ==
        prefs_default_search_->prepopulate_id) {
      if (!prefs_default_search_->safe_for_autoreplace) {
        prepopulated_urls[i]->safe_for_autoreplace = false;
        prepopulated_urls[i]->SetKeyword(prefs_default_search_->keyword());
        prepopulated_urls[i]->short_name = prefs_default_search_->short_name;
      }
      prepopulated_urls[i]->id = prefs_default_search_->id;
      prepopulated_urls[i]->sync_guid = prefs_default_search_->sync_guid;
      prepopulated_urls[i]->date_created = prefs_default_search_->date_created;
      prepopulated_urls[i]->last_modified =
          prefs_default_search_->last_modified;
      prefs_default_search_.reset(prepopulated_urls[i]);
      prepopulated_urls.weak_erase(prepopulated_urls.begin() + i);
      return;
    }
  }
}

void DefaultSearchManager::LoadDefaultSearchEngineFromPrefs() {
  if (!pref_service_)
    return;

  prefs_default_search_.reset();
  const PrefService::Preference* pref =
      pref_service_->FindPreference(kDefaultSearchProviderDataPrefName);
  DCHECK(pref);
  default_search_controlled_by_policy_ = pref->IsManaged();

  const base::DictionaryValue* url_dict =
      pref_service_->GetDictionary(kDefaultSearchProviderDataPrefName);
  if (url_dict->empty())
    return;

  if (default_search_controlled_by_policy_) {
    bool disabled_by_policy = false;
    if (url_dict->GetBoolean(kDisabledByPolicy, &disabled_by_policy) &&
        disabled_by_policy)
      return;
  }

  std::string search_url;
  base::string16 keyword;
  url_dict->GetString(kURL, &search_url);
  url_dict->GetString(kKeyword, &keyword);
  if (search_url.empty() || keyword.empty())
    return;

  prefs_default_search_.reset(new TemplateURLData);
  prefs_default_search_->SetKeyword(keyword);
  prefs_default_search_->SetURL(search_url);

  std::string id;
  url_dict->GetString(kID, &id);
  base::StringToInt64(id, &prefs_default_search_->id);
  url_dict->GetString(kShortName, &prefs_default_search_->short_name);
  url_dict->GetInteger(kPrepopulateID, &prefs_default_search_->prepopulate_id);
  url_dict->GetString(kSyncGUID, &prefs_default_search_->sync_guid);

  url_dict->GetString(kSuggestionsURL, &prefs_default_search_->suggestions_url);
  url_dict->GetString(kInstantURL, &prefs_default_search_->instant_url);
  url_dict->GetString(kImageURL, &prefs_default_search_->image_url);
  url_dict->GetString(kNewTabURL, &prefs_default_search_->new_tab_url);

  std::string favicon_url;
  std::string originating_url;
  url_dict->GetString(kFaviconURL, &favicon_url);
  url_dict->GetString(kOriginatingURL, &originating_url);
  prefs_default_search_->favicon_url = GURL(favicon_url);
  prefs_default_search_->originating_url = GURL(originating_url);

  url_dict->GetString(kSearchURLPostParams,
                      &prefs_default_search_->search_url_post_params);
  url_dict->GetString(kSuggestionsURLPostParams,
                      &prefs_default_search_->suggestions_url_post_params);
  url_dict->GetString(kInstantURLPostParams,
                      &prefs_default_search_->instant_url_post_params);
  url_dict->GetString(kImageURLPostParams,
                      &prefs_default_search_->image_url_post_params);

  url_dict->GetBoolean(kSafeForAutoReplace,
                       &prefs_default_search_->safe_for_autoreplace);

  std::string date_created_str;
  std::string last_modified_str;
  url_dict->GetString(kDateCreated, &date_created_str);
  url_dict->GetString(kLastModified, &last_modified_str);

  int64 date_created = 0;
  if (base::StringToInt64(date_created_str, &date_created)) {
    prefs_default_search_->date_created =
        base::Time::FromInternalValue(date_created);
  }

  int64 last_modified = 0;
  if (base::StringToInt64(date_created_str, &last_modified)) {
    prefs_default_search_->last_modified =
        base::Time::FromInternalValue(last_modified);
  }

  url_dict->GetInteger(kUsageCount, &prefs_default_search_->usage_count);

  const base::ListValue* alternate_urls = NULL;
  if (url_dict->GetList(kAlternateURLs, &alternate_urls)) {
    for (base::ListValue::const_iterator it = alternate_urls->begin();
         it != alternate_urls->end();
         ++it) {
      std::string alternate_url;
      if ((*it)->GetAsString(&alternate_url))
        prefs_default_search_->alternate_urls.push_back(alternate_url);
    }
  }

  const base::ListValue* encodings = NULL;
  if (url_dict->GetList(kInputEncodings, &encodings)) {
    for (base::ListValue::const_iterator it = encodings->begin();
         it != encodings->end();
         ++it) {
      std::string encoding;
      if ((*it)->GetAsString(&encoding))
        prefs_default_search_->input_encodings.push_back(encoding);
    }
  }

  url_dict->GetString(kSearchTermsReplacementKey,
                      &prefs_default_search_->search_terms_replacement_key);

  url_dict->GetBoolean(kCreatedByPolicy,
                       &prefs_default_search_->created_by_policy);

  prefs_default_search_->show_in_default_list = true;
  MergePrefsDataWithPrepopulated();
}

void DefaultSearchManager::LoadPrepopulatedDefaultSearch() {
  scoped_ptr<TemplateURLData> data =
      TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(pref_service_);
  fallback_default_search_ = data.Pass();
  MergePrefsDataWithPrepopulated();
}

void DefaultSearchManager::NotifyObserver() {
  if (!change_observer_.is_null()) {
    Source source = FROM_FALLBACK;
    TemplateURLData* data = GetDefaultSearchEngine(&source);
    change_observer_.Run(data, source);
  }
}
