blob: 4c32bf45557d36daf47696e885f21fbb50eec084 [file] [log] [blame]
// Copyright (c) 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/chromeos/hats/hats_dialog.h"
#include "base/bind.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "chrome/browser/chromeos/hats/hats_config.h"
#include "chrome/browser/chromeos/hats/hats_finch_helper.h"
#include "chrome/browser/profiles/profile_destroyer.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/browser_resources.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/dbus/util/version_loader.h"
#include "components/language/core/browser/pref_names.h"
#include "components/language/core/common/locale_util.h"
#include "components/prefs/pref_service.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/browser_thread.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/geometry/size.h"
using content::WebContents;
using content::WebUIMessageHandler;
namespace chromeos {
namespace {
// Default width/height ratio of screen size.
const int kDefaultWidth = 340;
const int kDefaultHeight = 260;
constexpr char kCrOSHaTSURL[] =
"https://storage.googleapis.com/chromeos-hats-web-stable/index.html";
// Keyword used to join the separate device info elements into a single string
// to be used as site context.
const char kDeviceInfoStopKeyword[] = "&";
const char kDefaultProfileLocale[] = "en-US";
enum class DeviceInfoKey : unsigned int {
BROWSER = 0,
PLATFORM,
FIRMWARE,
LOCALE,
};
// Maps the given DeviceInfoKey |key| enum to the corresponding string value
// that can be used as a key when creating a URL parameter.
const std::string KeyEnumToString(DeviceInfoKey key) {
switch (key) {
case DeviceInfoKey::BROWSER:
return "browser";
case DeviceInfoKey::PLATFORM:
return "platform";
case DeviceInfoKey::FIRMWARE:
return "firmware";
case DeviceInfoKey::LOCALE:
return "locale";
default:
NOTREACHED();
return std::string();
}
}
// Must be run on a blocking thread pool.
// Gathers the browser version info, firmware info and platform info and returns
// them in a single encoded string, the format of which is defined below.
// Currently the format is "<key>=<value>&<key>=<value>&<key>=<value>".
std::string GetFormattedSiteContext(const std::string& user_locale,
base::StringPiece join_keyword) {
std::vector<std::string> pairs;
pairs.push_back(KeyEnumToString(DeviceInfoKey::BROWSER) + "=" +
version_info::GetVersionNumber());
pairs.push_back(KeyEnumToString(DeviceInfoKey::PLATFORM) + "=" +
version_loader::GetVersion(version_loader::VERSION_FULL));
pairs.push_back(KeyEnumToString(DeviceInfoKey::FIRMWARE) + "=" +
version_loader::GetFirmware());
pairs.push_back(KeyEnumToString(DeviceInfoKey::LOCALE) + "=" + user_locale);
return base::JoinString(pairs, join_keyword);
}
} // namespace
// static
std::unique_ptr<HatsDialog> HatsDialog::CreateAndShow(
const HatsConfig& hats_config) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
Profile* profile = ProfileManager::GetActiveUserProfile();
std::string user_locale =
profile->GetPrefs()->GetString(language::prefs::kApplicationLocale);
language::ConvertToActualUILocale(&user_locale);
if (!user_locale.length())
user_locale = kDefaultProfileLocale;
std::unique_ptr<HatsDialog> hats_dialog(
new HatsDialog(HatsFinchHelper::GetTriggerID(hats_config), profile));
// Raw pointer is used here since the dialog is owned by the hats
// notification controller which lives until the end of the user session. The
// dialog will always be closed before that time instant.
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&GetFormattedSiteContext, user_locale,
kDeviceInfoStopKeyword),
base::BindOnce(&HatsDialog::Show, base::Unretained(hats_dialog.get())));
return hats_dialog;
}
void HatsDialog::Show(const std::string& site_context) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// Link the trigger ID to fetch the correct survey.
url_ = std::string(kCrOSHaTSURL) + "?" + site_context +
"&trigger=" + trigger_id_;
chrome::ShowWebDialog(nullptr, ProfileManager::GetActiveUserProfile(), this);
}
HatsDialog::HatsDialog(const std::string& trigger_id, Profile* user_profile)
: trigger_id_(trigger_id), user_profile_(user_profile) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
set_can_resize(false);
}
HatsDialog::~HatsDialog() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(user_profile_);
}
ui::ModalType HatsDialog::GetDialogModalType() const {
return ui::MODAL_TYPE_SYSTEM;
}
std::u16string HatsDialog::GetDialogTitle() const {
return std::u16string();
}
GURL HatsDialog::GetDialogContentURL() const {
return GURL(url_);
}
void HatsDialog::GetWebUIMessageHandlers(
std::vector<WebUIMessageHandler*>* handlers) const {}
void HatsDialog::GetDialogSize(gfx::Size* size) const {
size->SetSize(kDefaultWidth, kDefaultHeight);
}
std::string HatsDialog::GetDialogArgs() const {
return std::string();
}
void HatsDialog::OnDialogClosed(const std::string& json_retval) {}
void HatsDialog::OnCloseContents(WebContents* source, bool* out_close_dialog) {
*out_close_dialog = true;
}
bool HatsDialog::ShouldShowDialogTitle() const {
return false;
}
bool HatsDialog::ShouldShowCloseButton() const {
return false;
}
bool HatsDialog::HandleContextMenu(content::RenderFrameHost* render_frame_host,
const content::ContextMenuParams& params) {
// Disable context menu
return true;
}
ui::WebDialogDelegate::FrameKind HatsDialog::GetWebDialogFrameKind() const {
return ui::WebDialogDelegate::FrameKind::kDialog;
}
} // namespace chromeos