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