// Copyright (c) 2013 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/profile_resetter/resettable_settings_snapshot.h"

#include "base/guid.h"
#include "base/json/json_writer.h"
#include "base/md5.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/cancellation_flag.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profile_resetter/profile_reset_report.pb.h"
#include "chrome/browser/profile_resetter/reset_report_uploader.h"
#include "chrome/browser/profile_resetter/reset_report_uploader_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/common/channel_info.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
#include "components/feedback/feedback_data.h"
#include "components/feedback/feedback_util.h"
#include "components/search_engines/template_url_service.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/extension_registry.h"
#include "grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"

using feedback::FeedbackData;

namespace {

// Feedback bucket label.
const char kProfileResetWebUIBucket[] = "ProfileResetReport";

// Dictionary keys for feedback report.
const char kDefaultSearchEnginePath[] = "default_search_engine";
const char kEnabledExtensions[] = "enabled_extensions";
const char kHomepageIsNewTabPage[] = "homepage_is_ntp";
const char kHomepagePath[] = "homepage";
const char kShortcuts[] = "shortcuts";
const char kShowHomeButton[] = "show_home_button";
const char kStartupTypePath[] = "startup_type";
const char kStartupURLPath[] = "startup_urls";
const char kGuid[] = "guid";

template <class StringType>
void AddPair(base::ListValue* list,
             const base::string16& key,
             const StringType& value) {
  base::DictionaryValue* results = new base::DictionaryValue();
  results->SetString("key", key);
  results->SetString("value", value);
  list->Append(results);
}

}  // namespace

ResettableSettingsSnapshot::ResettableSettingsSnapshot(
    Profile* profile)
    : startup_(SessionStartupPref::GetStartupPref(profile)),
      shortcuts_determined_(false),
      weak_ptr_factory_(this) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  // URLs are always stored sorted.
  std::sort(startup_.urls.begin(), startup_.urls.end());

  PrefService* prefs = profile->GetPrefs();
  DCHECK(prefs);
  homepage_ = prefs->GetString(prefs::kHomePage);
  homepage_is_ntp_ = prefs->GetBoolean(prefs::kHomePageIsNewTabPage);
  show_home_button_ = prefs->GetBoolean(prefs::kShowHomeButton);

  TemplateURLService* service =
      TemplateURLServiceFactory::GetForProfile(profile);
  DCHECK(service);
  TemplateURL* dse = service->GetDefaultSearchProvider();
  if (dse)
    dse_url_ = dse->url();

  const extensions::ExtensionSet& enabled_ext =
      extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
  enabled_extensions_.reserve(enabled_ext.size());

  for (extensions::ExtensionSet::const_iterator it = enabled_ext.begin();
       it != enabled_ext.end(); ++it)
    enabled_extensions_.push_back(std::make_pair((*it)->id(), (*it)->name()));

  // ExtensionSet is sorted but it seems to be an implementation detail.
  std::sort(enabled_extensions_.begin(), enabled_extensions_.end());

  // Calculate the MD5 sum of the GUID to make sure that no part of the GUID
  // contains information identifying the sender of the report.
  guid_ = base::MD5String(base::GenerateGUID());
}

ResettableSettingsSnapshot::~ResettableSettingsSnapshot() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  if (cancellation_flag_.get())
    cancellation_flag_->data.Set();
}

void ResettableSettingsSnapshot::Subtract(
    const ResettableSettingsSnapshot& snapshot) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  ExtensionList extensions = base::STLSetDifference<ExtensionList>(
      enabled_extensions_, snapshot.enabled_extensions_);
  enabled_extensions_.swap(extensions);
}

