imageburner_ui.cc revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
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" 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" 24#include "url/gurl.h" 25 26namespace chromeos { 27namespace imageburner { 28 29namespace { 30 31const char kPropertyDevicePath[] = "devicePath"; 32const char kPropertyFilePath[] = "filePath"; 33const char kPropertyLabel[] = "label"; 34const char kPropertyDeviceType[] = "type"; 35 36// Link displayed on imageburner ui. 37const char kMoreInfoLink[] = 38 "http://www.chromium.org/chromium-os/chromiumos-design-docs/recovery-mode"; 39 40content::WebUIDataSource* CreateImageburnerUIHTMLSource() { 41 content::WebUIDataSource* source = 42 content::WebUIDataSource::Create(chrome::kChromeUIImageBurnerHost); 43 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", ASCIIToUTF16(kMoreInfoLink)); 80 81 source->SetJsonPath("strings.js"); 82 source->AddResourcePath("image_burner.js", IDR_IMAGEBURNER_JS); 83 source->SetDefaultResource(IDR_IMAGEBURNER_HTML); 84 return source; 85} 86 87class WebUIHandler 88 : public content::WebUIMessageHandler, 89 public BurnController::Delegate { 90 public: 91 explicit WebUIHandler(content::WebContents* contents) 92 : burn_controller_(BurnController::CreateBurnController(contents, this)){ 93 } 94 95 virtual ~WebUIHandler() { 96 } 97 98 // WebUIMessageHandler implementation. 99 virtual void RegisterMessages() OVERRIDE { 100 web_ui()->RegisterMessageCallback( 101 "getDevices", 102 base::Bind(&WebUIHandler::HandleGetDevices, base::Unretained(this))); 103 web_ui()->RegisterMessageCallback( 104 "burnImage", 105 base::Bind(&WebUIHandler::HandleBurnImage, base::Unretained(this))); 106 web_ui()->RegisterMessageCallback( 107 "cancelBurnImage", 108 base::Bind(&WebUIHandler::HandleCancelBurnImage, 109 base::Unretained(this))); 110 web_ui()->RegisterMessageCallback( 111 "webuiInitialized", 112 base::Bind(&WebUIHandler::HandleWebUIInitialized, 113 base::Unretained(this))); 114 } 115 116 // BurnController::Delegate override. 117 virtual void OnSuccess() OVERRIDE { 118 web_ui()->CallJavascriptFunction("browserBridge.reportSuccess"); 119 } 120 121 // BurnController::Delegate override. 122 virtual void OnFail(int error_message_id) OVERRIDE { 123 StringValue error_message(l10n_util::GetStringUTF16(error_message_id)); 124 web_ui()->CallJavascriptFunction("browserBridge.reportFail", error_message); 125 } 126 127 // BurnController::Delegate override. 128 virtual void OnDeviceAdded(const disks::DiskMountManager::Disk& disk) 129 OVERRIDE { 130 DictionaryValue disk_value; 131 CreateDiskValue(disk, &disk_value); 132 web_ui()->CallJavascriptFunction("browserBridge.deviceAdded", disk_value); 133 } 134 135 // BurnController::Delegate override. 136 virtual void OnDeviceRemoved(const disks::DiskMountManager::Disk& disk) 137 OVERRIDE { 138 StringValue device_path_value(disk.device_path()); 139 web_ui()->CallJavascriptFunction("browserBridge.deviceRemoved", 140 device_path_value); 141 } 142 143 // BurnController::Delegate override. 144 virtual void OnDeviceTooSmall(int64 device_size) OVERRIDE { 145 string16 size; 146 GetDataSizeText(device_size, &size); 147 StringValue device_size_text(size); 148 web_ui()->CallJavascriptFunction("browserBridge.reportDeviceTooSmall", 149 device_size_text); 150 } 151 152 // BurnController::Delegate override. 153 virtual void OnProgress(ProgressType progress_type, 154 int64 amount_finished, 155 int64 amount_total) OVERRIDE { 156 const string16 time_remaining_text = 157 l10n_util::GetStringUTF16(IDS_IMAGEBURN_PROGRESS_TIME_UNKNOWN); 158 SendProgressSignal(progress_type, amount_finished, amount_total, 159 time_remaining_text); 160 } 161 162 // BurnController::Delegate override. 163 virtual void OnProgressWithRemainingTime( 164 ProgressType progress_type, 165 int64 amount_finished, 166 int64 amount_total, 167 const base::TimeDelta& time_remaining) OVERRIDE { 168 const string16 time_remaining_text = l10n_util::GetStringFUTF16( 169 IDS_IMAGEBURN_DOWNLOAD_TIME_REMAINING, 170 ui::TimeFormat::TimeRemaining(time_remaining)); 171 SendProgressSignal(progress_type, amount_finished, amount_total, 172 time_remaining_text); 173 } 174 175 // BurnController::Delegate override. 176 virtual void OnNetworkDetected() OVERRIDE { 177 web_ui()->CallJavascriptFunction("browserBridge.reportNetworkDetected"); 178 } 179 180 // BurnController::Delegate override. 181 virtual void OnNoNetwork() OVERRIDE { 182 web_ui()->CallJavascriptFunction("browserBridge.reportNoNetwork"); 183 } 184 185 private: 186 void CreateDiskValue(const disks::DiskMountManager::Disk& disk, 187 DictionaryValue* disk_value) { 188 string16 label = ASCIIToUTF16(disk.drive_label()); 189 base::i18n::AdjustStringForLocaleDirection(&label); 190 disk_value->SetString(std::string(kPropertyLabel), label); 191 disk_value->SetString(std::string(kPropertyFilePath), disk.file_path()); 192 disk_value->SetString(std::string(kPropertyDevicePath), disk.device_path()); 193 disk_value->SetString(std::string(kPropertyDeviceType), 194 disks::DiskMountManager::DeviceTypeToString(disk.device_type())); 195 } 196 197 // Callback for the "getDevices" message. 198 void HandleGetDevices(const ListValue* args) { 199 const std::vector<disks::DiskMountManager::Disk> disks 200 = burn_controller_->GetBurnableDevices(); 201 ListValue results_value; 202 for (size_t i = 0; i != disks.size(); ++i) { 203 DictionaryValue* disk_value = new DictionaryValue(); 204 CreateDiskValue(disks[i], disk_value); 205 results_value.Append(disk_value); 206 } 207 web_ui()->CallJavascriptFunction("browserBridge.getDevicesCallback", 208 results_value); 209 } 210 211 // Callback for the webuiInitialized message. 212 void HandleWebUIInitialized(const ListValue* args) { 213 burn_controller_->Init(); 214 } 215 216 // Callback for the "cancelBurnImage" message. 217 void HandleCancelBurnImage(const ListValue* args) { 218 burn_controller_->CancelBurnImage(); 219 } 220 221 // Callback for the "burnImage" message. 222 // It may be called with NULL if there is a handler that has started burning, 223 // and thus set the target paths. 224 void HandleBurnImage(const ListValue* args) { 225 base::FilePath target_device_path; 226 ExtractTargetedDevicePath(*args, 0, &target_device_path); 227 228 base::FilePath target_file_path; 229 ExtractTargetedDevicePath(*args, 1, &target_file_path); 230 231 burn_controller_->StartBurnImage(target_device_path, target_file_path); 232 } 233 234 // Reports update to UI 235 void SendProgressSignal(ProgressType progress_type, 236 int64 amount_finished, 237 int64 amount_total, 238 const string16& time_remaining_text) { 239 DictionaryValue progress; 240 int progress_message_id = 0; 241 switch (progress_type) { 242 case DOWNLOADING: 243 progress.SetString("progressType", "download"); 244 progress_message_id = IDS_IMAGEBURN_DOWNLOAD_PROGRESS_TEXT; 245 break; 246 case UNZIPPING: 247 progress.SetString("progressType", "unzip"); 248 break; 249 case BURNING: 250 progress.SetString("progressType", "burn"); 251 progress_message_id = IDS_IMAGEBURN_BURN_PROGRESS_TEXT; 252 break; 253 default: 254 return; 255 } 256 257 progress.SetInteger("amountFinished", amount_finished); 258 progress.SetInteger("amountTotal", amount_total); 259 if (amount_total != 0) { 260 string16 progress_text; 261 GetProgressText(progress_message_id, amount_finished, amount_total, 262 &progress_text); 263 progress.SetString("progressText", progress_text); 264 } else { 265 progress.SetString("progressText", ""); 266 } 267 progress.SetString("timeLeftText", time_remaining_text); 268 269 web_ui()->CallJavascriptFunction("browserBridge.updateProgress", progress); 270 } 271 272 // size_text should be previously created. 273 void GetDataSizeText(int64 size, string16* size_text) { 274 *size_text = ui::FormatBytes(size); 275 base::i18n::AdjustStringForLocaleDirection(size_text); 276 } 277 278 // progress_text should be previously created. 279 void GetProgressText(int message_id, 280 int64 amount_finished, 281 int64 amount_total, 282 string16* progress_text) { 283 string16 finished; 284 GetDataSizeText(amount_finished, &finished); 285 string16 total; 286 GetDataSizeText(amount_total, &total); 287 *progress_text = l10n_util::GetStringFUTF16(message_id, finished, total); 288 } 289 290 // device_path has to be previously created. 291 void ExtractTargetedDevicePath(const ListValue& list_value, 292 int index, 293 base::FilePath* device_path) { 294 const Value* list_member; 295 std::string image_dest; 296 if (list_value.Get(index, &list_member) && 297 list_member->GetType() == Value::TYPE_STRING && 298 list_member->GetAsString(&image_dest)) { 299 *device_path = base::FilePath(image_dest); 300 } else { 301 LOG(ERROR) << "Unable to get path string"; 302 device_path->clear(); 303 } 304 } 305 306 scoped_ptr<BurnController> burn_controller_; 307 308 DISALLOW_COPY_AND_ASSIGN(WebUIHandler); 309}; 310 311} // namespace 312 313} // namespace imageburner 314} // namespace chromeos 315 316//////////////////////////////////////////////////////////////////////////////// 317// 318// ImageBurnUI 319// 320//////////////////////////////////////////////////////////////////////////////// 321 322ImageBurnUI::ImageBurnUI(content::WebUI* web_ui) : WebUIController(web_ui) { 323 chromeos::imageburner::WebUIHandler* handler = 324 new chromeos::imageburner::WebUIHandler(web_ui->GetWebContents()); 325 web_ui->AddMessageHandler(handler); 326 327 Profile* profile = Profile::FromWebUI(web_ui); 328 content::WebUIDataSource::Add( 329 profile, chromeos::imageburner::CreateImageburnerUIHTMLSource()); 330} 331