| // Copyright (c) 2012 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/imageburner/imageburner_ui.h" |
| |
| #include "base/bind.h" |
| #include "base/files/file_path.h" |
| #include "base/i18n/rtl.h" |
| #include "base/strings/string16.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/values.h" |
| #include "chrome/browser/chromeos/imageburner/burn_controller.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/common/url_constants.h" |
| #include "content/public/browser/web_ui.h" |
| #include "content/public/browser/web_ui_data_source.h" |
| #include "content/public/browser/web_ui_message_handler.h" |
| #include "grit/browser_resources.h" |
| #include "grit/generated_resources.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/base/l10n/time_format.h" |
| #include "ui/base/text/bytes_formatting.h" |
| #include "url/gurl.h" |
| |
| namespace chromeos { |
| namespace imageburner { |
| |
| namespace { |
| |
| const char kPropertyDevicePath[] = "devicePath"; |
| const char kPropertyFilePath[] = "filePath"; |
| const char kPropertyLabel[] = "label"; |
| const char kPropertyDeviceType[] = "type"; |
| |
| // Link displayed on imageburner ui. |
| const char kMoreInfoLink[] = |
| "http://www.chromium.org/chromium-os/chromiumos-design-docs/recovery-mode"; |
| |
| content::WebUIDataSource* CreateImageburnerUIHTMLSource() { |
| content::WebUIDataSource* source = |
| content::WebUIDataSource::Create(chrome::kChromeUIImageBurnerHost); |
| |
| source->AddLocalizedString("headerTitle", IDS_IMAGEBURN_HEADER_TITLE); |
| source->AddLocalizedString("headerDescription", |
| IDS_IMAGEBURN_HEADER_DESCRIPTION); |
| source->AddLocalizedString("headerLink", IDS_IMAGEBURN_HEADER_LINK); |
| source->AddLocalizedString("statusDevicesNone", |
| IDS_IMAGEBURN_NO_DEVICES_STATUS); |
| source->AddLocalizedString("warningDevicesNone", |
| IDS_IMAGEBURN_NO_DEVICES_WARNING); |
| source->AddLocalizedString("statusDevicesMultiple", |
| IDS_IMAGEBURN_MUL_DEVICES_STATUS); |
| source->AddLocalizedString("statusDeviceUSB", |
| IDS_IMAGEBURN_USB_DEVICE_STATUS); |
| source->AddLocalizedString("statusDeviceSD", |
| IDS_IMAGEBURN_SD_DEVICE_STATUS); |
| source->AddLocalizedString("warningDevices", |
| IDS_IMAGEBURN_DEVICES_WARNING); |
| source->AddLocalizedString("statusNoConnection", |
| IDS_IMAGEBURN_NO_CONNECTION_STATUS); |
| source->AddLocalizedString("warningNoConnection", |
| IDS_IMAGEBURN_NO_CONNECTION_WARNING); |
| source->AddLocalizedString("statusNoSpace", |
| IDS_IMAGEBURN_INSUFFICIENT_SPACE_STATUS); |
| source->AddLocalizedString("warningNoSpace", |
| IDS_IMAGEBURN_INSUFFICIENT_SPACE_WARNING); |
| source->AddLocalizedString("statusDownloading", |
| IDS_IMAGEBURN_DOWNLOADING_STATUS); |
| source->AddLocalizedString("statusUnzip", IDS_IMAGEBURN_UNZIP_STATUS); |
| source->AddLocalizedString("statusBurn", IDS_IMAGEBURN_BURN_STATUS); |
| source->AddLocalizedString("statusError", IDS_IMAGEBURN_ERROR_STATUS); |
| source->AddLocalizedString("statusSuccess", IDS_IMAGEBURN_SUCCESS_STATUS); |
| source->AddLocalizedString("warningSuccess", IDS_IMAGEBURN_SUCCESS_DESC); |
| source->AddLocalizedString("title", IDS_IMAGEBURN_PAGE_TITLE); |
| source->AddLocalizedString("confirmButton", IDS_IMAGEBURN_CONFIRM_BUTTON); |
| source->AddLocalizedString("cancelButton", IDS_IMAGEBURN_CANCEL_BUTTON); |
| source->AddLocalizedString("retryButton", IDS_IMAGEBURN_RETRY_BUTTON); |
| source->AddString("moreInfoLink", ASCIIToUTF16(kMoreInfoLink)); |
| |
| source->SetJsonPath("strings.js"); |
| source->AddResourcePath("image_burner.js", IDR_IMAGEBURNER_JS); |
| source->SetDefaultResource(IDR_IMAGEBURNER_HTML); |
| return source; |
| } |
| |
| class WebUIHandler |
| : public content::WebUIMessageHandler, |
| public BurnController::Delegate { |
| public: |
| explicit WebUIHandler(content::WebContents* contents) |
| : burn_controller_(BurnController::CreateBurnController(contents, this)){ |
| } |
| |
| virtual ~WebUIHandler() { |
| } |
| |
| // WebUIMessageHandler implementation. |
| virtual void RegisterMessages() OVERRIDE { |
| web_ui()->RegisterMessageCallback( |
| "getDevices", |
| base::Bind(&WebUIHandler::HandleGetDevices, base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| "burnImage", |
| base::Bind(&WebUIHandler::HandleBurnImage, base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| "cancelBurnImage", |
| base::Bind(&WebUIHandler::HandleCancelBurnImage, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback( |
| "webuiInitialized", |
| base::Bind(&WebUIHandler::HandleWebUIInitialized, |
| base::Unretained(this))); |
| } |
| |
| // BurnController::Delegate override. |
| virtual void OnSuccess() OVERRIDE { |
| web_ui()->CallJavascriptFunction("browserBridge.reportSuccess"); |
| } |
| |
| // BurnController::Delegate override. |
| virtual void OnFail(int error_message_id) OVERRIDE { |
| StringValue error_message(l10n_util::GetStringUTF16(error_message_id)); |
| web_ui()->CallJavascriptFunction("browserBridge.reportFail", error_message); |
| } |
| |
| // BurnController::Delegate override. |
| virtual void OnDeviceAdded(const disks::DiskMountManager::Disk& disk) |
| OVERRIDE { |
| DictionaryValue disk_value; |
| CreateDiskValue(disk, &disk_value); |
| web_ui()->CallJavascriptFunction("browserBridge.deviceAdded", disk_value); |
| } |
| |
| // BurnController::Delegate override. |
| virtual void OnDeviceRemoved(const disks::DiskMountManager::Disk& disk) |
| OVERRIDE { |
| StringValue device_path_value(disk.device_path()); |
| web_ui()->CallJavascriptFunction("browserBridge.deviceRemoved", |
| device_path_value); |
| } |
| |
| // BurnController::Delegate override. |
| virtual void OnDeviceTooSmall(int64 device_size) OVERRIDE { |
| string16 size; |
| GetDataSizeText(device_size, &size); |
| StringValue device_size_text(size); |
| web_ui()->CallJavascriptFunction("browserBridge.reportDeviceTooSmall", |
| device_size_text); |
| } |
| |
| // BurnController::Delegate override. |
| virtual void OnProgress(ProgressType progress_type, |
| int64 amount_finished, |
| int64 amount_total) OVERRIDE { |
| const string16 time_remaining_text = |
| l10n_util::GetStringUTF16(IDS_IMAGEBURN_PROGRESS_TIME_UNKNOWN); |
| SendProgressSignal(progress_type, amount_finished, amount_total, |
| time_remaining_text); |
| } |
| |
| // BurnController::Delegate override. |
| virtual void OnProgressWithRemainingTime( |
| ProgressType progress_type, |
| int64 amount_finished, |
| int64 amount_total, |
| const base::TimeDelta& time_remaining) OVERRIDE { |
| const string16 time_remaining_text = l10n_util::GetStringFUTF16( |
| IDS_IMAGEBURN_DOWNLOAD_TIME_REMAINING, |
| ui::TimeFormat::TimeRemaining(time_remaining)); |
| SendProgressSignal(progress_type, amount_finished, amount_total, |
| time_remaining_text); |
| } |
| |
| // BurnController::Delegate override. |
| virtual void OnNetworkDetected() OVERRIDE { |
| web_ui()->CallJavascriptFunction("browserBridge.reportNetworkDetected"); |
| } |
| |
| // BurnController::Delegate override. |
| virtual void OnNoNetwork() OVERRIDE { |
| web_ui()->CallJavascriptFunction("browserBridge.reportNoNetwork"); |
| } |
| |
| private: |
| void CreateDiskValue(const disks::DiskMountManager::Disk& disk, |
| DictionaryValue* disk_value) { |
| string16 label = ASCIIToUTF16(disk.drive_label()); |
| base::i18n::AdjustStringForLocaleDirection(&label); |
| disk_value->SetString(std::string(kPropertyLabel), label); |
| disk_value->SetString(std::string(kPropertyFilePath), disk.file_path()); |
| disk_value->SetString(std::string(kPropertyDevicePath), disk.device_path()); |
| disk_value->SetString(std::string(kPropertyDeviceType), |
| disks::DiskMountManager::DeviceTypeToString(disk.device_type())); |
| } |
| |
| // Callback for the "getDevices" message. |
| void HandleGetDevices(const ListValue* args) { |
| const std::vector<disks::DiskMountManager::Disk> disks |
| = burn_controller_->GetBurnableDevices(); |
| ListValue results_value; |
| for (size_t i = 0; i != disks.size(); ++i) { |
| DictionaryValue* disk_value = new DictionaryValue(); |
| CreateDiskValue(disks[i], disk_value); |
| results_value.Append(disk_value); |
| } |
| web_ui()->CallJavascriptFunction("browserBridge.getDevicesCallback", |
| results_value); |
| } |
| |
| // Callback for the webuiInitialized message. |
| void HandleWebUIInitialized(const ListValue* args) { |
| burn_controller_->Init(); |
| } |
| |
| // Callback for the "cancelBurnImage" message. |
| void HandleCancelBurnImage(const ListValue* args) { |
| burn_controller_->CancelBurnImage(); |
| } |
| |
| // Callback for the "burnImage" message. |
| // It may be called with NULL if there is a handler that has started burning, |
| // and thus set the target paths. |
| void HandleBurnImage(const ListValue* args) { |
| base::FilePath target_device_path; |
| ExtractTargetedDevicePath(*args, 0, &target_device_path); |
| |
| base::FilePath target_file_path; |
| ExtractTargetedDevicePath(*args, 1, &target_file_path); |
| |
| burn_controller_->StartBurnImage(target_device_path, target_file_path); |
| } |
| |
| // Reports update to UI |
| void SendProgressSignal(ProgressType progress_type, |
| int64 amount_finished, |
| int64 amount_total, |
| const string16& time_remaining_text) { |
| DictionaryValue progress; |
| int progress_message_id = 0; |
| switch (progress_type) { |
| case DOWNLOADING: |
| progress.SetString("progressType", "download"); |
| progress_message_id = IDS_IMAGEBURN_DOWNLOAD_PROGRESS_TEXT; |
| break; |
| case UNZIPPING: |
| progress.SetString("progressType", "unzip"); |
| break; |
| case BURNING: |
| progress.SetString("progressType", "burn"); |
| progress_message_id = IDS_IMAGEBURN_BURN_PROGRESS_TEXT; |
| break; |
| default: |
| return; |
| } |
| |
| progress.SetInteger("amountFinished", amount_finished); |
| progress.SetInteger("amountTotal", amount_total); |
| if (amount_total != 0) { |
| string16 progress_text; |
| GetProgressText(progress_message_id, amount_finished, amount_total, |
| &progress_text); |
| progress.SetString("progressText", progress_text); |
| } else { |
| progress.SetString("progressText", ""); |
| } |
| progress.SetString("timeLeftText", time_remaining_text); |
| |
| web_ui()->CallJavascriptFunction("browserBridge.updateProgress", progress); |
| } |
| |
| // size_text should be previously created. |
| void GetDataSizeText(int64 size, string16* size_text) { |
| *size_text = ui::FormatBytes(size); |
| base::i18n::AdjustStringForLocaleDirection(size_text); |
| } |
| |
| // progress_text should be previously created. |
| void GetProgressText(int message_id, |
| int64 amount_finished, |
| int64 amount_total, |
| string16* progress_text) { |
| string16 finished; |
| GetDataSizeText(amount_finished, &finished); |
| string16 total; |
| GetDataSizeText(amount_total, &total); |
| *progress_text = l10n_util::GetStringFUTF16(message_id, finished, total); |
| } |
| |
| // device_path has to be previously created. |
| void ExtractTargetedDevicePath(const ListValue& list_value, |
| int index, |
| base::FilePath* device_path) { |
| const Value* list_member; |
| std::string image_dest; |
| if (list_value.Get(index, &list_member) && |
| list_member->GetType() == Value::TYPE_STRING && |
| list_member->GetAsString(&image_dest)) { |
| *device_path = base::FilePath(image_dest); |
| } else { |
| LOG(ERROR) << "Unable to get path string"; |
| device_path->clear(); |
| } |
| } |
| |
| scoped_ptr<BurnController> burn_controller_; |
| |
| DISALLOW_COPY_AND_ASSIGN(WebUIHandler); |
| }; |
| |
| } // namespace |
| |
| } // namespace imageburner |
| } // namespace chromeos |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // ImageBurnUI |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| ImageBurnUI::ImageBurnUI(content::WebUI* web_ui) : WebUIController(web_ui) { |
| chromeos::imageburner::WebUIHandler* handler = |
| new chromeos::imageburner::WebUIHandler(web_ui->GetWebContents()); |
| web_ui->AddMessageHandler(handler); |
| |
| Profile* profile = Profile::FromWebUI(web_ui); |
| content::WebUIDataSource::Add( |
| profile, chromeos::imageburner::CreateImageburnerUIHTMLSource()); |
| } |