OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 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/options2/chromeos/about_page_handler.h" |
| 6 |
| 7 #include <vector> |
| 8 |
| 9 #include "base/basictypes.h" |
| 10 #include "base/bind.h" |
| 11 #include "base/bind_helpers.h" |
| 12 #include "base/command_line.h" |
| 13 #include "base/i18n/time_formatting.h" |
| 14 #include "base/string16.h" |
| 15 #include "base/string_number_conversions.h" |
| 16 #include "base/time.h" |
| 17 #include "base/utf_string_conversions.h" |
| 18 #include "base/values.h" |
| 19 #include "chrome/browser/chromeos/dbus/dbus_thread_manager.h" |
| 20 #include "chrome/browser/chromeos/dbus/power_manager_client.h" |
| 21 #include "chrome/browser/chromeos/dbus/update_engine_client.h" |
| 22 #include "chrome/browser/chromeos/login/user_manager.h" |
| 23 #include "chrome/browser/chromeos/login/wizard_controller.h" |
| 24 #include "chrome/browser/google/google_util.h" |
| 25 #include "chrome/common/chrome_version_info.h" |
| 26 #include "chrome/common/url_constants.h" |
| 27 #include "content/public/common/content_client.h" |
| 28 #include "googleurl/src/gurl.h" |
| 29 #include "grit/chromium_strings.h" |
| 30 #include "grit/generated_resources.h" |
| 31 #include "grit/locale_settings.h" |
| 32 #include "grit/theme_resources.h" |
| 33 #include "ui/base/l10n/l10n_util.h" |
| 34 #include "ui/base/resource/resource_bundle.h" |
| 35 #include "v8/include/v8.h" |
| 36 #include "webkit/glue/user_agent.h" |
| 37 #include "webkit/glue/webkit_glue.h" |
| 38 #include "webkit/glue/user_agent.h" |
| 39 |
| 40 namespace { |
| 41 |
| 42 // These are used as placeholder text around the links in the text in the |
| 43 // license. |
| 44 const char kBeginLink[] = "BEGIN_LINK"; |
| 45 const char kEndLink[] = "END_LINK"; |
| 46 const char kBeginLinkChr[] = "BEGIN_LINK_CHR"; |
| 47 const char kBeginLinkOss[] = "BEGIN_LINK_OSS"; |
| 48 const char kEndLinkChr[] = "END_LINK_CHR"; |
| 49 const char kEndLinkOss[] = "END_LINK_OSS"; |
| 50 const char kBeginLinkCrosOss[] = "BEGIN_LINK_CROS_OSS"; |
| 51 const char kEndLinkCrosOss[] = "END_LINK_CROS_OSS"; |
| 52 |
| 53 // Returns a substring [start, end) from |text|. |
| 54 std::string StringSubRange(const std::string& text, size_t start, |
| 55 size_t end) { |
| 56 DCHECK(end > start); |
| 57 return text.substr(start, end - start); |
| 58 } |
| 59 |
| 60 } // namespace |
| 61 |
| 62 namespace chromeos { |
| 63 |
| 64 class AboutPageHandler::UpdateObserver |
| 65 : public UpdateEngineClient::Observer { |
| 66 public: |
| 67 explicit UpdateObserver(AboutPageHandler* handler) : page_handler_(handler) {} |
| 68 virtual ~UpdateObserver() {} |
| 69 |
| 70 AboutPageHandler* page_handler() const { return page_handler_; } |
| 71 |
| 72 private: |
| 73 virtual void UpdateStatusChanged( |
| 74 const UpdateEngineClient::Status& status) OVERRIDE { |
| 75 page_handler_->UpdateStatus(status); |
| 76 } |
| 77 |
| 78 AboutPageHandler* page_handler_; |
| 79 |
| 80 DISALLOW_COPY_AND_ASSIGN(UpdateObserver); |
| 81 }; |
| 82 |
| 83 AboutPageHandler::AboutPageHandler() |
| 84 : progress_(-1), |
| 85 sticky_(false), |
| 86 started_(false) |
| 87 {} |
| 88 |
| 89 AboutPageHandler::~AboutPageHandler() { |
| 90 if (update_observer_.get()) { |
| 91 DBusThreadManager::Get()->GetUpdateEngineClient()-> |
| 92 RemoveObserver(update_observer_.get()); |
| 93 } |
| 94 } |
| 95 |
| 96 void AboutPageHandler::GetLocalizedValues(DictionaryValue* localized_strings) { |
| 97 DCHECK(localized_strings); |
| 98 |
| 99 static OptionsStringResource resources[] = { |
| 100 { "firmware", IDS_ABOUT_PAGE_FIRMWARE }, |
| 101 { "product", IDS_PRODUCT_OS_NAME }, |
| 102 { "os", IDS_PRODUCT_OS_NAME }, |
| 103 { "platform", IDS_PLATFORM_LABEL }, |
| 104 { "loading", IDS_ABOUT_PAGE_LOADING }, |
| 105 { "check_now", IDS_ABOUT_PAGE_CHECK_NOW }, |
| 106 { "update_status", IDS_UPGRADE_CHECK_STARTED }, |
| 107 { "restart_now", IDS_RELAUNCH_AND_UPDATE }, |
| 108 { "browser", IDS_PRODUCT_NAME }, |
| 109 { "more_info", IDS_ABOUT_PAGE_MORE_INFO }, |
| 110 { "copyright", IDS_ABOUT_VERSION_COPYRIGHT }, |
| 111 { "channel", IDS_ABOUT_PAGE_CHANNEL }, |
| 112 { "stable", IDS_ABOUT_PAGE_CHANNEL_STABLE }, |
| 113 { "beta", IDS_ABOUT_PAGE_CHANNEL_BETA }, |
| 114 { "dev", IDS_ABOUT_PAGE_CHANNEL_DEVELOPMENT }, |
| 115 { "canary", IDS_ABOUT_PAGE_CHANNEL_CANARY }, |
| 116 { "channel_warning_header", IDS_ABOUT_PAGE_CHANNEL_WARNING_HEADER }, |
| 117 { "channel_warning_text", IDS_ABOUT_PAGE_CHANNEL_WARNING_TEXT }, |
| 118 { "user_agent", IDS_ABOUT_VERSION_USER_AGENT }, |
| 119 { "command_line", IDS_ABOUT_VERSION_COMMAND_LINE }, |
| 120 }; |
| 121 |
| 122 RegisterStrings(localized_strings, resources, arraysize(resources)); |
| 123 RegisterTitle(localized_strings, "aboutPage", IDS_ABOUT_TAB_TITLE); |
| 124 |
| 125 // browser version |
| 126 |
| 127 chrome::VersionInfo version_info; |
| 128 DCHECK(version_info.is_valid()); |
| 129 |
| 130 std::string browser_version = version_info.Version(); |
| 131 std::string version_modifier = |
| 132 chrome::VersionInfo::GetVersionStringModifier(); |
| 133 if (!version_modifier.empty()) |
| 134 browser_version += " " + version_modifier; |
| 135 |
| 136 #if !defined(GOOGLE_CHROME_BUILD) |
| 137 browser_version += " ("; |
| 138 browser_version += version_info.LastChange(); |
| 139 browser_version += ")"; |
| 140 #endif |
| 141 |
| 142 localized_strings->SetString("browser_version", browser_version); |
| 143 |
| 144 // license |
| 145 |
| 146 std::string text = l10n_util::GetStringUTF8(IDS_ABOUT_VERSION_LICENSE); |
| 147 |
| 148 bool chromium_url_appears_first = |
| 149 text.find(kBeginLinkChr) < text.find(kBeginLinkOss); |
| 150 |
| 151 size_t link1 = text.find(kBeginLink); |
| 152 DCHECK(link1 != std::string::npos); |
| 153 size_t link1_end = text.find(kEndLink, link1); |
| 154 DCHECK(link1_end != std::string::npos); |
| 155 size_t link2 = text.find(kBeginLink, link1_end); |
| 156 DCHECK(link2 != std::string::npos); |
| 157 size_t link2_end = text.find(kEndLink, link2); |
| 158 DCHECK(link2_end != std::string::npos); |
| 159 |
| 160 localized_strings->SetString("license_content_0", text.substr(0, link1)); |
| 161 localized_strings->SetString("license_content_1", |
| 162 StringSubRange(text, link1_end + strlen(kEndLinkOss), link2)); |
| 163 localized_strings->SetString("license_content_2", |
| 164 text.substr(link2_end + strlen(kEndLinkOss))); |
| 165 |
| 166 // The Chromium link within the main text of the dialog. |
| 167 localized_strings->SetString(chromium_url_appears_first ? |
| 168 "license_link_content_0" : "license_link_content_1", |
| 169 StringSubRange(text, |
| 170 text.find(kBeginLinkChr) + strlen(kBeginLinkChr), |
| 171 text.find(kEndLinkChr))); |
| 172 GURL url = google_util::AppendGoogleLocaleParam( |
| 173 GURL(chrome::kChromiumProjectURL)); |
| 174 localized_strings->SetString(chromium_url_appears_first ? |
| 175 "license_link_0" : "license_link_1", url.spec()); |
| 176 |
| 177 // The Open Source link within the main text of the dialog. |
| 178 localized_strings->SetString(chromium_url_appears_first ? |
| 179 "license_link_content_1" : "license_link_content_0", |
| 180 StringSubRange(text, |
| 181 text.find(kBeginLinkOss) + strlen(kBeginLinkOss), |
| 182 text.find(kEndLinkOss))); |
| 183 localized_strings->SetString(chromium_url_appears_first ? |
| 184 "license_link_1" : "license_link_0", chrome::kChromeUICreditsURL); |
| 185 |
| 186 std::string cros_text = |
| 187 l10n_util::GetStringUTF8(IDS_ABOUT_CROS_VERSION_LICENSE); |
| 188 |
| 189 size_t cros_link = cros_text.find(kBeginLinkCrosOss); |
| 190 DCHECK(cros_link != std::string::npos); |
| 191 size_t cros_link_end = cros_text.find(kEndLinkCrosOss, cros_link); |
| 192 DCHECK(cros_link_end != std::string::npos); |
| 193 |
| 194 localized_strings->SetString("cros_license_content_0", |
| 195 cros_text.substr(0, cros_link)); |
| 196 localized_strings->SetString("cros_license_content_1", |
| 197 cros_text.substr(cros_link_end + strlen(kEndLinkCrosOss))); |
| 198 localized_strings->SetString("cros_license_link_content_0", |
| 199 StringSubRange(cros_text, cros_link + strlen(kBeginLinkCrosOss), |
| 200 cros_link_end)); |
| 201 localized_strings->SetString("cros_license_link_0", |
| 202 chrome::kChromeUIOSCreditsURL); |
| 203 |
| 204 // webkit |
| 205 |
| 206 localized_strings->SetString("webkit_version", |
| 207 webkit_glue::GetWebKitVersion()); |
| 208 |
| 209 // javascript |
| 210 |
| 211 localized_strings->SetString("js_engine", "V8"); |
| 212 localized_strings->SetString("js_engine_version", v8::V8::GetVersion()); |
| 213 |
| 214 // user agent |
| 215 |
| 216 localized_strings->SetString("user_agent_info", |
| 217 content::GetUserAgent(GURL())); |
| 218 |
| 219 // command line |
| 220 |
| 221 #if defined(OS_WIN) |
| 222 localized_strings->SetString("command_line_info", |
| 223 WideToUTF16(CommandLine::ForCurrentProcess()->GetCommandLineString())); |
| 224 #elif defined(OS_POSIX) |
| 225 // TODO(viettrungluu): something horrible might happen if there are non-UTF-8 |
| 226 // arguments (since |SetString()| requires Unicode). |
| 227 std::string command_line = ""; |
| 228 typedef std::vector<std::string> ArgvList; |
| 229 const ArgvList& argv = CommandLine::ForCurrentProcess()->argv(); |
| 230 for (ArgvList::const_iterator iter = argv.begin(); iter != argv.end(); iter++) |
| 231 command_line += " " + *iter; |
| 232 localized_strings->SetString("command_line_info", command_line); |
| 233 #endif |
| 234 } |
| 235 |
| 236 void AboutPageHandler::RegisterMessages() { |
| 237 web_ui_->RegisterMessageCallback("PageReady", |
| 238 base::Bind(&AboutPageHandler::PageReady, base::Unretained(this))); |
| 239 web_ui_->RegisterMessageCallback("SetReleaseTrack", |
| 240 base::Bind(&AboutPageHandler::SetReleaseTrack, base::Unretained(this))); |
| 241 |
| 242 web_ui_->RegisterMessageCallback("CheckNow", |
| 243 base::Bind(&AboutPageHandler::CheckNow, base::Unretained(this))); |
| 244 web_ui_->RegisterMessageCallback("RestartNow", |
| 245 base::Bind(&AboutPageHandler::RestartNow, base::Unretained(this))); |
| 246 } |
| 247 |
| 248 void AboutPageHandler::PageReady(const ListValue* args) { |
| 249 // Version information is loaded from a callback |
| 250 loader_.GetVersion(&consumer_, |
| 251 base::Bind(&AboutPageHandler::OnOSVersion, |
| 252 base::Unretained(this)), |
| 253 VersionLoader::VERSION_FULL); |
| 254 loader_.GetFirmware(&consumer_, |
| 255 base::Bind(&AboutPageHandler::OnOSFirmware, |
| 256 base::Unretained(this))); |
| 257 |
| 258 UpdateEngineClient* update_engine_client = |
| 259 DBusThreadManager::Get()->GetUpdateEngineClient(); |
| 260 |
| 261 update_observer_.reset(new UpdateObserver(this)); |
| 262 update_engine_client->AddObserver(update_observer_.get()); |
| 263 |
| 264 // Update the WebUI page with the current status. See comments below. |
| 265 UpdateStatus(update_engine_client->GetLastStatus()); |
| 266 |
| 267 // Initiate update check. UpdateStatus() below will be called when we |
| 268 // get update status via update_observer_. If the update has been |
| 269 // already complete, update_observer_ won't receive a notification. |
| 270 // This is why we manually update the WebUI page above. |
| 271 CheckNow(NULL); |
| 272 |
| 273 // Request the channel information. Use the observer to track the about |
| 274 // page handler and ensure it does not get deleted before the callback. |
| 275 update_engine_client->GetReleaseTrack( |
| 276 base::Bind(UpdateSelectedChannel, update_observer_.get())); |
| 277 } |
| 278 |
| 279 void AboutPageHandler::SetReleaseTrack(const ListValue* args) { |
| 280 if (!UserManager::Get()->current_user_is_owner()) { |
| 281 LOG(WARNING) << "Non-owner tried to change release track."; |
| 282 return; |
| 283 } |
| 284 const std::string channel = UTF16ToUTF8(ExtractStringValue(args)); |
| 285 DBusThreadManager::Get()->GetUpdateEngineClient()->SetReleaseTrack(channel); |
| 286 } |
| 287 |
| 288 void AboutPageHandler::CheckNow(const ListValue* args) { |
| 289 // Make sure that libcros is loaded and OOBE is complete. |
| 290 if (!WizardController::default_controller() || |
| 291 WizardController::IsDeviceRegistered()) { |
| 292 DBusThreadManager::Get()->GetUpdateEngineClient()-> |
| 293 RequestUpdateCheck(UpdateEngineClient::EmptyUpdateCheckCallback()); |
| 294 } |
| 295 } |
| 296 |
| 297 void AboutPageHandler::RestartNow(const ListValue* args) { |
| 298 DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart(); |
| 299 } |
| 300 |
| 301 void AboutPageHandler::UpdateStatus( |
| 302 const UpdateEngineClient::Status& status) { |
| 303 string16 message; |
| 304 std::string image = "up-to-date"; |
| 305 bool enabled = false; |
| 306 |
| 307 switch (status.status) { |
| 308 case UpdateEngineClient::UPDATE_STATUS_IDLE: |
| 309 if (!sticky_) { |
| 310 message = l10n_util::GetStringFUTF16(IDS_UPGRADE_ALREADY_UP_TO_DATE, |
| 311 l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME)); |
| 312 enabled = true; |
| 313 } |
| 314 break; |
| 315 case UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE: |
| 316 message = l10n_util::GetStringUTF16(IDS_UPGRADE_CHECK_STARTED); |
| 317 sticky_ = false; |
| 318 break; |
| 319 case UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE: |
| 320 message = l10n_util::GetStringUTF16(IDS_UPDATE_AVAILABLE); |
| 321 started_ = true; |
| 322 break; |
| 323 case UpdateEngineClient::UPDATE_STATUS_DOWNLOADING: |
| 324 { |
| 325 int progress = static_cast<int>(status.download_progress * 100.0); |
| 326 if (progress != progress_) { |
| 327 progress_ = progress; |
| 328 message = l10n_util::GetStringFUTF16Int(IDS_UPDATE_DOWNLOADING, |
| 329 progress_); |
| 330 } |
| 331 started_ = true; |
| 332 } |
| 333 break; |
| 334 case UpdateEngineClient::UPDATE_STATUS_VERIFYING: |
| 335 message = l10n_util::GetStringUTF16(IDS_UPDATE_VERIFYING); |
| 336 started_ = true; |
| 337 break; |
| 338 case UpdateEngineClient::UPDATE_STATUS_FINALIZING: |
| 339 message = l10n_util::GetStringUTF16(IDS_UPDATE_FINALIZING); |
| 340 started_ = true; |
| 341 break; |
| 342 case UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT: |
| 343 message = l10n_util::GetStringUTF16(IDS_UPDATE_COMPLETED); |
| 344 image = "available"; |
| 345 sticky_ = true; |
| 346 break; |
| 347 default: |
| 348 // case UpdateEngineClient::UPDATE_STATUS_ERROR: |
| 349 // case UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT: |
| 350 |
| 351 // The error is only displayed if we were able to determine an |
| 352 // update was available. |
| 353 if (started_) { |
| 354 message = l10n_util::GetStringUTF16(IDS_UPDATE_ERROR); |
| 355 image = "fail"; |
| 356 enabled = true; |
| 357 sticky_ = true; |
| 358 started_ = false; |
| 359 } |
| 360 break; |
| 361 } |
| 362 if (message.size()) { |
| 363 scoped_ptr<Value> update_message(Value::CreateStringValue(message)); |
| 364 // "Checking for update..." needs to be shown for a while, so users |
| 365 // can read it, hence insert delay for this. |
| 366 scoped_ptr<Value> insert_delay(Value::CreateBooleanValue( |
| 367 status.status == |
| 368 UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE)); |
| 369 web_ui_->CallJavascriptFunction("AboutPage.updateStatusCallback", |
| 370 *update_message, *insert_delay); |
| 371 |
| 372 scoped_ptr<Value> enabled_value(Value::CreateBooleanValue(enabled)); |
| 373 web_ui_->CallJavascriptFunction("AboutPage.updateEnableCallback", |
| 374 *enabled_value); |
| 375 |
| 376 scoped_ptr<Value> image_string(Value::CreateStringValue(image)); |
| 377 web_ui_->CallJavascriptFunction("AboutPage.setUpdateImage", |
| 378 *image_string); |
| 379 } |
| 380 // We'll change the "Check For Update" button to "Restart" button. |
| 381 if (status.status == UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) { |
| 382 web_ui_->CallJavascriptFunction("AboutPage.changeToRestartButton"); |
| 383 } |
| 384 } |
| 385 |
| 386 void AboutPageHandler::OnOSVersion(VersionLoader::Handle handle, |
| 387 std::string version) { |
| 388 if (version.size()) { |
| 389 scoped_ptr<Value> version_string(Value::CreateStringValue(version)); |
| 390 web_ui_->CallJavascriptFunction("AboutPage.updateOSVersionCallback", |
| 391 *version_string); |
| 392 } |
| 393 } |
| 394 |
| 395 void AboutPageHandler::OnOSFirmware(VersionLoader::Handle handle, |
| 396 std::string firmware) { |
| 397 if (firmware.size()) { |
| 398 scoped_ptr<Value> firmware_string(Value::CreateStringValue(firmware)); |
| 399 web_ui_->CallJavascriptFunction("AboutPage.updateOSFirmwareCallback", |
| 400 *firmware_string); |
| 401 } |
| 402 } |
| 403 |
| 404 // Callback from UpdateEngine with channel information. |
| 405 // static |
| 406 void AboutPageHandler::UpdateSelectedChannel(UpdateObserver* observer, |
| 407 const std::string& channel) { |
| 408 if (DBusThreadManager::Get()->GetUpdateEngineClient() |
| 409 ->HasObserver(observer)) { |
| 410 // If UpdateEngineClient still has the observer, then the page handler |
| 411 // is valid. |
| 412 AboutPageHandler* handler = observer->page_handler(); |
| 413 scoped_ptr<Value> channel_string(Value::CreateStringValue(channel)); |
| 414 handler->web_ui_->CallJavascriptFunction( |
| 415 "AboutPage.updateSelectedOptionCallback", *channel_string); |
| 416 } |
| 417 } |
| 418 |
| 419 } // namespace chromeos |
OLD | NEW |