blob: 9f345f4ab1f6280b2f8fe4e8eb52923e39727fa7 [file] [log] [blame]
// 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/welcome_win10_handler.h"
#include "base/bind.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/shell_integration.h"
#include "chrome/browser/shell_integration_win.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/service_manager_connection.h"
#include "services/service_manager/public/cpp/connector.h"
#include "url/gurl.h"
namespace {
void RecordDefaultBrowserResult(
const std::string& histogram_suffix,
shell_integration::DefaultWebClientState default_browser_state) {
// Consider the page successful if this or any other side-by-side install of
// Chrome was chosen as the user's default browser.
base::UmaHistogramBoolean(
base::StringPrintf("Welcome.Win10.DefaultPromptResult_%s",
histogram_suffix.c_str()),
(default_browser_state == shell_integration::IS_DEFAULT ||
default_browser_state == shell_integration::OTHER_MODE_IS_DEFAULT));
}
void RecordPinnedResult(const std::string& histogram_suffix,
bool succeeded,
bool is_pinned) {
if (!succeeded)
return;
base::UmaHistogramBoolean(
base::StringPrintf("Welcome.Win10.PinnedPromptResult_%s",
histogram_suffix.c_str()),
is_pinned);
}
// Returns a new Connector that can be used on a different thread.
std::unique_ptr<service_manager::Connector> GetClonedConnector() {
return content::ServiceManagerConnection::GetForProcess()
->GetConnector()
->Clone();
}
} // namespace
WelcomeWin10Handler::WelcomeWin10Handler() : weak_ptr_factory_(this) {
// The check is started as early as possible because waiting for the page to
// be fully loaded is unnecessarily wasting time.
StartIsPinnedToTaskbarCheck();
}
WelcomeWin10Handler::~WelcomeWin10Handler() {
// The instructions for pinning Chrome to the taskbar were only displayed if
// Chrome wasn't pinned to the taskbar at page construction time.
bool pin_instructions_shown =
pinned_state_result_.has_value() && !pinned_state_result_.value();
std::string histogram_suffix = "Inline";
histogram_suffix += pin_instructions_shown ? "Combined" : "Default";
// Closing the page. Record whether the instructions were useful.
(new shell_integration::DefaultBrowserWorker(
base::Bind(&RecordDefaultBrowserResult, histogram_suffix)))
->StartCheckIsDefault();
if (pin_instructions_shown) {
// On error, call RecordPinnedResult() with |succeeded| == false.
base::Closure error_callback =
base::Bind(&RecordPinnedResult, histogram_suffix, false, false);
shell_integration::win::GetIsPinnedToTaskbarState(
GetClonedConnector(), error_callback,
base::Bind(&RecordPinnedResult, histogram_suffix));
}
}
void WelcomeWin10Handler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
"handleSetDefaultBrowser",
base::Bind(&WelcomeWin10Handler::HandleSetDefaultBrowser,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"handleContinue",
base::Bind(&WelcomeWin10Handler::HandleContinue, base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"getPinnedToTaskbarState",
base::Bind(&WelcomeWin10Handler::HandleGetPinnedToTaskbarState,
base::Unretained(this)));
}
void WelcomeWin10Handler::HandleGetPinnedToTaskbarState(
const base::ListValue* args) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
AllowJavascript();
// Save the callback id so that the result can be sent back when it is
// available.
bool callback_id_found = args->GetString(0, &pinned_state_callback_id_);
DCHECK(callback_id_found);
// Send back the result if it is already available.
if (pinned_state_result_.has_value()) {
SendPinnedToTaskbarStateResult();
return;
}
// Only wait for a small amount of time for the result. If the timer fires,
// it will be assumed that Chrome isn't pinned to the taskbar. This is to make
// sure the instructions are displayed in case it was impossible to determine
// the pinned state.
constexpr base::TimeDelta kPinnedToTaskbarTimeout =
base::TimeDelta::FromMilliseconds(200);
timer_.Start(FROM_HERE, kPinnedToTaskbarTimeout,
base::Bind(&WelcomeWin10Handler::OnIsPinnedToTaskbarDetermined,
base::Unretained(this), true, false));
}
void WelcomeWin10Handler::HandleSetDefaultBrowser(const base::ListValue* args) {
base::RecordAction(
base::UserMetricsAction("Win10WelcomePage_SetAsDefaultBrowser"));
// The worker owns itself.
(new shell_integration::DefaultBrowserWorker(
shell_integration::DefaultWebClientWorkerCallback()))
->StartSetAsDefault();
}
void WelcomeWin10Handler::HandleContinue(const base::ListValue* args) {
web_ui()->GetWebContents()->GetController().LoadURL(
GURL(chrome::kChromeUINewTabURL), content::Referrer(),
ui::PageTransition::PAGE_TRANSITION_LINK, std::string());
}
void WelcomeWin10Handler::StartIsPinnedToTaskbarCheck() {
// Assume that Chrome is pinned to the taskbar if an error occurs.
base::Closure error_callback =
base::Bind(&WelcomeWin10Handler::OnIsPinnedToTaskbarDetermined,
weak_ptr_factory_.GetWeakPtr(), false, true);
shell_integration::win::GetIsPinnedToTaskbarState(
GetClonedConnector(), error_callback,
base::Bind(&WelcomeWin10Handler::OnIsPinnedToTaskbarResult,
weak_ptr_factory_.GetWeakPtr()));
}
void WelcomeWin10Handler::OnIsPinnedToTaskbarResult(bool succeeded,
bool is_pinned_to_taskbar) {
// Assume that Chrome is pinned to the taskbar if an error occured.
OnIsPinnedToTaskbarDetermined(false, !succeeded || is_pinned_to_taskbar);
}
void WelcomeWin10Handler::OnIsPinnedToTaskbarDetermined(
bool timed_out,
bool is_pinned_to_taskbar) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// Early exit if the pinned_state was already determined.
if (pinned_state_result_.has_value())
return;
UMA_HISTOGRAM_BOOLEAN("Welcome.Win10.PinCheckTimedOut", timed_out);
// Stop the timer if it's still running.
timer_.Stop();
// Cache the value.
pinned_state_result_.emplace(is_pinned_to_taskbar);
// If the page already called getPinnedToTaskbarState(), the result can be
// sent back.
if (!pinned_state_callback_id_.empty())
SendPinnedToTaskbarStateResult();
}
void WelcomeWin10Handler::SendPinnedToTaskbarStateResult() {
ResolveJavascriptCallback(base::Value(pinned_state_callback_id_),
base::Value(pinned_state_result_.value()));
}