// Copyright 2016 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 "chrome/browser/ui/webui/settings/search_engines_handler.h"

#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
#include "chrome/browser/ui/search_engines/template_url_table_model.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/grit/locale_settings.h"
#include "components/search_engines/template_url.h"
#include "components/search_engines/template_url_service.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_ui.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"

namespace {
// The following strings need to match with the IDs of the paper-input elements
// at settings/search_engines_page/add_search_engine_dialog.html.
const char kSearchEngineField[] = "searchEngine";
const char kKeywordField[] = "keyword";
const char kQueryUrlField[] = "queryUrl";

// Dummy number used for indicating that a new search engine is added.
const int kNewSearchEngineIndex = -1;
}  // namespace

namespace settings {

SearchEnginesHandler::SearchEnginesHandler(Profile* profile)
    : profile_(profile), list_controller_(profile) {}

SearchEnginesHandler::~SearchEnginesHandler() {
  // TODO(tommycli): Refactor KeywordEditorController to be compatible with
  // ScopedObserver so this is no longer necessary.
  list_controller_.table_model()->SetObserver(nullptr);
}

void SearchEnginesHandler::RegisterMessages() {
  web_ui()->RegisterMessageCallback(
      "getSearchEnginesList",
      base::Bind(&SearchEnginesHandler::HandleGetSearchEnginesList,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "setDefaultSearchEngine",
      base::Bind(&SearchEnginesHandler::HandleSetDefaultSearchEngine,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "removeSearchEngine",
      base::Bind(&SearchEnginesHandler::HandleRemoveSearchEngine,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "validateSearchEngineInput",
      base::Bind(&SearchEnginesHandler::HandleValidateSearchEngineInput,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "searchEngineEditStarted",
      base::Bind(&SearchEnginesHandler::HandleSearchEngineEditStarted,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "searchEngineEditCancelled",
      base::Bind(&SearchEnginesHandler::HandleSearchEngineEditCancelled,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "searchEngineEditCompleted",
      base::Bind(&SearchEnginesHandler::HandleSearchEngineEditCompleted,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "disableExtension",
      base::Bind(&SearchEnginesHandler::HandleDisableExtension,
                 base::Unretained(this)));
}

void SearchEnginesHandler::OnJavascriptAllowed() {
  list_controller_.table_model()->SetObserver(this);
}

void SearchEnginesHandler::OnJavascriptDisallowed() {
  list_controller_.table_model()->SetObserver(nullptr);
}

std::unique_ptr<base::DictionaryValue>
SearchEnginesHandler::GetSearchEnginesList() {
  AllowJavascript();

  // Find the default engine.
  const TemplateURL* default_engine =
      list_controller_.GetDefaultSearchProvider();
  int default_index =
      list_controller_.table_model()->IndexOfTemplateURL(default_engine);

  // Build the first list (default search engines).
  std::unique_ptr<base::ListValue> defaults =
      base::WrapUnique(new base::ListValue());
  int last_default_engine_index =
      list_controller_.table_model()->last_search_engine_index();
  for (int i = 0; i < last_default_engine_index; ++i) {
    // Third argument is false, as the engine is not from an extension.
    defaults->Append(CreateDictionaryForEngine(i, i == default_index));
  }

  // Build the second list (other search engines).
  std::unique_ptr<base::ListValue> others =
      base::WrapUnique(new base::ListValue());
  int last_other_engine_index =
      list_controller_.table_model()->last_other_engine_index();
  for (int i = std::max(last_default_engine_index, 0);
       i < last_other_engine_index; ++i) {
    others->Append(CreateDictionaryForEngine(i, i == default_index));
  }

  // Build the third list (omnibox extensions).
  std::unique_ptr<base::ListValue> extensions =
      base::WrapUnique(new base::ListValue());
  int engine_count = list_controller_.table_model()->RowCount();
  for (int i = std::max(last_other_engine_index, 0); i < engine_count; ++i) {
    extensions->Append(CreateDictionaryForEngine(i, i == default_index));
  }

  std::unique_ptr<base::DictionaryValue> search_engines_info(
      new base::DictionaryValue);
  search_engines_info->Set("defaults", base::WrapUnique(defaults.release()));
  search_engines_info->Set("others", base::WrapUnique(others.release()));
  search_engines_info->Set("extensions",
                           base::WrapUnique(extensions.release()));
  return search_engines_info;
}

void SearchEnginesHandler::OnModelChanged() {
  CallJavascriptFunction("cr.webUIListenerCallback",
                         base::StringValue("search-engines-changed"),
                         *GetSearchEnginesList());
}

void SearchEnginesHandler::OnItemsChanged(int start, int length) {
  OnModelChanged();
}

void SearchEnginesHandler::OnItemsAdded(int start, int length) {
  OnModelChanged();
}

void SearchEnginesHandler::OnItemsRemoved(int start, int length) {
  OnModelChanged();
}

std::unique_ptr<base::DictionaryValue>
SearchEnginesHandler::CreateDictionaryForEngine(int index, bool is_default) {
  TemplateURLTableModel* table_model = list_controller_.table_model();
  const TemplateURL* template_url = list_controller_.GetTemplateURL(index);

  // The items which are to be written into |dict| are also described in
  // chrome/browser/resources/settings/search_engines_page/
  // in @typedef for SearchEngine. Please update it whenever you add or remove
  // any keys here.
  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
  dict->SetString("name", template_url->short_name());
  dict->SetString("displayName",
                  table_model->GetText(
                      index, IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN));
  dict->SetString(
      "keyword",
      table_model->GetText(index, IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN));
  dict->SetString("url",
                  template_url->url_ref().DisplayURL(
                      UIThreadSearchTermsData(Profile::FromWebUI(web_ui()))));
  dict->SetBoolean("urlLocked", template_url->prepopulate_id() > 0);
  GURL icon_url = template_url->favicon_url();
  if (icon_url.is_valid())
    dict->SetString("iconURL", icon_url.spec());
  dict->SetInteger("modelIndex", index);

  dict->SetBoolean("canBeRemoved", list_controller_.CanRemove(template_url));
  dict->SetBoolean("canBeDefault",
                   list_controller_.CanMakeDefault(template_url));
  dict->SetBoolean("default", is_default);
  dict->SetBoolean("canBeEdited", list_controller_.CanEdit(template_url));
  TemplateURL::Type type = template_url->GetType();
  dict->SetBoolean("isOmniboxExtension",
                   type == TemplateURL::OMNIBOX_API_EXTENSION);
  if (type == TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION ||
      type == TemplateURL::OMNIBOX_API_EXTENSION) {
    const extensions::Extension* extension =
        extensions::ExtensionRegistry::Get(Profile::FromWebUI(web_ui()))
            ->GetExtensionById(template_url->GetExtensionId(),
                               extensions::ExtensionRegistry::EVERYTHING);
    if (extension) {
      dict->Set("extension",
                extensions::util::GetExtensionInfo(extension).release());
    }
  }
  return dict;
}

void SearchEnginesHandler::HandleGetSearchEnginesList(
    const base::ListValue* args) {
  CHECK_EQ(1U, args->GetSize());
  const base::Value* callback_id;
  CHECK(args->Get(0, &callback_id));
  ResolveJavascriptCallback(*callback_id, *GetSearchEnginesList());
}

void SearchEnginesHandler::HandleSetDefaultSearchEngine(
    const base::ListValue* args) {
  int index;
  if (!ExtractIntegerValue(args, &index)) {
    NOTREACHED();
    return;
  }
  if (index < 0 || index >= list_controller_.table_model()->RowCount())
    return;

  list_controller_.MakeDefaultTemplateURL(index);

  content::RecordAction(
      base::UserMetricsAction("Options_SearchEngineSetDefault"));
}

void SearchEnginesHandler::HandleRemoveSearchEngine(
    const base::ListValue* args) {
  int index;
  if (!ExtractIntegerValue(args, &index)) {
    NOTREACHED();
    return;
  }
  if (index < 0 || index >= list_controller_.table_model()->RowCount())
    return;

  if (list_controller_.CanRemove(list_controller_.GetTemplateURL(index))) {
    list_controller_.RemoveTemplateURL(index);
    content::RecordAction(
        base::UserMetricsAction("Options_SearchEngineRemoved"));
  }
}

void SearchEnginesHandler::HandleSearchEngineEditStarted(
    const base::ListValue* args) {
  int index;
  if (!ExtractIntegerValue(args, &index)) {
    NOTREACHED();
    return;
  }

  // Allow -1, which means we are adding a new engine.
  if (index < kNewSearchEngineIndex ||
      index >= list_controller_.table_model()->RowCount()) {
    return;
  }

  edit_controller_.reset(new EditSearchEngineController(
      index == kNewSearchEngineIndex ? nullptr
                                     : list_controller_.GetTemplateURL(index),
      this, Profile::FromWebUI(web_ui())));
}

void SearchEnginesHandler::OnEditedKeyword(TemplateURL* template_url,
                                           const base::string16& title,
                                           const base::string16& keyword,
                                           const std::string& url) {
  DCHECK(!url.empty());
  if (template_url)
    list_controller_.ModifyTemplateURL(template_url, title, keyword, url);
  else
    list_controller_.AddTemplateURL(title, keyword, url);

  edit_controller_.reset();
}

void SearchEnginesHandler::HandleValidateSearchEngineInput(
    const base::ListValue* args) {
  CHECK_EQ(3U, args->GetSize());

  const base::Value* callback_id;
  std::string field_name;
  std::string field_value;
  CHECK(args->Get(0, &callback_id));
  CHECK(args->GetString(1, &field_name));
  CHECK(args->GetString(2, &field_value));
  ResolveJavascriptCallback(
      *callback_id,
      base::FundamentalValue(CheckFieldValidity(field_name, field_value)));
}

bool SearchEnginesHandler::CheckFieldValidity(const std::string& field_name,
                                              const std::string& field_value) {
  if (!edit_controller_.get())
    return false;

  bool is_valid = false;
  if (field_name.compare(kSearchEngineField) == 0)
    is_valid = edit_controller_->IsTitleValid(base::UTF8ToUTF16(field_value));
  else if (field_name.compare(kKeywordField) == 0)
    is_valid = edit_controller_->IsKeywordValid(base::UTF8ToUTF16(field_value));
  else if (field_name.compare(kQueryUrlField) == 0)
    is_valid = edit_controller_->IsURLValid(field_value);
  else
    NOTREACHED();

  return is_valid;
}

void SearchEnginesHandler::HandleSearchEngineEditCancelled(
    const base::ListValue* args) {
  if (!edit_controller_.get())
    return;
  edit_controller_->CleanUpCancelledAdd();
  edit_controller_.reset();
}

void SearchEnginesHandler::HandleSearchEngineEditCompleted(
    const base::ListValue* args) {
  if (!edit_controller_.get())
    return;
  std::string search_engine;
  std::string keyword;
  std::string query_url;
  CHECK(args->GetString(0, &search_engine));
  CHECK(args->GetString(1, &keyword));
  CHECK(args->GetString(2, &query_url));

  // Recheck validity. It's possible to get here with invalid input if e.g. the
  // user calls the right JS functions directly from the web inspector.
  if (CheckFieldValidity(kSearchEngineField, search_engine) &&
      CheckFieldValidity(kKeywordField, keyword) &&
      CheckFieldValidity(kQueryUrlField, query_url)) {
    edit_controller_->AcceptAddOrEdit(base::UTF8ToUTF16(search_engine),
                                      base::UTF8ToUTF16(keyword), query_url);
  }
}

void SearchEnginesHandler::HandleDisableExtension(
    const base::ListValue* args) {
  std::string extension_id;
  CHECK(args->GetString(0, &extension_id));
  ExtensionService* extension_service =
      extensions::ExtensionSystem::Get(profile_)->extension_service();
  DCHECK(extension_service);
  extension_service->DisableExtension(
      extension_id, extensions::Extension::DISABLE_USER_ACTION);
}

}  // namespace settings