int ResettableSettingsSnapshot::FindDifferentFields(
    const ResettableSettingsSnapshot& snapshot) const {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  int bit_mask = 0;

  if (startup_.type != snapshot.startup_.type ||
      startup_.urls != snapshot.startup_.urls)
    bit_mask |= STARTUP_MODE;

  if (homepage_is_ntp_ != snapshot.homepage_is_ntp_ ||
      homepage_ != snapshot.homepage_ ||
      show_home_button_ != snapshot.show_home_button_)
    bit_mask |= HOMEPAGE;

  if (dse_url_ != snapshot.dse_url_)
    bit_mask |= DSE_URL;

  if (enabled_extensions_ != snapshot.enabled_extensions_)
    bit_mask |= EXTENSIONS;

  if (shortcuts_ != snapshot.shortcuts_)
    bit_mask |= SHORTCUTS;

  static_assert(ResettableSettingsSnapshot::ALL_FIELDS == 31,
                "new field needs to be added here");

  return bit_mask;
}

void ResettableSettingsSnapshot::RequestShortcuts(
    const base::Closure& callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(!cancellation_flag_.get() && !shortcuts_determined());

  cancellation_flag_ = new SharedCancellationFlag;
  content::BrowserThread::PostTaskAndReplyWithResult(
      content::BrowserThread::FILE,
      FROM_HERE,
      base::Bind(&GetChromeLaunchShortcuts, cancellation_flag_),
      base::Bind(&ResettableSettingsSnapshot::SetShortcutsAndReport,
                 weak_ptr_factory_.GetWeakPtr(),
                 callback));
}

void ResettableSettingsSnapshot::SetShortcutsAndReport(
    const base::Closure& callback,
    const std::vector<ShortcutCommand>& shortcuts) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  shortcuts_ = shortcuts;
  shortcuts_determined_ = true;
  cancellation_flag_ = NULL;

  if (!callback.is_null())
    callback.Run();
}

std::string SerializeSettingsReport(const ResettableSettingsSnapshot& snapshot,
                                    int field_mask) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  base::DictionaryValue dict;

  if (field_mask & ResettableSettingsSnapshot::STARTUP_MODE) {
    base::ListValue* list = new base::ListValue;
    const std::vector<GURL>& urls = snapshot.startup_urls();
    for (std::vector<GURL>::const_iterator i = urls.begin();
         i != urls.end(); ++i)
      list->AppendString(i->spec());
    dict.Set(kStartupURLPath, list);
    dict.SetInteger(kStartupTypePath, snapshot.startup_type());
  }

  if (field_mask & ResettableSettingsSnapshot::HOMEPAGE) {
    dict.SetString(kHomepagePath, snapshot.homepage());
    dict.SetBoolean(kHomepageIsNewTabPage, snapshot.homepage_is_ntp());
    dict.SetBoolean(kShowHomeButton, snapshot.show_home_button());
  }

  if (field_mask & ResettableSettingsSnapshot::DSE_URL)
    dict.SetString(kDefaultSearchEnginePath, snapshot.dse_url());

  if (field_mask & ResettableSettingsSnapshot::EXTENSIONS) {
    base::ListValue* list = new base::ListValue;
    const ResettableSettingsSnapshot::ExtensionList& extensions =
        snapshot.enabled_extensions();
    for (ResettableSettingsSnapshot::ExtensionList::const_iterator i =
         extensions.begin(); i != extensions.end(); ++i) {
      // Replace "\"" to simplify server-side analysis.
      std::string ext_name;
      base::ReplaceChars(i->second, "\"", "\'", &ext_name);
      list->AppendString(i->first + ";" + ext_name);
    }
    dict.Set(kEnabledExtensions, list);
  }

  if (field_mask & ResettableSettingsSnapshot::SHORTCUTS) {
    base::ListValue* list = new base::ListValue;
    const std::vector<ShortcutCommand>& shortcuts = snapshot.shortcuts();
    for (std::vector<ShortcutCommand>::const_iterator i = shortcuts.begin();
         i != shortcuts.end(); ++i) {
      base::string16 arguments;
      // Replace "\"" to simplify server-side analysis.
      base::ReplaceChars(i->second, base::ASCIIToUTF16("\""),
                         base::ASCIIToUTF16("\'"), &arguments);
      list->AppendString(arguments);
    }
    dict.Set(kShortcuts, list);
  }

  dict.SetString(kGuid, snapshot.guid());

  static_assert(ResettableSettingsSnapshot::ALL_FIELDS == 31,
                "new field needs to be serialized here");

  std::string json;
  base::JSONWriter::Write(dict, &json);
  return json;
}

