// 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 "chrome/browser/ui/webui/voice_search_ui.h"

#include <string>
#include <utility>

#include "base/command_line.h"
#include "base/files/file_enumerator.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/plugins/plugin_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/hotword_service.h"
#include "chrome/browser/search/hotword_service_factory.h"
#include "chrome/browser/ui/app_list/start_page_service.h"
#include "chrome/browser/ui/webui/version_handler.h"
#include "chrome/common/channel_info.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/features.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/browser_resources.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
#include "components/prefs/pref_service.h"
#include "components/strings/grit/components_strings.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/url_data_source.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/browser/web_ui_message_handler.h"
#include "content/public/common/user_agent.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
#include "extensions/features/features.h"
#include "ui/base/l10n/l10n_util.h"

#if defined(OS_WIN)
#include "base/win/windows_version.h"
#endif

using base::ASCIIToUTF16;
using content::WebUIMessageHandler;

namespace {

content::WebUIDataSource* CreateVoiceSearchUiHtmlSource() {
  content::WebUIDataSource* html_source =
      content::WebUIDataSource::Create(chrome::kChromeUIVoiceSearchHost);

  html_source->AddLocalizedString("loadingMessage",
                                  IDS_VOICESEARCH_LOADING_MESSAGE);
  html_source->AddLocalizedString("voiceSearchLongTitle",
                                  IDS_VOICESEARCH_TITLE_MESSAGE);

  html_source->SetJsonPath("strings.js");
  html_source->AddResourcePath("about_voicesearch.js",
                               IDR_ABOUT_VOICESEARCH_JS);
  html_source->SetDefaultResource(IDR_ABOUT_VOICESEARCH_HTML);
  return html_source;
}

// Helper functions for collecting a list of key-value pairs that will
// be displayed.
void AddPair16(base::ListValue* list,
               const base::string16& key,
               const base::string16& value) {
  std::unique_ptr<base::DictionaryValue> results(new base::DictionaryValue());
  results->SetString("key", key);
  results->SetString("value", value);
  list->Append(std::move(results));
}

void AddPair(base::ListValue* list,
             const base::StringPiece& key,
             const base::StringPiece& value) {
  AddPair16(list, UTF8ToUTF16(key), UTF8ToUTF16(value));
}

void AddPairBool(base::ListValue* list,
                 const base::StringPiece& key,
                 bool value) {
  AddPair(list, key, value ? "Yes" : "No");
}

// Generate an empty data-pair which acts as a line break.
void AddLineBreak(base::ListValue* list) {
  AddPair(list, "", "");
}

void AddSharedModulePlatformsOnFileThread(base::ListValue* list,
                                          const base::FilePath& path,
                                          base::Closure callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);

  if (!path.empty()) {
    // Display available platforms for shared module.
    base::FilePath platforms_path = path.AppendASCII("_platform_specific");
    base::FileEnumerator enumerator(
        platforms_path, false, base::FileEnumerator::DIRECTORIES);
    base::string16 files;
    for (base::FilePath name = enumerator.Next();
         !name.empty();
         name = enumerator.Next()) {
      files += name.BaseName().LossyDisplayName() + ASCIIToUTF16(" ");
    }
    AddPair16(list,
              ASCIIToUTF16("Shared Module Platforms"),
              files.empty() ? ASCIIToUTF16("undefined") : files);
    AddLineBreak(list);
  }

  content::BrowserThread::PostTask(content::BrowserThread::UI,
                                   FROM_HERE,
                                   callback);
}

////////////////////////////////////////////////////////////////////////////////
//
// VoiceSearchDomHandler
//
////////////////////////////////////////////////////////////////////////////////

// The handler for Javascript messages for the about:flags page.
class VoiceSearchDomHandler : public WebUIMessageHandler {
 public:
  explicit VoiceSearchDomHandler(Profile* profile)
      : profile_(profile),
        weak_factory_(this) {}

  ~VoiceSearchDomHandler() override {}

  // WebUIMessageHandler implementation.
  void RegisterMessages() override {
    web_ui()->RegisterMessageCallback(
        "requestVoiceSearchInfo",
        base::Bind(&VoiceSearchDomHandler::HandleRequestVoiceSearchInfo,
                   base::Unretained(this)));
  }

 private:
  // Callback for the "requestVoiceSearchInfo" message. No arguments.
  void HandleRequestVoiceSearchInfo(const base::ListValue* args) {
    PopulatePageInformation();
  }

  void ReturnVoiceSearchInfo(std::unique_ptr<base::ListValue> info) {
    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
    DCHECK(info);
    base::DictionaryValue voiceSearchInfo;
    voiceSearchInfo.Set("voiceSearchInfo", std::move(info));
    web_ui()->CallJavascriptFunctionUnsafe("returnVoiceSearchInfo",
                                           voiceSearchInfo);
  }

