blob: c88297b01a0da74eb5c7bbcf3fb0b62306cd8114 [file] [log] [blame]
// Copyright 2018 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/chromeos/login/recommend_apps_screen_handler.h"
#include "base/metrics/histogram_macros.h"
#include "chrome/browser/chromeos/arc/session/arc_session_manager.h"
#include "chrome/browser/chromeos/login/screens/recommend_apps_screen.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/app_list/arc/arc_fast_app_reinstall_starter.h"
#include "chrome/grit/component_extension_resources.h"
#include "chrome/grit/generated_resources.h"
#include "components/arc/arc_prefs.h"
#include "components/login/localized_values_builder.h"
#include "ui/base/resource/resource_bundle.h"
namespace {
constexpr const char kUserActionSkip[] = "recommendAppsSkip";
constexpr const char kUserActionRetry[] = "recommendAppsRetry";
constexpr const char kUserActionInstall[] = "recommendAppsInstall";
constexpr const int kMaxAppCount = 21;
enum class RecommendAppsScreenState {
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused. This should be kept in sync with
// RecommendAppsScreenState in enums.xml.
SHOW = 0,
NO_SHOW = 1,
ERROR = 2,
kMaxValue = ERROR
};
enum class RecommendAppsScreenAction {
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused. This should be kept in sync with
// RecommendAppsScreenAction in enums.xml.
SKIPPED = 0,
RETRIED = 1,
SELECTED_NONE = 2,
APP_SELECTED = 3,
kMaxValue = APP_SELECTED
};
void RecordUmaUserSelectionAppCount(int app_count) {
UMA_HISTOGRAM_EXACT_LINEAR("OOBE.RecommendApps.Screen.SelectedAppCount",
app_count, kMaxAppCount);
}
void RecordUmaSelectedRecommendedPercentage(
int selected_recommended_percentage) {
UMA_HISTOGRAM_PERCENTAGE(
"OOBE.RecommendApps.Screen.SelectedRecommendedPercentage",
selected_recommended_percentage);
}
void RecordUmaScreenState(RecommendAppsScreenState state) {
UMA_HISTOGRAM_ENUMERATION("OOBE.RecommendApps.Screen.State", state);
}
void RecordUmaScreenAction(RecommendAppsScreenAction action) {
UMA_HISTOGRAM_ENUMERATION("OOBE.RecommendApps.Screen.Action", action);
}
} // namespace
namespace chromeos {
constexpr StaticOobeScreenId RecommendAppsScreenView::kScreenId;
RecommendAppsScreenHandler::RecommendAppsScreenHandler(
JSCallsContainer* js_calls_container)
: BaseScreenHandler(kScreenId, js_calls_container) {
}
RecommendAppsScreenHandler::~RecommendAppsScreenHandler() {
if (screen_)
screen_->OnViewDestroyed(this);
}
void RecommendAppsScreenHandler::DeclareLocalizedValues(
::login::LocalizedValuesBuilder* builder) {
builder->Add("recommendAppsScreenTitle",
IDS_LOGIN_RECOMMEND_APPS_SCREEN_TITLE);
builder->Add("recommendAppsScreenDescription",
IDS_LOGIN_RECOMMEND_APPS_SCREEN_DESCRIPTION);
builder->Add("recommendAppsSkip", IDS_LOGIN_RECOMMEND_APPS_SKIP);
builder->Add("recommendAppsInstall", IDS_LOGIN_RECOMMEND_APPS_INSTALL);
builder->Add("recommendAppsRetry", IDS_LOGIN_RECOMMEND_APPS_RETRY);
builder->Add("recommendAppsLoading", IDS_LOGIN_RECOMMEND_APPS_SCREEN_LOADING);
builder->Add("recommendAppsError", IDS_LOGIN_RECOMMEND_APPS_SCREEN_ERROR);
}
void RecommendAppsScreenHandler::RegisterMessages() {
BaseScreenHandler::RegisterMessages();
AddCallback(kUserActionSkip, &RecommendAppsScreenHandler::OnUserSkip);
AddCallback(kUserActionRetry, &RecommendAppsScreenHandler::HandleRetry);
AddRawCallback(kUserActionInstall,
&RecommendAppsScreenHandler::HandleInstall);
}
void RecommendAppsScreenHandler::Bind(RecommendAppsScreen* screen) {
screen_ = screen;
BaseScreenHandler::SetBaseScreen(screen);
}
void RecommendAppsScreenHandler::Show() {
ShowScreen(kScreenId);
Profile* profile = ProfileManager::GetActiveUserProfile();
pref_service_ = profile->GetPrefs();
}
void RecommendAppsScreenHandler::Hide() {}
void RecommendAppsScreenHandler::OnLoadError() {
RecordUmaScreenState(RecommendAppsScreenState::ERROR);
CallJS("login.RecommendAppsScreen.showError");
}
void RecommendAppsScreenHandler::OnLoadSuccess(const base::Value& app_list) {
recommended_app_count_ = static_cast<int>(app_list.GetList().size());
LoadAppListInUI(app_list);
}
void RecommendAppsScreenHandler::OnParseResponseError() {
RecordUmaScreenState(RecommendAppsScreenState::NO_SHOW);
HandleSkip();
}
void RecommendAppsScreenHandler::Initialize() {}
void RecommendAppsScreenHandler::LoadAppListInUI(const base::Value& app_list) {
if (!page_is_ready()) {
RecordUmaScreenState(RecommendAppsScreenState::ERROR);
CallJS("login.RecommendAppsScreen.showError");
return;
}
RecordUmaScreenState(RecommendAppsScreenState::SHOW);
const ui::ResourceBundle& resource_bundle =
ui::ResourceBundle::GetSharedInstance();
base::StringPiece app_list_webview = resource_bundle.GetRawDataResource(
IDR_ARC_SUPPORT_RECOMMEND_APP_LIST_VIEW_HTML);
CallJS("login.RecommendAppsScreen.setWebview", app_list_webview.as_string());
CallJS("login.RecommendAppsScreen.loadAppList", app_list);
}
void RecommendAppsScreenHandler::OnUserSkip() {
RecordUmaScreenAction(RecommendAppsScreenAction::SKIPPED);
HandleSkip();
}
// There are three scenarios that HandleSkip() is called:
// 1. The user clicks the Skip button.
// 2. The user doesn't select any apps and click the Install button.
// 3. The response from the fetcher cannot be parsed.
// Each case has its own entry point to be logged.
void RecommendAppsScreenHandler::HandleSkip() {
if (screen_)
screen_->OnSkip();
}
void RecommendAppsScreenHandler::HandleRetry() {
RecordUmaScreenAction(RecommendAppsScreenAction::RETRIED);
if (screen_)
screen_->OnRetry();
}
void RecommendAppsScreenHandler::HandleInstall(const base::ListValue* args) {
if (recommended_app_count_ != 0) {
int selected_app_count = static_cast<int>(args->GetSize());
int selected_recommended_percentage =
100 * selected_app_count / recommended_app_count_;
RecordUmaUserSelectionAppCount(selected_app_count);
RecordUmaSelectedRecommendedPercentage(selected_recommended_percentage);
}
// If the user does not select any apps, we should skip the app downloading
// screen.
if (args->GetList().empty()) {
RecordUmaScreenAction(RecommendAppsScreenAction::SELECTED_NONE);
HandleSkip();
return;
}
RecordUmaScreenAction(RecommendAppsScreenAction::APP_SELECTED);
pref_service_->Set(arc::prefs::kArcFastAppReinstallPackages, *args);
arc::ArcFastAppReinstallStarter* fast_app_reinstall_starter =
arc::ArcSessionManager::Get()->fast_app_resintall_starter();
if (fast_app_reinstall_starter) {
fast_app_reinstall_starter->OnAppsSelectionFinished();
} else {
LOG(ERROR)
<< "Cannot complete Fast App Reinstall flow. Starter is not available.";
}
if (screen_)
screen_->OnInstall();
}
} // namespace chromeos