scoped_ptr<reset_report::ChromeResetReport> SerializeSettingsReportToProto(
    const ResettableSettingsSnapshot& snapshot,
    int field_mask) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  scoped_ptr<reset_report::ChromeResetReport> report(
      new reset_report::ChromeResetReport());

  if (field_mask & ResettableSettingsSnapshot::STARTUP_MODE) {
    for (const auto& url : snapshot.startup_urls())
      report->add_startup_url_path(url.spec());
    switch (snapshot.startup_type()) {
      case SessionStartupPref::DEFAULT:
        report->set_startup_type(
            reset_report::ChromeResetReport_SessionStartupType_DEFAULT);
        break;
      case SessionStartupPref::LAST:
        report->set_startup_type(
            reset_report::ChromeResetReport_SessionStartupType_LAST);
        break;
      case SessionStartupPref::URLS:
        report->set_startup_type(
            reset_report::ChromeResetReport_SessionStartupType_URLS);
        break;
    }
  }

  if (field_mask & ResettableSettingsSnapshot::HOMEPAGE) {
    report->set_homepage_path(snapshot.homepage());
    report->set_homepage_is_new_tab_page(snapshot.homepage_is_ntp());
    report->set_show_home_button(snapshot.show_home_button());
  }

  if (field_mask & ResettableSettingsSnapshot::DSE_URL)
    report->set_default_search_engine_path(snapshot.dse_url());

  if (field_mask & ResettableSettingsSnapshot::EXTENSIONS) {
    for (const auto& enabled_extension : snapshot.enabled_extensions()) {
      reset_report::ChromeResetReport_Extension* new_extension =
          report->add_enabled_extensions();
      new_extension->set_extension_id(enabled_extension.first);
      new_extension->set_extension_name(enabled_extension.second);
    }
  }

  if (field_mask & ResettableSettingsSnapshot::SHORTCUTS) {
    for (const auto& shortcut_command : snapshot.shortcuts())
      report->add_shortcuts(base::UTF16ToUTF8(shortcut_command.second));
  }

  report->set_guid(snapshot.guid());

  static_assert(ResettableSettingsSnapshot::ALL_FIELDS == 31,
                "new field needs to be serialized here");
  return report;
}

void SendSettingsFeedback(const std::string& report,
                          Profile* profile) {
  scoped_refptr<FeedbackData> feedback_data = new FeedbackData();
  feedback_data->set_category_tag(kProfileResetWebUIBucket);
  feedback_data->set_description(report);

  feedback_data->set_image(make_scoped_ptr(new std::string));
  feedback_data->set_context(profile);

  feedback_data->set_page_url("");
  feedback_data->set_user_email("");

  feedback_util::SendReport(feedback_data);
}

void SendSettingsFeedbackProto(const reset_report::ChromeResetReport& report,
                               Profile* profile) {
  ResetReportUploaderFactory::GetForBrowserContext(profile)
      ->DispatchReport(report);
}