  // Fill in the data to be displayed on the page.
  void PopulatePageInformation() {
    // Store Key-Value pairs of about-information.
    std::unique_ptr<base::ListValue> list(new base::ListValue());

    // Populate information.
    AddOperatingSystemInfo(list.get());
    AddAudioInfo(list.get());
    AddLanguageInfo(list.get());
    AddHotwordInfo(list.get());
    AddAppListInfo(list.get());

    AddExtensionInfo(extension_misc::kHotwordNewExtensionId,
                     "Extension",
                     list.get());

    AddExtensionInfo(extension_misc::kHotwordSharedModuleId,
                     "Shared Module",
                     list.get());

    base::FilePath path;
    extensions::ExtensionSystem* extension_system =
        extensions::ExtensionSystem::Get(profile_);
    if (extension_system) {
      ExtensionService* extension_service =
          extension_system->extension_service();
      const extensions::Extension* extension =
          extension_service->GetExtensionById(
              extension_misc::kHotwordSharedModuleId, true);
      if (extension)
        path = extension->path();
    }
    base::ListValue* raw_list = list.get();
    content::BrowserThread::PostTask(
        content::BrowserThread::FILE, FROM_HERE,
        base::Bind(&AddSharedModulePlatformsOnFileThread, raw_list, path,
                   base::Bind(&VoiceSearchDomHandler::ReturnVoiceSearchInfo,
                              weak_factory_.GetWeakPtr(),
                              base::Passed(std::move(list)))));
  }

  // Adds information regarding the system and chrome version info to list.
  void AddOperatingSystemInfo(base::ListValue* list)  {
    // Obtain the Chrome version info.
    AddPair(list,
            l10n_util::GetStringUTF8(IDS_PRODUCT_NAME),
            version_info::GetVersionNumber() + " (" +
            chrome::GetChannelString() + ")");

    // OS version information.
    std::string os_label = version_info::GetOSType();
#if defined(OS_WIN)
    base::win::OSInfo* os = base::win::OSInfo::GetInstance();
    switch (os->version()) {
      case base::win::VERSION_XP:
        os_label += " XP";
        break;
      case base::win::VERSION_SERVER_2003:
        os_label += " Server 2003 or XP Pro 64 bit";
        break;
      case base::win::VERSION_VISTA:
        os_label += " Vista or Server 2008";
        break;
      case base::win::VERSION_WIN7:
        os_label += " 7 or Server 2008 R2";
        break;
      case base::win::VERSION_WIN8:
        os_label += " 8 or Server 2012";
        break;
      default:
        os_label += " UNKNOWN";
        break;
    }
    os_label += " SP" + base::IntToString(os->service_pack().major);

    if (os->service_pack().minor > 0)
      os_label += "." + base::IntToString(os->service_pack().minor);

    if (os->architecture() == base::win::OSInfo::X64_ARCHITECTURE)
      os_label += " 64 bit";
#endif
    AddPair(list, l10n_util::GetStringUTF8(IDS_VERSION_UI_OS), os_label);

    AddLineBreak(list);
  }

  // Adds information regarding audio to the list.
  void AddAudioInfo(base::ListValue* list) {
    // NaCl and its associated functions are not available on most mobile
    // platforms. ENABLE_EXTENSIONS covers those platforms and hey would not
    // allow Hotwording anyways since it is an extension.
    std::string nacl_enabled = "not available";
#if BUILDFLAG(ENABLE_EXTENSIONS)
    nacl_enabled = "No";
    // Determine if NaCl is available.
    base::FilePath path;
    if (PathService::Get(chrome::FILE_NACL_PLUGIN, &path)) {
      content::WebPluginInfo info;
      PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile_).get();
      if (content::PluginService::GetInstance()->GetPluginInfoByPath(path,
                                                                     &info) &&
          plugin_prefs->IsPluginEnabled(info)) {
        nacl_enabled = "Yes";
      }
    }
#endif

    AddPair(list, "NaCl Enabled", nacl_enabled);

    HotwordService* hotword_service =
        HotwordServiceFactory::GetForProfile(profile_);
    AddPairBool(list, "Microphone Present",
                hotword_service && hotword_service->microphone_available());

    AddPairBool(list, "Audio Capture Allowed",
                profile_->GetPrefs()->GetBoolean(prefs::kAudioCaptureAllowed));

