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