scoped_ptr<base::ListValue> GetReadableFeedbackForSnapshot(
    Profile* profile,
    const ResettableSettingsSnapshot& snapshot) {
  DCHECK(profile);
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  scoped_ptr<base::ListValue> list(new base::ListValue);
  AddPair(list.get(),
          l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_LOCALE),
          g_browser_process->GetApplicationLocale());
  AddPair(list.get(),
          l10n_util::GetStringUTF16(IDS_VERSION_UI_USER_AGENT),
          GetUserAgent());
  std::string version = version_info::GetVersionNumber();
  version += chrome::GetChannelString();
  AddPair(list.get(),
          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
          version);

  // Add snapshot data.
  const std::vector<GURL>& urls = snapshot.startup_urls();
  std::string startup_urls;
  for (std::vector<GURL>::const_iterator i = urls.begin();
       i != urls.end(); ++i) {
    if (!startup_urls.empty())
      startup_urls += ' ';
    startup_urls += i->host();
  }
  if (!startup_urls.empty()) {
    AddPair(list.get(),
            l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_STARTUP_URLS),
            startup_urls);
  }

  base::string16 startup_type;
  switch (snapshot.startup_type()) {
    case SessionStartupPref::DEFAULT:
      startup_type = l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_SHOW_NEWTAB);
      break;
    case SessionStartupPref::LAST:
      startup_type = l10n_util::GetStringUTF16(
          IDS_OPTIONS_STARTUP_RESTORE_LAST_SESSION);
      break;
    case SessionStartupPref::URLS:
      startup_type = l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_SHOW_PAGES);
      break;
    default:
      break;
  }
  AddPair(list.get(),
          l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_STARTUP_TYPE),
          startup_type);

  if (!snapshot.homepage().empty()) {
    AddPair(list.get(),
            l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_HOMEPAGE),
            snapshot.homepage());
  }

  int is_ntp_message_id = snapshot.homepage_is_ntp()
      ? IDS_RESET_PROFILE_SETTINGS_YES
      : IDS_RESET_PROFILE_SETTINGS_NO;
  AddPair(list.get(),
          l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_HOMEPAGE_IS_NTP),
          l10n_util::GetStringUTF16(is_ntp_message_id));

  int show_home_button_id = snapshot.show_home_button()
      ? IDS_RESET_PROFILE_SETTINGS_YES
      : IDS_RESET_PROFILE_SETTINGS_NO;
  AddPair(
      list.get(),
      l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_SHOW_HOME_BUTTON),
      l10n_util::GetStringUTF16(show_home_button_id));

  TemplateURLService* service =
      TemplateURLServiceFactory::GetForProfile(profile);
  DCHECK(service);
  TemplateURL* dse = service->GetDefaultSearchProvider();
  if (dse) {
    AddPair(list.get(),
            l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_DSE),
            dse->GenerateSearchURL(service->search_terms_data()).host());
  }

  if (snapshot.shortcuts_determined()) {
    base::string16 shortcut_targets;
    const std::vector<ShortcutCommand>& shortcuts = snapshot.shortcuts();
    for (std::vector<ShortcutCommand>::const_iterator i =
         shortcuts.begin(); i != shortcuts.end(); ++i) {
      if (!shortcut_targets.empty())
        shortcut_targets += base::ASCIIToUTF16("\n");
      shortcut_targets += base::ASCIIToUTF16("chrome.exe ");
      shortcut_targets += i->second;
    }
    if (!shortcut_targets.empty()) {
      AddPair(list.get(),
              l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_SHORTCUTS),
              shortcut_targets);
    }
  } else {
    AddPair(list.get(),
            l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_SHORTCUTS),
            l10n_util::GetStringUTF16(
                IDS_RESET_PROFILE_SETTINGS_PROCESSING_SHORTCUTS));
  }

  const ResettableSettingsSnapshot::ExtensionList& extensions =
      snapshot.enabled_extensions();
  std::string extension_names;
  for (ResettableSettingsSnapshot::ExtensionList::const_iterator i =
       extensions.begin(); i != extensions.end(); ++i) {
    if (!extension_names.empty())
      extension_names += '\n';
    extension_names += i->second;
  }
  if (!extension_names.empty()) {
    AddPair(list.get(),
            l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_EXTENSIONS),
            extension_names);
  }
  return list.Pass();
}
