1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.h"
6
7#include "base/bind.h"
8#include "base/command_line.h"
9#include "base/strings/string_number_conversions.h"
10#include "base/sys_info.h"
11#include "base/values.h"
12#include "chrome/browser/browser_process.h"
13#include "chrome/browser/chrome_notification_types.h"
14#include "chrome/browser/chromeos/app_mode/kiosk_app_launch_error.h"
15#include "chrome/browser/chromeos/login/existing_user_controller.h"
16#include "chrome/grit/generated_resources.h"
17#include "chromeos/chromeos_switches.h"
18#include "content/public/browser/notification_details.h"
19#include "content/public/browser/notification_service.h"
20#include "content/public/browser/web_ui.h"
21#include "ui/base/l10n/l10n_util.h"
22#include "ui/base/webui/web_ui_util.h"
23
24namespace chromeos {
25
26namespace {
27
28// JS functions that define new and old kiosk UI API.
29const char kKioskSetAppsNewAPI[] = "login.AccountPickerScreen.setApps";
30const char kKioskSetAppsOldAPI[] = "login.AppsMenuButton.setApps";
31const char kKioskShowErrorNewAPI[] = "login.AccountPickerScreen.showAppError";
32const char kKioskShowErrorOldAPI[] = "login.AppsMenuButton.showError";
33
34}  // namespace
35
36KioskAppMenuHandler::KioskAppMenuHandler(
37    const scoped_refptr<NetworkStateInformer>& network_state_informer)
38    : is_webui_initialized_(false),
39      network_state_informer_(network_state_informer),
40      weak_ptr_factory_(this) {
41  KioskAppManager::Get()->AddObserver(this);
42  network_state_informer_->AddObserver(this);
43}
44
45KioskAppMenuHandler::~KioskAppMenuHandler() {
46  KioskAppManager::Get()->RemoveObserver(this);
47  network_state_informer_->RemoveObserver(this);
48}
49
50void KioskAppMenuHandler::GetLocalizedStrings(
51    base::DictionaryValue* localized_strings) {
52  localized_strings->SetString(
53      "showApps",
54      l10n_util::GetStringUTF16(IDS_KIOSK_APPS_BUTTON));
55  localized_strings->SetString(
56      "confirmKioskAppDiagnosticModeFormat",
57      l10n_util::GetStringUTF16(IDS_LOGIN_CONFIRM_KIOSK_DIAGNOSTIC_FORMAT));
58  localized_strings->SetString(
59      "confirmKioskAppDiagnosticModeYes",
60      l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL));
61  localized_strings->SetString(
62      "confirmKioskAppDiagnosticModeNo",
63      l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL));
64  localized_strings->SetBoolean(
65      "kioskAppHasLaunchError",
66      KioskAppLaunchError::Get() != KioskAppLaunchError::NONE);
67}
68
69void KioskAppMenuHandler::RegisterMessages() {
70  web_ui()->RegisterMessageCallback("initializeKioskApps",
71      base::Bind(&KioskAppMenuHandler::HandleInitializeKioskApps,
72                 base::Unretained(this)));
73  web_ui()->RegisterMessageCallback("kioskAppsLoaded",
74      base::Bind(&KioskAppMenuHandler::HandleKioskAppsLoaded,
75                 base::Unretained(this)));
76  web_ui()->RegisterMessageCallback("checkKioskAppLaunchError",
77      base::Bind(&KioskAppMenuHandler::HandleCheckKioskAppLaunchError,
78                 base::Unretained(this)));
79}
80
81// static
82bool KioskAppMenuHandler::EnableNewKioskUI() {
83  // Turn off new kiosk UI for M34/35.
84  // TODO(xiyuan, nkostylev): Revist for http://crbug.com/362062.
85  return false;
86}
87
88void KioskAppMenuHandler::SendKioskApps() {
89  if (!is_webui_initialized_)
90    return;
91
92  KioskAppManager::Apps apps;
93  KioskAppManager::Get()->GetApps(&apps);
94
95  base::ListValue apps_list;
96  for (size_t i = 0; i < apps.size(); ++i) {
97    const KioskAppManager::App& app_data = apps[i];
98
99    scoped_ptr<base::DictionaryValue> app_info(new base::DictionaryValue);
100    app_info->SetBoolean("isApp", true);
101    app_info->SetString("id", app_data.app_id);
102    app_info->SetString("label", app_data.name);
103
104    // TODO(xiyuan): Replace data url with a URLDataSource.
105    std::string icon_url("chrome://theme/IDR_APP_DEFAULT_ICON");
106    if (!app_data.icon.isNull())
107      icon_url = webui::GetBitmapDataUrl(*app_data.icon.bitmap());
108    app_info->SetString("iconUrl", icon_url);
109
110    apps_list.Append(app_info.release());
111  }
112
113  web_ui()->CallJavascriptFunction(EnableNewKioskUI() ?
114      kKioskSetAppsNewAPI : kKioskSetAppsOldAPI,
115      apps_list);
116}
117
118void KioskAppMenuHandler::HandleInitializeKioskApps(
119    const base::ListValue* args) {
120  is_webui_initialized_ = true;
121  SendKioskApps();
122  UpdateState(ErrorScreenActor::ERROR_REASON_UPDATE);
123}
124
125void KioskAppMenuHandler::HandleKioskAppsLoaded(
126    const base::ListValue* args) {
127  content::NotificationService::current()->Notify(
128      chrome::NOTIFICATION_KIOSK_APPS_LOADED,
129      content::NotificationService::AllSources(),
130      content::NotificationService::NoDetails());
131}
132
133void KioskAppMenuHandler::HandleCheckKioskAppLaunchError(
134    const base::ListValue* args) {
135  KioskAppLaunchError::Error error = KioskAppLaunchError::Get();
136  if (error == KioskAppLaunchError::NONE)
137    return;
138  KioskAppLaunchError::Clear();
139
140  const std::string error_message = KioskAppLaunchError::GetErrorMessage(error);
141  bool new_kiosk_ui = EnableNewKioskUI();
142  web_ui()->CallJavascriptFunction(new_kiosk_ui ?
143      kKioskShowErrorNewAPI : kKioskShowErrorOldAPI,
144      base::StringValue(error_message));
145}
146
147void KioskAppMenuHandler::OnKioskAppsSettingsChanged() {
148  SendKioskApps();
149}
150
151void KioskAppMenuHandler::OnKioskAppDataChanged(const std::string& app_id) {
152  SendKioskApps();
153}
154
155void KioskAppMenuHandler::UpdateState(ErrorScreenActor::ErrorReason reason) {
156  if (network_state_informer_->state() == NetworkStateInformer::ONLINE)
157    KioskAppManager::Get()->RetryFailedAppDataFetch();
158}
159
160}  // namespace chromeos
161