    AddLineBreak(list);
  }

  // Adds information regarding languages to the list.
  void AddLanguageInfo(base::ListValue* list) {
    std::string locale =
#if defined(OS_CHROMEOS)
        // On ChromeOS locale is per-profile.
        profile_->GetPrefs()->GetString(prefs::kApplicationLocale);
#else
        g_browser_process->GetApplicationLocale();
#endif
    AddPair(list, "Current Language", locale);

    AddPair(list,
            "Hotword Previous Language",
            profile_->GetPrefs()->GetString(prefs::kHotwordPreviousLanguage));

    AddLineBreak(list);
  }

  // Adds information specific to the hotword configuration to the list.
  void AddHotwordInfo(base::ListValue* list)  {
    HotwordService* hotword_service =
        HotwordServiceFactory::GetForProfile(profile_);
    AddPairBool(list, "Hotword Module Installable",
                hotword_service && hotword_service->IsHotwordAllowed());

    AddPairBool(list, "Hotword Search Enabled",
                profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled));

    AddPairBool(
        list, "Always-on Hotword Search Enabled",
        profile_->GetPrefs()->GetBoolean(prefs::kHotwordAlwaysOnSearchEnabled));

    AddPairBool(list, "Hotword Audio Logging Enabled",
                hotword_service && hotword_service->IsOptedIntoAudioLogging());

    AddLineBreak(list);
  }

  // Adds information specific to an extension to the list.
  void AddExtensionInfo(const std::string& extension_id,
                        const std::string& name_prefix,
                        base::ListValue* list) {
    DCHECK(!name_prefix.empty());
    std::string version("undefined");
    std::string id("undefined");
    base::FilePath path;

    extensions::ExtensionSystem* extension_system =
        extensions::ExtensionSystem::Get(profile_);
    if (extension_system) {
      ExtensionService* extension_service =
          extension_system->extension_service();
      const extensions::Extension* extension =
          extension_service->GetExtensionById(extension_id, true);
      if (extension) {
        id = extension->id();
        version = extension->VersionString();
        path = extension->path();
      }
    }
    AddPair(list, name_prefix + " Id", id);
    AddPair(list, name_prefix + " Version", version);
    AddPair16(list,
              ASCIIToUTF16(name_prefix + " Path"),
              path.empty() ?
              ASCIIToUTF16("undefined") : path.LossyDisplayName());

    extensions::ExtensionPrefs* extension_prefs =
        extensions::ExtensionPrefs::Get(profile_);
    int pref_state = -1;
    extension_prefs->ReadPrefAsInteger(extension_id, "state", &pref_state);
    std::string state;
    switch (pref_state) {
      case extensions::Extension::DISABLED:
        state = "DISABLED";
        break;
      case extensions::Extension::ENABLED:
        state = "ENABLED";
        break;
      case extensions::Extension::EXTERNAL_EXTENSION_UNINSTALLED:
        state = "EXTERNAL_EXTENSION_UNINSTALLED";
        break;
      default:
        state = "undefined";
    }

    AddPair(list, name_prefix + " State", state);

    AddLineBreak(list);
  }

  // Adds information specific to voice search in the app launcher to the list.
  void AddAppListInfo(base::ListValue* list) {
#if BUILDFLAG(ENABLE_APP_LIST)
    std::string state = "No Start Page Service";
    app_list::StartPageService* start_page_service =
        app_list::StartPageService::Get(profile_);
    if (start_page_service) {
      app_list::SpeechRecognitionState speech_state =
          start_page_service->state();
      switch (speech_state) {
        case app_list::SPEECH_RECOGNITION_OFF:
          state = "SPEECH_RECOGNITION_OFF";
          break;
        case app_list::SPEECH_RECOGNITION_READY:
          state = "SPEECH_RECOGNITION_READY";
          break;
        case app_list::SPEECH_RECOGNITION_HOTWORD_LISTENING:
          state = "SPEECH_RECOGNITION_HOTWORD_LISTENING";
          break;
        case app_list::SPEECH_RECOGNITION_RECOGNIZING:
          state = "SPEECH_RECOGNITION_RECOGNIZING";
          break;
        case app_list::SPEECH_RECOGNITION_IN_SPEECH:
          state = "SPEECH_RECOGNITION_IN_SPEECH";
          break;
        case app_list::SPEECH_RECOGNITION_STOPPING:
          state = "SPEECH_RECOGNITION_STOPPING";
          break;
        case app_list::SPEECH_RECOGNITION_NETWORK_ERROR:
          state = "SPEECH_RECOGNITION_NETWORK_ERROR";
          break;
        default:
          state = "undefined";
      }
    }
    AddPair(list, "Start Page State", state);
    AddLineBreak(list);
#endif
  }

  Profile* profile_;
  base::WeakPtrFactory<VoiceSearchDomHandler> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(VoiceSearchDomHandler);
};

}  // namespace

///////////////////////////////////////////////////////////////////////////////
//
// VoiceSearchUI
//
///////////////////////////////////////////////////////////////////////////////

VoiceSearchUI::VoiceSearchUI(content::WebUI* web_ui)
    : content::WebUIController(web_ui) {
  Profile* profile = Profile::FromWebUI(web_ui);
  web_ui->AddMessageHandler(base::MakeUnique<VoiceSearchDomHandler>(profile));

  // Set up the about:voicesearch source.
  content::WebUIDataSource::Add(profile, CreateVoiceSearchUiHtmlSource());
}

VoiceSearchUI::~VoiceSearchUI() {}
