1 // Copyright (c) 2012 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.
5 #include "chrome/browser/ui/webui/chromeos/imageburner/imageburner_ui.h"
8 #include "base/files/file_path.h"
9 #include "base/i18n/rtl.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/values.h"
13 #include "chrome/browser/chromeos/imageburner/burn_controller.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/common/url_constants.h"
16 #include "content/public/browser/web_ui.h"
17 #include "content/public/browser/web_ui_data_source.h"
18 #include "content/public/browser/web_ui_message_handler.h"
19 #include "grit/browser_resources.h"
20 #include "grit/generated_resources.h"
21 #include "ui/base/l10n/l10n_util.h"
22 #include "ui/base/l10n/time_format.h"
23 #include "ui/base/text/bytes_formatting.h"
27 namespace imageburner
{
31 const char kPropertyDevicePath
[] = "devicePath";
32 const char kPropertyFilePath
[] = "filePath";
33 const char kPropertyLabel
[] = "label";
34 const char kPropertyDeviceType
[] = "type";
36 // Link displayed on imageburner ui.
37 const char kMoreInfoLink
[] =
38 "http://www.chromium.org/chromium-os/chromiumos-design-docs/recovery-mode";
40 content::WebUIDataSource
* CreateImageburnerUIHTMLSource() {
41 content::WebUIDataSource
* source
=
42 content::WebUIDataSource::Create(chrome::kChromeUIImageBurnerHost
);
44 source
->AddLocalizedString("headerTitle", IDS_IMAGEBURN_HEADER_TITLE
);
45 source
->AddLocalizedString("headerDescription",
46 IDS_IMAGEBURN_HEADER_DESCRIPTION
);
47 source
->AddLocalizedString("headerLink", IDS_IMAGEBURN_HEADER_LINK
);
48 source
->AddLocalizedString("statusDevicesNone",
49 IDS_IMAGEBURN_NO_DEVICES_STATUS
);
50 source
->AddLocalizedString("warningDevicesNone",
51 IDS_IMAGEBURN_NO_DEVICES_WARNING
);
52 source
->AddLocalizedString("statusDevicesMultiple",
53 IDS_IMAGEBURN_MUL_DEVICES_STATUS
);
54 source
->AddLocalizedString("statusDeviceUSB",
55 IDS_IMAGEBURN_USB_DEVICE_STATUS
);
56 source
->AddLocalizedString("statusDeviceSD",
57 IDS_IMAGEBURN_SD_DEVICE_STATUS
);
58 source
->AddLocalizedString("warningDevices",
59 IDS_IMAGEBURN_DEVICES_WARNING
);
60 source
->AddLocalizedString("statusNoConnection",
61 IDS_IMAGEBURN_NO_CONNECTION_STATUS
);
62 source
->AddLocalizedString("warningNoConnection",
63 IDS_IMAGEBURN_NO_CONNECTION_WARNING
);
64 source
->AddLocalizedString("statusNoSpace",
65 IDS_IMAGEBURN_INSUFFICIENT_SPACE_STATUS
);
66 source
->AddLocalizedString("warningNoSpace",
67 IDS_IMAGEBURN_INSUFFICIENT_SPACE_WARNING
);
68 source
->AddLocalizedString("statusDownloading",
69 IDS_IMAGEBURN_DOWNLOADING_STATUS
);
70 source
->AddLocalizedString("statusUnzip", IDS_IMAGEBURN_UNZIP_STATUS
);
71 source
->AddLocalizedString("statusBurn", IDS_IMAGEBURN_BURN_STATUS
);
72 source
->AddLocalizedString("statusError", IDS_IMAGEBURN_ERROR_STATUS
);
73 source
->AddLocalizedString("statusSuccess", IDS_IMAGEBURN_SUCCESS_STATUS
);
74 source
->AddLocalizedString("warningSuccess", IDS_IMAGEBURN_SUCCESS_DESC
);
75 source
->AddLocalizedString("title", IDS_IMAGEBURN_PAGE_TITLE
);
76 source
->AddLocalizedString("confirmButton", IDS_IMAGEBURN_CONFIRM_BUTTON
);
77 source
->AddLocalizedString("cancelButton", IDS_IMAGEBURN_CANCEL_BUTTON
);
78 source
->AddLocalizedString("retryButton", IDS_IMAGEBURN_RETRY_BUTTON
);
79 source
->AddString("moreInfoLink", base::ASCIIToUTF16(kMoreInfoLink
));
81 source
->SetJsonPath("strings.js");
82 source
->AddResourcePath("image_burner.js", IDR_IMAGEBURNER_JS
);
83 source
->SetDefaultResource(IDR_IMAGEBURNER_HTML
);
88 : public content::WebUIMessageHandler
,
89 public BurnController::Delegate
{
91 explicit WebUIHandler(content::WebContents
* contents
)
92 : burn_controller_(BurnController::CreateBurnController(contents
, this)){
95 virtual ~WebUIHandler() {
98 // WebUIMessageHandler implementation.
99 virtual void RegisterMessages() OVERRIDE
{
100 web_ui()->RegisterMessageCallback(
102 base::Bind(&WebUIHandler::HandleGetDevices
, base::Unretained(this)));
103 web_ui()->RegisterMessageCallback(
105 base::Bind(&WebUIHandler::HandleBurnImage
, base::Unretained(this)));
106 web_ui()->RegisterMessageCallback(
108 base::Bind(&WebUIHandler::HandleCancelBurnImage
,
109 base::Unretained(this)));
110 web_ui()->RegisterMessageCallback(
112 base::Bind(&WebUIHandler::HandleWebUIInitialized
,
113 base::Unretained(this)));
116 // BurnController::Delegate override.
117 virtual void OnSuccess() OVERRIDE
{
118 web_ui()->CallJavascriptFunction("browserBridge.reportSuccess");
121 // BurnController::Delegate override.
122 virtual void OnFail(int error_message_id
) OVERRIDE
{
123 base::StringValue
error_message(
124 l10n_util::GetStringUTF16(error_message_id
));
125 web_ui()->CallJavascriptFunction("browserBridge.reportFail", error_message
);
128 // BurnController::Delegate override.
129 virtual void OnDeviceAdded(const disks::DiskMountManager::Disk
& disk
)
131 base::DictionaryValue disk_value
;
132 CreateDiskValue(disk
, &disk_value
);
133 web_ui()->CallJavascriptFunction("browserBridge.deviceAdded", disk_value
);
136 // BurnController::Delegate override.
137 virtual void OnDeviceRemoved(const disks::DiskMountManager::Disk
& disk
)
139 base::StringValue
device_path_value(disk
.device_path());
140 web_ui()->CallJavascriptFunction("browserBridge.deviceRemoved",
144 // BurnController::Delegate override.
145 virtual void OnDeviceTooSmall(int64 device_size
) OVERRIDE
{
147 GetDataSizeText(device_size
, &size
);
148 base::StringValue
device_size_text(size
);
149 web_ui()->CallJavascriptFunction("browserBridge.reportDeviceTooSmall",
153 // BurnController::Delegate override.
154 virtual void OnProgress(ProgressType progress_type
,
155 int64 amount_finished
,
156 int64 amount_total
) OVERRIDE
{
157 const base::string16 time_remaining_text
=
158 l10n_util::GetStringUTF16(IDS_IMAGEBURN_PROGRESS_TIME_UNKNOWN
);
159 SendProgressSignal(progress_type
, amount_finished
, amount_total
,
160 time_remaining_text
);
163 // BurnController::Delegate override.
164 virtual void OnProgressWithRemainingTime(
165 ProgressType progress_type
,
166 int64 amount_finished
,
168 const base::TimeDelta
& time_remaining
) OVERRIDE
{
169 const base::string16 time_remaining_text
= l10n_util::GetStringFUTF16(
170 IDS_IMAGEBURN_DOWNLOAD_TIME_REMAINING
,
171 ui::TimeFormat::TimeRemaining(time_remaining
));
172 SendProgressSignal(progress_type
, amount_finished
, amount_total
,
173 time_remaining_text
);
176 // BurnController::Delegate override.
177 virtual void OnNetworkDetected() OVERRIDE
{
178 web_ui()->CallJavascriptFunction("browserBridge.reportNetworkDetected");
181 // BurnController::Delegate override.
182 virtual void OnNoNetwork() OVERRIDE
{
183 web_ui()->CallJavascriptFunction("browserBridge.reportNoNetwork");
187 void CreateDiskValue(const disks::DiskMountManager::Disk
& disk
,
188 base::DictionaryValue
* disk_value
) {
189 base::string16 label
= base::ASCIIToUTF16(disk
.drive_label());
190 base::i18n::AdjustStringForLocaleDirection(&label
);
191 disk_value
->SetString(std::string(kPropertyLabel
), label
);
192 disk_value
->SetString(std::string(kPropertyFilePath
), disk
.file_path());
193 disk_value
->SetString(std::string(kPropertyDevicePath
), disk
.device_path());
194 disk_value
->SetString(std::string(kPropertyDeviceType
),
195 disks::DiskMountManager::DeviceTypeToString(disk
.device_type()));
198 // Callback for the "getDevices" message.
199 void HandleGetDevices(const base::ListValue
* args
) {
200 const std::vector
<disks::DiskMountManager::Disk
> disks
201 = burn_controller_
->GetBurnableDevices();
202 base::ListValue results_value
;
203 for (size_t i
= 0; i
!= disks
.size(); ++i
) {
204 base::DictionaryValue
* disk_value
= new base::DictionaryValue();
205 CreateDiskValue(disks
[i
], disk_value
);
206 results_value
.Append(disk_value
);
208 web_ui()->CallJavascriptFunction("browserBridge.getDevicesCallback",
212 // Callback for the webuiInitialized message.
213 void HandleWebUIInitialized(const base::ListValue
* args
) {
214 burn_controller_
->Init();
217 // Callback for the "cancelBurnImage" message.
218 void HandleCancelBurnImage(const base::ListValue
* args
) {
219 burn_controller_
->CancelBurnImage();
222 // Callback for the "burnImage" message.
223 // It may be called with NULL if there is a handler that has started burning,
224 // and thus set the target paths.
225 void HandleBurnImage(const base::ListValue
* args
) {
226 base::FilePath target_device_path
;
227 ExtractTargetedDevicePath(*args
, 0, &target_device_path
);
229 base::FilePath target_file_path
;
230 ExtractTargetedDevicePath(*args
, 1, &target_file_path
);
232 burn_controller_
->StartBurnImage(target_device_path
, target_file_path
);
235 // Reports update to UI
236 void SendProgressSignal(ProgressType progress_type
,
237 int64 amount_finished
,
239 const base::string16
& time_remaining_text
) {
240 base::DictionaryValue progress
;
241 int progress_message_id
= 0;
242 switch (progress_type
) {
244 progress
.SetString("progressType", "download");
245 progress_message_id
= IDS_IMAGEBURN_DOWNLOAD_PROGRESS_TEXT
;
248 progress
.SetString("progressType", "unzip");
251 progress
.SetString("progressType", "burn");
252 progress_message_id
= IDS_IMAGEBURN_BURN_PROGRESS_TEXT
;
258 progress
.SetInteger("amountFinished", amount_finished
);
259 progress
.SetInteger("amountTotal", amount_total
);
260 if (amount_total
!= 0) {
261 base::string16 progress_text
;
262 GetProgressText(progress_message_id
, amount_finished
, amount_total
,
264 progress
.SetString("progressText", progress_text
);
266 progress
.SetString("progressText", "");
268 progress
.SetString("timeLeftText", time_remaining_text
);
270 web_ui()->CallJavascriptFunction("browserBridge.updateProgress", progress
);
273 // size_text should be previously created.
274 void GetDataSizeText(int64 size
, base::string16
* size_text
) {
275 *size_text
= ui::FormatBytes(size
);
276 base::i18n::AdjustStringForLocaleDirection(size_text
);
279 // progress_text should be previously created.
280 void GetProgressText(int message_id
,
281 int64 amount_finished
,
283 base::string16
* progress_text
) {
284 base::string16 finished
;
285 GetDataSizeText(amount_finished
, &finished
);
286 base::string16 total
;
287 GetDataSizeText(amount_total
, &total
);
288 *progress_text
= l10n_util::GetStringFUTF16(message_id
, finished
, total
);
291 // device_path has to be previously created.
292 void ExtractTargetedDevicePath(const base::ListValue
& list_value
,
294 base::FilePath
* device_path
) {
295 const base::Value
* list_member
;
296 std::string image_dest
;
297 if (list_value
.Get(index
, &list_member
) &&
298 list_member
->GetType() == base::Value::TYPE_STRING
&&
299 list_member
->GetAsString(&image_dest
)) {
300 *device_path
= base::FilePath(image_dest
);
302 LOG(ERROR
) << "Unable to get path string";
303 device_path
->clear();
307 scoped_ptr
<BurnController
> burn_controller_
;
309 DISALLOW_COPY_AND_ASSIGN(WebUIHandler
);
314 } // namespace imageburner
315 } // namespace chromeos
317 ////////////////////////////////////////////////////////////////////////////////
321 ////////////////////////////////////////////////////////////////////////////////
323 ImageBurnUI::ImageBurnUI(content::WebUI
* web_ui
) : WebUIController(web_ui
) {
324 chromeos::imageburner::WebUIHandler
* handler
=
325 new chromeos::imageburner::WebUIHandler(web_ui
->GetWebContents());
326 web_ui
->AddMessageHandler(handler
);
328 Profile
* profile
= Profile::FromWebUI(web_ui
);
329 content::WebUIDataSource::Add(
330 profile
, chromeos::imageburner::CreateImageburnerUIHTMLSource());