Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 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. |
| 4 | |
| 5 | #include "chrome/browser/ui/webui/chromeos/imageburner/imageburner_ui.h" |
| 6 | |
| 7 | #include "base/bind.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 8 | #include "base/files/file_path.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 9 | #include "base/i18n/rtl.h" |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 10 | #include "base/strings/string16.h" |
| 11 | #include "base/strings/utf_string_conversions.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 12 | #include "base/values.h" |
| 13 | #include "chrome/browser/chromeos/imageburner/burn_controller.h" |
| 14 | #include "chrome/browser/profiles/profile.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 15 | #include "chrome/common/url_constants.h" |
| 16 | #include "content/public/browser/web_ui.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 17 | #include "content/public/browser/web_ui_data_source.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 18 | #include "content/public/browser/web_ui_message_handler.h" |
| 19 | #include "grit/browser_resources.h" |
| 20 | #include "grit/generated_resources.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 21 | #include "ui/base/l10n/l10n_util.h" |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 22 | #include "ui/base/l10n/time_format.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 23 | #include "ui/base/text/bytes_formatting.h" |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 24 | #include "url/gurl.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 25 | |
| 26 | namespace chromeos { |
| 27 | namespace imageburner { |
| 28 | |
| 29 | namespace { |
| 30 | |
| 31 | const char kPropertyDevicePath[] = "devicePath"; |
| 32 | const char kPropertyFilePath[] = "filePath"; |
| 33 | const char kPropertyLabel[] = "label"; |
| 34 | const char kPropertyPath[] = "path"; |
| 35 | const char kPropertyDeviceType[] = "type"; |
| 36 | |
| 37 | // Link displayed on imageburner ui. |
| 38 | const char kMoreInfoLink[] = |
| 39 | "http://www.chromium.org/chromium-os/chromiumos-design-docs/recovery-mode"; |
| 40 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 41 | content::WebUIDataSource* CreateImageburnerUIHTMLSource() { |
| 42 | content::WebUIDataSource* source = |
| 43 | content::WebUIDataSource::Create(chrome::kChromeUIImageBurnerHost); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 44 | |
| 45 | source->AddLocalizedString("headerTitle", IDS_IMAGEBURN_HEADER_TITLE); |
| 46 | source->AddLocalizedString("headerDescription", |
| 47 | IDS_IMAGEBURN_HEADER_DESCRIPTION); |
| 48 | source->AddLocalizedString("headerLink", IDS_IMAGEBURN_HEADER_LINK); |
| 49 | source->AddLocalizedString("statusDevicesNone", |
| 50 | IDS_IMAGEBURN_NO_DEVICES_STATUS); |
| 51 | source->AddLocalizedString("warningDevicesNone", |
| 52 | IDS_IMAGEBURN_NO_DEVICES_WARNING); |
| 53 | source->AddLocalizedString("statusDevicesMultiple", |
| 54 | IDS_IMAGEBURN_MUL_DEVICES_STATUS); |
| 55 | source->AddLocalizedString("statusDeviceUSB", |
| 56 | IDS_IMAGEBURN_USB_DEVICE_STATUS); |
| 57 | source->AddLocalizedString("statusDeviceSD", |
| 58 | IDS_IMAGEBURN_SD_DEVICE_STATUS); |
| 59 | source->AddLocalizedString("warningDevices", |
| 60 | IDS_IMAGEBURN_DEVICES_WARNING); |
| 61 | source->AddLocalizedString("statusNoConnection", |
| 62 | IDS_IMAGEBURN_NO_CONNECTION_STATUS); |
| 63 | source->AddLocalizedString("warningNoConnection", |
| 64 | IDS_IMAGEBURN_NO_CONNECTION_WARNING); |
| 65 | source->AddLocalizedString("statusNoSpace", |
| 66 | IDS_IMAGEBURN_INSUFFICIENT_SPACE_STATUS); |
| 67 | source->AddLocalizedString("warningNoSpace", |
| 68 | IDS_IMAGEBURN_INSUFFICIENT_SPACE_WARNING); |
| 69 | source->AddLocalizedString("statusDownloading", |
| 70 | IDS_IMAGEBURN_DOWNLOADING_STATUS); |
| 71 | source->AddLocalizedString("statusUnzip", IDS_IMAGEBURN_UNZIP_STATUS); |
| 72 | source->AddLocalizedString("statusBurn", IDS_IMAGEBURN_BURN_STATUS); |
| 73 | source->AddLocalizedString("statusError", IDS_IMAGEBURN_ERROR_STATUS); |
| 74 | source->AddLocalizedString("statusSuccess", IDS_IMAGEBURN_SUCCESS_STATUS); |
| 75 | source->AddLocalizedString("warningSuccess", IDS_IMAGEBURN_SUCCESS_DESC); |
| 76 | source->AddLocalizedString("title", IDS_IMAGEBURN_PAGE_TITLE); |
| 77 | source->AddLocalizedString("confirmButton", IDS_IMAGEBURN_CONFIRM_BUTTON); |
| 78 | source->AddLocalizedString("cancelButton", IDS_IMAGEBURN_CANCEL_BUTTON); |
| 79 | source->AddLocalizedString("retryButton", IDS_IMAGEBURN_RETRY_BUTTON); |
| 80 | source->AddString("moreInfoLink", ASCIIToUTF16(kMoreInfoLink)); |
| 81 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 82 | source->SetJsonPath("strings.js"); |
| 83 | source->AddResourcePath("image_burner.js", IDR_IMAGEBURNER_JS); |
| 84 | source->SetDefaultResource(IDR_IMAGEBURNER_HTML); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 85 | return source; |
| 86 | } |
| 87 | |
| 88 | class WebUIHandler |
| 89 | : public content::WebUIMessageHandler, |
| 90 | public BurnController::Delegate { |
| 91 | public: |
| 92 | explicit WebUIHandler(content::WebContents* contents) |
| 93 | : burn_controller_(BurnController::CreateBurnController(contents, this)){ |
| 94 | } |
| 95 | |
| 96 | virtual ~WebUIHandler() { |
| 97 | } |
| 98 | |
| 99 | // WebUIMessageHandler implementation. |
| 100 | virtual void RegisterMessages() OVERRIDE { |
| 101 | web_ui()->RegisterMessageCallback( |
| 102 | "getDevices", |
| 103 | base::Bind(&WebUIHandler::HandleGetDevices, base::Unretained(this))); |
| 104 | web_ui()->RegisterMessageCallback( |
| 105 | "burnImage", |
| 106 | base::Bind(&WebUIHandler::HandleBurnImage, base::Unretained(this))); |
| 107 | web_ui()->RegisterMessageCallback( |
| 108 | "cancelBurnImage", |
| 109 | base::Bind(&WebUIHandler::HandleCancelBurnImage, |
| 110 | base::Unretained(this))); |
| 111 | web_ui()->RegisterMessageCallback( |
| 112 | "webuiInitialized", |
| 113 | base::Bind(&WebUIHandler::HandleWebUIInitialized, |
| 114 | base::Unretained(this))); |
| 115 | } |
| 116 | |
| 117 | // BurnController::Delegate override. |
| 118 | virtual void OnSuccess() OVERRIDE { |
| 119 | web_ui()->CallJavascriptFunction("browserBridge.reportSuccess"); |
| 120 | } |
| 121 | |
| 122 | // BurnController::Delegate override. |
| 123 | virtual void OnFail(int error_message_id) OVERRIDE { |
| 124 | StringValue error_message(l10n_util::GetStringUTF16(error_message_id)); |
| 125 | web_ui()->CallJavascriptFunction("browserBridge.reportFail", error_message); |
| 126 | } |
| 127 | |
| 128 | // BurnController::Delegate override. |
| 129 | virtual void OnDeviceAdded(const disks::DiskMountManager::Disk& disk) |
| 130 | OVERRIDE { |
| 131 | DictionaryValue disk_value; |
| 132 | CreateDiskValue(disk, &disk_value); |
| 133 | web_ui()->CallJavascriptFunction("browserBridge.deviceAdded", disk_value); |
| 134 | } |
| 135 | |
| 136 | // BurnController::Delegate override. |
| 137 | virtual void OnDeviceRemoved(const disks::DiskMountManager::Disk& disk) |
| 138 | OVERRIDE { |
| 139 | StringValue device_path_value(disk.device_path()); |
| 140 | web_ui()->CallJavascriptFunction("browserBridge.deviceRemoved", |
| 141 | device_path_value); |
| 142 | } |
| 143 | |
| 144 | // BurnController::Delegate override. |
| 145 | virtual void OnDeviceTooSmall(int64 device_size) OVERRIDE { |
| 146 | string16 size; |
| 147 | GetDataSizeText(device_size, &size); |
| 148 | StringValue device_size_text(size); |
| 149 | web_ui()->CallJavascriptFunction("browserBridge.reportDeviceTooSmall", |
| 150 | device_size_text); |
| 151 | } |
| 152 | |
| 153 | // BurnController::Delegate override. |
| 154 | virtual void OnProgress(ProgressType progress_type, |
| 155 | int64 amount_finished, |
| 156 | int64 amount_total) OVERRIDE { |
| 157 | const 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); |
| 161 | } |
| 162 | |
| 163 | // BurnController::Delegate override. |
| 164 | virtual void OnProgressWithRemainingTime( |
| 165 | ProgressType progress_type, |
| 166 | int64 amount_finished, |
| 167 | int64 amount_total, |
| 168 | const base::TimeDelta& time_remaining) OVERRIDE { |
| 169 | const string16 time_remaining_text = l10n_util::GetStringFUTF16( |
| 170 | IDS_IMAGEBURN_DOWNLOAD_TIME_REMAINING, |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 171 | ui::TimeFormat::TimeRemaining(time_remaining)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 172 | SendProgressSignal(progress_type, amount_finished, amount_total, |
| 173 | time_remaining_text); |
| 174 | } |
| 175 | |
| 176 | // BurnController::Delegate override. |
| 177 | virtual void OnNetworkDetected() OVERRIDE { |
| 178 | web_ui()->CallJavascriptFunction("browserBridge.reportNetworkDetected"); |
| 179 | } |
| 180 | |
| 181 | // BurnController::Delegate override. |
| 182 | virtual void OnNoNetwork() OVERRIDE { |
| 183 | web_ui()->CallJavascriptFunction("browserBridge.reportNoNetwork"); |
| 184 | } |
| 185 | |
| 186 | private: |
| 187 | void CreateDiskValue(const disks::DiskMountManager::Disk& disk, |
| 188 | DictionaryValue* disk_value) { |
| 189 | string16 label = 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())); |
| 196 | } |
| 197 | |
| 198 | // Callback for the "getDevices" message. |
| 199 | void HandleGetDevices(const ListValue* args) { |
| 200 | const std::vector<disks::DiskMountManager::Disk> disks |
| 201 | = burn_controller_->GetBurnableDevices(); |
| 202 | ListValue results_value; |
| 203 | for (size_t i = 0; i != disks.size(); ++i) { |
| 204 | DictionaryValue* disk_value = new DictionaryValue(); |
| 205 | CreateDiskValue(disks[i], disk_value); |
| 206 | results_value.Append(disk_value); |
| 207 | } |
| 208 | web_ui()->CallJavascriptFunction("browserBridge.getDevicesCallback", |
| 209 | results_value); |
| 210 | } |
| 211 | |
| 212 | // Callback for the webuiInitialized message. |
| 213 | void HandleWebUIInitialized(const ListValue* args) { |
| 214 | burn_controller_->Init(); |
| 215 | } |
| 216 | |
| 217 | // Callback for the "cancelBurnImage" message. |
| 218 | void HandleCancelBurnImage(const ListValue* args) { |
| 219 | burn_controller_->CancelBurnImage(); |
| 220 | } |
| 221 | |
| 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 ListValue* args) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 226 | base::FilePath target_device_path; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 227 | ExtractTargetedDevicePath(*args, 0, &target_device_path); |
| 228 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 229 | base::FilePath target_file_path; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 230 | ExtractTargetedDevicePath(*args, 1, &target_file_path); |
| 231 | |
| 232 | burn_controller_->StartBurnImage(target_device_path, target_file_path); |
| 233 | } |
| 234 | |
| 235 | // Reports update to UI |
| 236 | void SendProgressSignal(ProgressType progress_type, |
| 237 | int64 amount_finished, |
| 238 | int64 amount_total, |
| 239 | const string16& time_remaining_text) { |
| 240 | DictionaryValue progress; |
| 241 | int progress_message_id = 0; |
| 242 | switch (progress_type) { |
| 243 | case DOWNLOADING: |
| 244 | progress.SetString("progressType", "download"); |
| 245 | progress_message_id = IDS_IMAGEBURN_DOWNLOAD_PROGRESS_TEXT; |
| 246 | break; |
| 247 | case UNZIPPING: |
| 248 | progress.SetString("progressType", "unzip"); |
| 249 | break; |
| 250 | case BURNING: |
| 251 | progress.SetString("progressType", "burn"); |
| 252 | progress_message_id = IDS_IMAGEBURN_BURN_PROGRESS_TEXT; |
| 253 | break; |
| 254 | default: |
| 255 | return; |
| 256 | } |
| 257 | |
| 258 | progress.SetInteger("amountFinished", amount_finished); |
| 259 | progress.SetInteger("amountTotal", amount_total); |
| 260 | if (amount_total != 0) { |
| 261 | string16 progress_text; |
| 262 | GetProgressText(progress_message_id, amount_finished, amount_total, |
| 263 | &progress_text); |
| 264 | progress.SetString("progressText", progress_text); |
| 265 | } else { |
| 266 | progress.SetString("progressText", ""); |
| 267 | } |
| 268 | progress.SetString("timeLeftText", time_remaining_text); |
| 269 | |
| 270 | web_ui()->CallJavascriptFunction("browserBridge.updateProgress", progress); |
| 271 | } |
| 272 | |
| 273 | // size_text should be previously created. |
| 274 | void GetDataSizeText(int64 size, string16* size_text) { |
| 275 | *size_text = ui::FormatBytes(size); |
| 276 | base::i18n::AdjustStringForLocaleDirection(size_text); |
| 277 | } |
| 278 | |
| 279 | // progress_text should be previously created. |
| 280 | void GetProgressText(int message_id, |
| 281 | int64 amount_finished, |
| 282 | int64 amount_total, |
| 283 | string16* progress_text) { |
| 284 | string16 finished; |
| 285 | GetDataSizeText(amount_finished, &finished); |
| 286 | string16 total; |
| 287 | GetDataSizeText(amount_total, &total); |
| 288 | *progress_text = l10n_util::GetStringFUTF16(message_id, finished, total); |
| 289 | } |
| 290 | |
| 291 | // device_path has to be previously created. |
| 292 | void ExtractTargetedDevicePath(const ListValue& list_value, |
| 293 | int index, |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 294 | base::FilePath* device_path) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 295 | const Value* list_member; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 296 | std::string image_dest; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 297 | if (list_value.Get(index, &list_member) && |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 298 | list_member->GetType() == Value::TYPE_STRING && |
| 299 | list_member->GetAsString(&image_dest)) { |
| 300 | *device_path = base::FilePath(image_dest); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 301 | } else { |
| 302 | LOG(ERROR) << "Unable to get path string"; |
| 303 | device_path->clear(); |
| 304 | } |
| 305 | } |
| 306 | |
| 307 | scoped_ptr<BurnController> burn_controller_; |
| 308 | |
| 309 | DISALLOW_COPY_AND_ASSIGN(WebUIHandler); |
| 310 | }; |
| 311 | |
| 312 | } // namespace |
| 313 | |
| 314 | } // namespace imageburner |
| 315 | } // namespace chromeos |
| 316 | |
| 317 | //////////////////////////////////////////////////////////////////////////////// |
| 318 | // |
| 319 | // ImageBurnUI |
| 320 | // |
| 321 | //////////////////////////////////////////////////////////////////////////////// |
| 322 | |
| 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); |
| 327 | |
| 328 | Profile* profile = Profile::FromWebUI(web_ui); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 329 | content::WebUIDataSource::Add( |
| 330 | profile, chromeos::imageburner::CreateImageburnerUIHTMLSource()); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 331 | } |