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/users/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/ui/webui/help/help_utils_chromeos.h" 17 #include "chromeos/dbus/dbus_thread_manager.h" 18 #include "chromeos/dbus/power_manager_client.h" 19 #include "chromeos/network/network_handler.h" 20 #include "chromeos/network/network_state.h" 21 #include "chromeos/network/network_state_handler.h" 22 #include "chromeos/settings/cros_settings_names.h" 23 #include "grit/chromium_strings.h" 24 #include "grit/generated_resources.h" 25 #include "third_party/cros_system_api/dbus/service_constants.h" 26 #include "ui/base/l10n/l10n_util.h" 27 28 using chromeos::CrosSettings; 29 using chromeos::DBusThreadManager; 30 using chromeos::UpdateEngineClient; 31 using chromeos::UserManager; 32 using chromeos::WizardController; 33 34 namespace { 35 36 // Network status in the context of device update. 37 enum NetworkStatus { 38 // It's allowed in device policy to use current network for update. 39 NETWORK_STATUS_ALLOWED = 0, 40 // It's disallowed in device policy to use current network for update. 41 NETWORK_STATUS_DISALLOWED, 42 // Device is in offline state. 43 NETWORK_STATUS_OFFLINE 44 }; 45 46 const bool kDefaultAutoUpdateDisabled = false; 47 48 NetworkStatus GetNetworkStatus(const chromeos::NetworkState* network) { 49 if (!network || !network->IsConnectedState()) // Offline state. 50 return NETWORK_STATUS_OFFLINE; 51 52 // The connection type checking strategy must be the same as the one 53 // used in update engine. 54 if (network->type() == shill::kTypeBluetooth) 55 return NETWORK_STATUS_DISALLOWED; 56 if (network->type() == shill::kTypeCellular && 57 !help_utils_chromeos::IsUpdateOverCellularAllowed()) { 58 return NETWORK_STATUS_DISALLOWED; 59 } 60 return NETWORK_STATUS_ALLOWED; 61 } 62 63 // Returns true if auto-update is disabled by the system administrator. 64 bool IsAutoUpdateDisabled() { 65 bool update_disabled = kDefaultAutoUpdateDisabled; 66 chromeos::CrosSettings* settings = chromeos::CrosSettings::Get(); 67 if (!settings) 68 return update_disabled; 69 const base::Value* update_disabled_value = 70 settings->GetPref(chromeos::kUpdateDisabled); 71 if (update_disabled_value) 72 CHECK(update_disabled_value->GetAsBoolean(&update_disabled)); 73 return update_disabled; 74 } 75 76 } // namespace 77 78 VersionUpdater* VersionUpdater::Create() { 79 return new VersionUpdaterCros; 80 } 81 82 void VersionUpdaterCros::CheckForUpdate(const StatusCallback& callback) { 83 callback_ = callback; 84 85 if (IsAutoUpdateDisabled()) { 86 callback_.Run(FAILED, 0, 87 l10n_util::GetStringUTF16(IDS_UPGRADE_DISABLED_BY_POLICY)); 88 return; 89 } 90 91 chromeos::NetworkStateHandler* network_state_handler = 92 chromeos::NetworkHandler::Get()->network_state_handler(); 93 const chromeos::NetworkState* network = 94 network_state_handler->DefaultNetwork(); 95 96 // Don't proceed to update if we're currently offline or connected 97 // to a network for which updates are disallowed. 98 NetworkStatus status = GetNetworkStatus(network); 99 if (status == NETWORK_STATUS_OFFLINE) { 100 callback_.Run(FAILED_OFFLINE, 0, 101 l10n_util::GetStringUTF16(IDS_UPGRADE_OFFLINE)); 102 return; 103 } else if (status == NETWORK_STATUS_DISALLOWED) { 104 base::string16 message = 105 l10n_util::GetStringFUTF16( 106 IDS_UPGRADE_DISALLOWED, 107 help_utils_chromeos::GetConnectionTypeAsUTF16(network->type())); 108 callback_.Run(FAILED_CONNECTION_TYPE_DISALLOWED, 0, message); 109 return; 110 } 111 112 UpdateEngineClient* update_engine_client = 113 DBusThreadManager::Get()->GetUpdateEngineClient(); 114 update_engine_client->AddObserver(this); 115 116 // Make sure that libcros is loaded and OOBE is complete. 117 if (!WizardController::default_controller() || 118 chromeos::StartupUtils::IsDeviceRegistered()) { 119 update_engine_client->RequestUpdateCheck( 120 base::Bind(&VersionUpdaterCros::OnUpdateCheck, 121 weak_ptr_factory_.GetWeakPtr())); 122 } 123 } 124 125 void VersionUpdaterCros::RelaunchBrowser() const { 126 DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart(); 127 } 128 129 void VersionUpdaterCros::SetChannel(const std::string& channel, 130 bool is_powerwash_allowed) { 131 if (UserManager::Get()->IsCurrentUserOwner()) { 132 // For local owner set the field in the policy blob. 133 CrosSettings::Get()->SetString(chromeos::kReleaseChannel, channel); 134 } 135 DBusThreadManager::Get()->GetUpdateEngineClient()-> 136 SetChannel(channel, is_powerwash_allowed); 137 } 138 139 void VersionUpdaterCros::GetChannel(bool get_current_channel, 140 const ChannelCallback& cb) { 141 UpdateEngineClient* update_engine_client = 142 DBusThreadManager::Get()->GetUpdateEngineClient(); 143 144 // Request the channel information. 145 update_engine_client->GetChannel(get_current_channel, cb); 146 } 147 148 VersionUpdaterCros::VersionUpdaterCros() 149 : last_operation_(UpdateEngineClient::UPDATE_STATUS_IDLE), 150 weak_ptr_factory_(this) { 151 } 152 153 VersionUpdaterCros::~VersionUpdaterCros() { 154 UpdateEngineClient* update_engine_client = 155 DBusThreadManager::Get()->GetUpdateEngineClient(); 156 update_engine_client->RemoveObserver(this); 157 } 158 159 void VersionUpdaterCros::UpdateStatusChanged( 160 const UpdateEngineClient::Status& status) { 161 Status my_status = UPDATED; 162 int progress = 0; 163 base::string16 message; 164 165 // If the updater is currently idle, just show the last operation (unless it 166 // was previously checking for an update -- in that case, the system is 167 // up-to-date now). See http://crbug.com/120063 for details. 168 UpdateEngineClient::UpdateStatusOperation operation_to_show = status.status; 169 if (status.status == UpdateEngineClient::UPDATE_STATUS_IDLE && 170 last_operation_ != 171 UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE) { 172 operation_to_show = last_operation_; 173 } 174 175 switch (operation_to_show) { 176 case UpdateEngineClient::UPDATE_STATUS_ERROR: 177 case UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT: 178 case UpdateEngineClient::UPDATE_STATUS_ATTEMPTING_ROLLBACK: 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 211 void 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, base::string16()); 217 } 218