version_updater_chromeos.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
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/help/version_updater_chromeos.h" 6 7#include <cmath> 8 9#include "base/bind.h" 10#include "base/bind_helpers.h" 11#include "chrome/browser/browser_process.h" 12#include "chrome/browser/chromeos/login/startup_utils.h" 13#include "chrome/browser/chromeos/login/wizard_controller.h" 14#include "chrome/browser/chromeos/settings/cros_settings.h" 15#include "chrome/browser/ui/webui/help/help_utils_chromeos.h" 16#include "chromeos/dbus/dbus_thread_manager.h" 17#include "chromeos/dbus/power_manager_client.h" 18#include "chromeos/network/network_handler.h" 19#include "chromeos/network/network_state.h" 20#include "chromeos/network/network_state_handler.h" 21#include "chromeos/settings/cros_settings_names.h" 22#include "components/user_manager/user_manager.h" 23#include "grit/generated_resources.h" 24#include "third_party/cros_system_api/dbus/service_constants.h" 25#include "ui/base/l10n/l10n_util.h" 26 27using chromeos::CrosSettings; 28using chromeos::DBusThreadManager; 29using chromeos::UpdateEngineClient; 30using user_manager::UserManager; 31using chromeos::WizardController; 32 33namespace { 34 35// Network status in the context of device update. 36enum NetworkStatus { 37 // It's allowed in device policy to use current network for update. 38 NETWORK_STATUS_ALLOWED = 0, 39 // It's disallowed in device policy to use current network for update. 40 NETWORK_STATUS_DISALLOWED, 41 // Device is in offline state. 42 NETWORK_STATUS_OFFLINE 43}; 44 45const bool kDefaultAutoUpdateDisabled = false; 46 47NetworkStatus GetNetworkStatus(const chromeos::NetworkState* network) { 48 if (!network || !network->IsConnectedState()) // Offline state. 49 return NETWORK_STATUS_OFFLINE; 50 51 // The connection type checking strategy must be the same as the one 52 // used in update engine. 53 if (network->type() == shill::kTypeBluetooth) 54 return NETWORK_STATUS_DISALLOWED; 55 if (network->type() == shill::kTypeCellular && 56 !help_utils_chromeos::IsUpdateOverCellularAllowed()) { 57 return NETWORK_STATUS_DISALLOWED; 58 } 59 return NETWORK_STATUS_ALLOWED; 60} 61 62// Returns true if auto-update is disabled by the system administrator. 63bool IsAutoUpdateDisabled() { 64 bool update_disabled = kDefaultAutoUpdateDisabled; 65 chromeos::CrosSettings* settings = chromeos::CrosSettings::Get(); 66 if (!settings) 67 return update_disabled; 68 const base::Value* update_disabled_value = 69 settings->GetPref(chromeos::kUpdateDisabled); 70 if (update_disabled_value) 71 CHECK(update_disabled_value->GetAsBoolean(&update_disabled)); 72 return update_disabled; 73} 74 75} // namespace 76 77VersionUpdater* VersionUpdater::Create() { 78 return new VersionUpdaterCros; 79} 80 81void VersionUpdaterCros::CheckForUpdate(const StatusCallback& callback) { 82 callback_ = callback; 83 84 if (IsAutoUpdateDisabled()) { 85 callback_.Run(FAILED, 0, 86 l10n_util::GetStringUTF16(IDS_UPGRADE_DISABLED_BY_POLICY)); 87 return; 88 } 89 90 chromeos::NetworkStateHandler* network_state_handler = 91 chromeos::NetworkHandler::Get()->network_state_handler(); 92 const chromeos::NetworkState* network = 93 network_state_handler->DefaultNetwork(); 94 95 // Don't proceed to update if we're currently offline or connected 96 // to a network for which updates are disallowed. 97 NetworkStatus status = GetNetworkStatus(network); 98 if (status == NETWORK_STATUS_OFFLINE) { 99 callback_.Run(FAILED_OFFLINE, 0, 100 l10n_util::GetStringUTF16(IDS_UPGRADE_OFFLINE)); 101 return; 102 } else if (status == NETWORK_STATUS_DISALLOWED) { 103 base::string16 message = 104 l10n_util::GetStringFUTF16( 105 IDS_UPGRADE_DISALLOWED, 106 help_utils_chromeos::GetConnectionTypeAsUTF16(network->type())); 107 callback_.Run(FAILED_CONNECTION_TYPE_DISALLOWED, 0, message); 108 return; 109 } 110 111 UpdateEngineClient* update_engine_client = 112 DBusThreadManager::Get()->GetUpdateEngineClient(); 113 update_engine_client->AddObserver(this); 114 115 // Make sure that libcros is loaded and OOBE is complete. 116 if (!WizardController::default_controller() || 117 chromeos::StartupUtils::IsDeviceRegistered()) { 118 update_engine_client->RequestUpdateCheck( 119 base::Bind(&VersionUpdaterCros::OnUpdateCheck, 120 weak_ptr_factory_.GetWeakPtr())); 121 } 122} 123 124void VersionUpdaterCros::RelaunchBrowser() const { 125 DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart(); 126} 127 128void VersionUpdaterCros::SetChannel(const std::string& channel, 129 bool is_powerwash_allowed) { 130 if (user_manager::UserManager::Get()->IsCurrentUserOwner()) { 131 // For local owner set the field in the policy blob. 132 CrosSettings::Get()->SetString(chromeos::kReleaseChannel, channel); 133 } 134 DBusThreadManager::Get()->GetUpdateEngineClient()-> 135 SetChannel(channel, is_powerwash_allowed); 136} 137 138void VersionUpdaterCros::GetChannel(bool get_current_channel, 139 const ChannelCallback& cb) { 140 UpdateEngineClient* update_engine_client = 141 DBusThreadManager::Get()->GetUpdateEngineClient(); 142 143 // Request the channel information. 144 update_engine_client->GetChannel(get_current_channel, cb); 145} 146 147VersionUpdaterCros::VersionUpdaterCros() 148 : last_operation_(UpdateEngineClient::UPDATE_STATUS_IDLE), 149 weak_ptr_factory_(this) { 150} 151 152VersionUpdaterCros::~VersionUpdaterCros() { 153 UpdateEngineClient* update_engine_client = 154 DBusThreadManager::Get()->GetUpdateEngineClient(); 155 update_engine_client->RemoveObserver(this); 156} 157 158void VersionUpdaterCros::UpdateStatusChanged( 159 const UpdateEngineClient::Status& status) { 160 Status my_status = UPDATED; 161 int progress = 0; 162 base::string16 message; 163 164 // If the updater is currently idle, just show the last operation (unless it 165 // was previously checking for an update -- in that case, the system is 166 // up-to-date now). See http://crbug.com/120063 for details. 167 UpdateEngineClient::UpdateStatusOperation operation_to_show = status.status; 168 if (status.status == UpdateEngineClient::UPDATE_STATUS_IDLE && 169 last_operation_ != 170 UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE) { 171 operation_to_show = last_operation_; 172 } 173 174 switch (operation_to_show) { 175 case UpdateEngineClient::UPDATE_STATUS_ERROR: 176 case UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT: 177 case UpdateEngineClient::UPDATE_STATUS_ATTEMPTING_ROLLBACK: 178 // This path previously used the FAILED status and IDS_UPGRADE_ERROR, but 179 // the update engine reports errors for some conditions that shouldn't 180 // actually be displayed as errors to users: http://crbug.com/146919. 181 // Just use the UPDATED status instead. 182 break; 183 case UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE: 184 my_status = CHECKING; 185 break; 186 case UpdateEngineClient::UPDATE_STATUS_DOWNLOADING: 187 progress = static_cast<int>(round(status.download_progress * 100)); 188 // Fall through. 189 case UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE: 190 my_status = UPDATING; 191 break; 192 case UpdateEngineClient::UPDATE_STATUS_VERIFYING: 193 case UpdateEngineClient::UPDATE_STATUS_FINALIZING: 194 // Once the download is finished, keep the progress at 100; it shouldn't 195 // go down while the status is the same. 196 progress = 100; 197 my_status = UPDATING; 198 break; 199 case UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT: 200 my_status = NEARLY_UPDATED; 201 break; 202 default: 203 break; 204 } 205 206 callback_.Run(my_status, progress, message); 207 last_operation_ = status.status; 208} 209 210void VersionUpdaterCros::OnUpdateCheck( 211 UpdateEngineClient::UpdateCheckResult result) { 212 // If version updating is not implemented, this binary is the most up-to-date 213 // possible with respect to automatic updating. 214 if (result == UpdateEngineClient::UPDATE_RESULT_NOTIMPLEMENTED) 215 callback_.Run(UPDATED, 0, base::string16()); 216} 217