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.
5 #include "chrome/browser/ui/webui/help/version_updater_chromeos.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/ownership/owner_settings_service_chromeos.h"
15 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h"
16 #include "chrome/browser/chromeos/settings/cros_settings.h"
17 #include "chrome/browser/ui/webui/help/help_utils_chromeos.h"
18 #include "chrome/grit/generated_resources.h"
19 #include "chromeos/dbus/dbus_thread_manager.h"
20 #include "chromeos/dbus/power_manager_client.h"
21 #include "chromeos/network/network_handler.h"
22 #include "chromeos/network/network_state.h"
23 #include "chromeos/network/network_state_handler.h"
24 #include "chromeos/settings/cros_settings_names.h"
25 #include "third_party/cros_system_api/dbus/service_constants.h"
26 #include "ui/base/l10n/l10n_util.h"
28 using chromeos::CrosSettings
;
29 using chromeos::DBusThreadManager
;
30 using chromeos::OwnerSettingsServiceChromeOS
;
31 using chromeos::OwnerSettingsServiceChromeOSFactory
;
32 using chromeos::UpdateEngineClient
;
33 using chromeos::WizardController
;
37 // Network status in the context of device update.
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
47 const bool kDefaultAutoUpdateDisabled
= false;
49 NetworkStatus
GetNetworkStatus(const chromeos::NetworkState
* network
) {
50 if (!network
|| !network
->IsConnectedState()) // Offline state.
51 return NETWORK_STATUS_OFFLINE
;
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
;
61 return NETWORK_STATUS_ALLOWED
;
64 // Returns true if auto-update is disabled by the system administrator.
65 bool IsAutoUpdateDisabled() {
66 bool update_disabled
= kDefaultAutoUpdateDisabled
;
67 chromeos::CrosSettings
* settings
= chromeos::CrosSettings::Get();
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
;
77 // Returns whether an update is allowed. If not, it calls the callback with
78 // the appropriate status.
79 bool EnsureCanUpdate(const VersionUpdater::StatusCallback
& callback
) {
80 if (IsAutoUpdateDisabled()) {
81 callback
.Run(VersionUpdater::FAILED
, 0,
82 l10n_util::GetStringUTF16(IDS_UPGRADE_DISABLED_BY_POLICY
));
86 chromeos::NetworkStateHandler
* network_state_handler
=
87 chromeos::NetworkHandler::Get()->network_state_handler();
88 const chromeos::NetworkState
* network
=
89 network_state_handler
->DefaultNetwork();
91 // Don't allow an update if we're currently offline or connected
92 // to a network for which updates are disallowed.
93 NetworkStatus status
= GetNetworkStatus(network
);
94 if (status
== NETWORK_STATUS_OFFLINE
) {
95 callback
.Run(VersionUpdater::FAILED_OFFLINE
, 0,
96 l10n_util::GetStringUTF16(IDS_UPGRADE_OFFLINE
));
98 } else if (status
== NETWORK_STATUS_DISALLOWED
) {
99 base::string16 message
=
100 l10n_util::GetStringFUTF16(
101 IDS_UPGRADE_DISALLOWED
,
102 help_utils_chromeos::GetConnectionTypeAsUTF16(network
->type()));
103 callback
.Run(VersionUpdater::FAILED_CONNECTION_TYPE_DISALLOWED
, 0, message
);
112 VersionUpdater
* VersionUpdater::Create(content::BrowserContext
* context
) {
113 return new VersionUpdaterCros(context
);
116 void VersionUpdaterCros::GetUpdateStatus(const StatusCallback
& callback
) {
117 callback_
= callback
;
119 if (!EnsureCanUpdate(callback
))
122 UpdateEngineClient
* update_engine_client
=
123 DBusThreadManager::Get()->GetUpdateEngineClient();
124 if (!update_engine_client
->HasObserver(this))
125 update_engine_client
->AddObserver(this);
127 this->UpdateStatusChanged(
128 DBusThreadManager::Get()->GetUpdateEngineClient()->GetLastStatus());
131 void VersionUpdaterCros::CheckForUpdate(const StatusCallback
& callback
) {
132 callback_
= callback
;
134 if (!EnsureCanUpdate(callback
))
137 UpdateEngineClient
* update_engine_client
=
138 DBusThreadManager::Get()->GetUpdateEngineClient();
139 if (!update_engine_client
->HasObserver(this))
140 update_engine_client
->AddObserver(this);
142 if (update_engine_client
->GetLastStatus().status
!=
143 UpdateEngineClient::UPDATE_STATUS_IDLE
) {
144 check_for_update_when_idle_
= true;
147 check_for_update_when_idle_
= false;
149 // Make sure that libcros is loaded and OOBE is complete.
150 if (!WizardController::default_controller() ||
151 chromeos::StartupUtils::IsDeviceRegistered()) {
152 update_engine_client
->RequestUpdateCheck(base::Bind(
153 &VersionUpdaterCros::OnUpdateCheck
, weak_ptr_factory_
.GetWeakPtr()));
157 void VersionUpdaterCros::RelaunchBrowser() const {
158 DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
161 void VersionUpdaterCros::SetChannel(const std::string
& channel
,
162 bool is_powerwash_allowed
) {
163 OwnerSettingsServiceChromeOS
* service
=
165 ? OwnerSettingsServiceChromeOSFactory::GetInstance()
166 ->GetForBrowserContext(context_
)
168 // For local owner set the field in the policy blob.
170 service
->SetString(chromeos::kReleaseChannel
, channel
);
171 DBusThreadManager::Get()->GetUpdateEngineClient()->
172 SetChannel(channel
, is_powerwash_allowed
);
175 void VersionUpdaterCros::GetChannel(bool get_current_channel
,
176 const ChannelCallback
& cb
) {
177 UpdateEngineClient
* update_engine_client
=
178 DBusThreadManager::Get()->GetUpdateEngineClient();
180 // Request the channel information.
181 update_engine_client
->GetChannel(get_current_channel
, cb
);
184 VersionUpdaterCros::VersionUpdaterCros(content::BrowserContext
* context
)
186 last_operation_(UpdateEngineClient::UPDATE_STATUS_IDLE
),
187 check_for_update_when_idle_(false),
188 weak_ptr_factory_(this) {
191 VersionUpdaterCros::~VersionUpdaterCros() {
192 UpdateEngineClient
* update_engine_client
=
193 DBusThreadManager::Get()->GetUpdateEngineClient();
194 update_engine_client
->RemoveObserver(this);
197 void VersionUpdaterCros::UpdateStatusChanged(
198 const UpdateEngineClient::Status
& status
) {
199 Status my_status
= UPDATED
;
201 base::string16 message
;
203 // If the updater is currently idle, just show the last operation (unless it
204 // was previously checking for an update -- in that case, the system is
205 // up-to-date now). See http://crbug.com/120063 for details.
206 UpdateEngineClient::UpdateStatusOperation operation_to_show
= status
.status
;
207 if (status
.status
== UpdateEngineClient::UPDATE_STATUS_IDLE
&&
209 UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE
) {
210 operation_to_show
= last_operation_
;
213 switch (operation_to_show
) {
214 case UpdateEngineClient::UPDATE_STATUS_ERROR
:
215 case UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT
:
216 case UpdateEngineClient::UPDATE_STATUS_ATTEMPTING_ROLLBACK
:
217 // This path previously used the FAILED status and IDS_UPGRADE_ERROR, but
218 // the update engine reports errors for some conditions that shouldn't
219 // actually be displayed as errors to users: http://crbug.com/146919.
220 // Just use the UPDATED status instead.
222 case UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE
:
223 my_status
= CHECKING
;
225 case UpdateEngineClient::UPDATE_STATUS_DOWNLOADING
:
226 progress
= static_cast<int>(round(status
.download_progress
* 100));
228 case UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE
:
229 my_status
= UPDATING
;
231 case UpdateEngineClient::UPDATE_STATUS_VERIFYING
:
232 case UpdateEngineClient::UPDATE_STATUS_FINALIZING
:
233 // Once the download is finished, keep the progress at 100; it shouldn't
234 // go down while the status is the same.
236 my_status
= UPDATING
;
238 case UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT
:
239 my_status
= NEARLY_UPDATED
;
245 callback_
.Run(my_status
, progress
, message
);
246 last_operation_
= status
.status
;
248 if (check_for_update_when_idle_
&&
249 status
.status
== UpdateEngineClient::UPDATE_STATUS_IDLE
) {
250 CheckForUpdate(callback_
);
254 void VersionUpdaterCros::OnUpdateCheck(
255 UpdateEngineClient::UpdateCheckResult result
) {
256 // If version updating is not implemented, this binary is the most up-to-date
257 // possible with respect to automatic updating.
258 if (result
== UpdateEngineClient::UPDATE_RESULT_NOTIMPLEMENTED
)
259 callback_
.Run(UPDATED
, 0, base::string16());