blob: 449c1011a0589fc9d9b7a45624f629c0b3742b73 [file] [log] [blame]
Jay Srinivasane73acab2012-07-10 14:34:03 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "update_engine/dbus_service.h"
Darin Petkova07586b2010-10-20 13:41:15 -07006
Alex Deymof4867c42013-06-28 14:41:39 -07007#include <set>
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -07008#include <string>
Darin Petkova07586b2010-10-20 13:41:15 -07009
10#include <base/logging.h>
Jay Srinivasan1c0fe792013-03-28 16:45:25 -070011#include <policy/device_policy.h>
Darin Petkova07586b2010-10-20 13:41:15 -070012
Alex Deymof4867c42013-06-28 14:41:39 -070013#include "update_engine/connection_manager.h"
David Zeuthen75a4c3e2013-09-06 11:36:59 -070014#include "update_engine/dbus_constants.h"
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070015#include "update_engine/marshal.glibmarshal.h"
Darin Petkov49d91322010-10-25 16:34:58 -070016#include "update_engine/omaha_request_params.h"
Alex Deymo5fdf7762013-07-17 20:01:40 -070017#include "update_engine/p2p_manager.h"
Alex Deymof4867c42013-06-28 14:41:39 -070018#include "update_engine/update_attempter.h"
19#include "update_engine/prefs.h"
Darin Petkova07586b2010-10-20 13:41:15 -070020#include "update_engine/utils.h"
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070021
Alex Deymof4867c42013-06-28 14:41:39 -070022using std::set;
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070023using std::string;
David Zeuthen75a4c3e2013-09-06 11:36:59 -070024using chromeos_update_engine::AttemptUpdateFlags;
25using chromeos_update_engine::kAttemptUpdateFlagNonInteractive;
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070026
Darin Petkov820a77b2011-04-27 16:48:58 -070027static const char kAUTestURLRequest[] = "autest";
Jay Srinivasane73acab2012-07-10 14:34:03 -070028// By default autest bypasses scattering. If we want to test scattering,
29// we should use autest-scheduled. The Url used is same in both cases, but
30// different params are passed to CheckForUpdate method.
31static const char kScheduledAUTestURLRequest[] = "autest-scheduled";
32
Darin Petkov820a77b2011-04-27 16:48:58 -070033static const char kAUTestURL[] =
Darin Petkov5445e162011-11-04 10:10:27 +010034 "https://omaha.sandbox.google.com/service/update2";
Darin Petkov820a77b2011-04-27 16:48:58 -070035
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070036G_DEFINE_TYPE(UpdateEngineService, update_engine_service, G_TYPE_OBJECT)
37
38static void update_engine_service_finalize(GObject* object) {
39 G_OBJECT_CLASS(update_engine_service_parent_class)->finalize(object);
40}
41
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070042static guint status_update_signal = 0;
43
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070044static void update_engine_service_class_init(UpdateEngineServiceClass* klass) {
45 GObjectClass *object_class;
46 object_class = G_OBJECT_CLASS(klass);
47 object_class->finalize = update_engine_service_finalize;
Darin Petkov5a7f5652010-07-22 21:40:09 -070048
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070049 status_update_signal = g_signal_new(
50 "status_update",
51 G_OBJECT_CLASS_TYPE(klass),
52 G_SIGNAL_RUN_LAST,
53 0, // 0 == no class method associated
54 NULL, // Accumulator
55 NULL, // Accumulator data
56 update_engine_VOID__INT64_DOUBLE_STRING_STRING_INT64,
57 G_TYPE_NONE, // Return type
58 5, // param count:
59 G_TYPE_INT64,
60 G_TYPE_DOUBLE,
61 G_TYPE_STRING,
62 G_TYPE_STRING,
63 G_TYPE_INT64);
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070064}
65
66static void update_engine_service_init(UpdateEngineService* object) {
67}
68
69UpdateEngineService* update_engine_service_new(void) {
70 return reinterpret_cast<UpdateEngineService*>(
71 g_object_new(UPDATE_ENGINE_TYPE_SERVICE, NULL));
72}
73
Darin Petkov296889c2010-07-23 16:20:54 -070074gboolean update_engine_service_attempt_update(UpdateEngineService* self,
75 gchar* app_version,
76 gchar* omaha_url,
77 GError **error) {
David Zeuthen75a4c3e2013-09-06 11:36:59 -070078 return update_engine_service_attempt_update_with_flags(self,
79 app_version,
80 omaha_url,
81 0, // No flags set.
82 error);
83}
84
85gboolean update_engine_service_attempt_update_with_flags(
86 UpdateEngineService* self,
87 gchar* app_version,
88 gchar* omaha_url,
89 gint flags_as_int,
90 GError **error) {
Darin Petkova07586b2010-10-20 13:41:15 -070091 string update_app_version;
92 string update_omaha_url;
David Zeuthen75a4c3e2013-09-06 11:36:59 -070093 AttemptUpdateFlags flags = static_cast<AttemptUpdateFlags>(flags_as_int);
Gilad Arnoldb92f0df2013-01-10 16:32:45 -080094 bool interactive = true;
Jay Srinivasane73acab2012-07-10 14:34:03 -070095
Darin Petkova07586b2010-10-20 13:41:15 -070096 // Only non-official (e.g., dev and test) builds can override the current
Darin Petkov820a77b2011-04-27 16:48:58 -070097 // version and update server URL over D-Bus. However, pointing to the
98 // hardcoded test update server URL is always allowed.
Darin Petkova07586b2010-10-20 13:41:15 -070099 if (!chromeos_update_engine::utils::IsOfficialBuild()) {
100 if (app_version) {
101 update_app_version = app_version;
102 }
103 if (omaha_url) {
104 update_omaha_url = omaha_url;
105 }
106 }
Jay Srinivasane73acab2012-07-10 14:34:03 -0700107 if (omaha_url) {
108 if (strcmp(omaha_url, kScheduledAUTestURLRequest) == 0) {
109 update_omaha_url = kAUTestURL;
110 // pretend that it's not user-initiated even though it is,
111 // so as to test scattering logic, etc. which get kicked off
112 // only in scheduled update checks.
Gilad Arnoldb92f0df2013-01-10 16:32:45 -0800113 interactive = false;
Jay Srinivasane73acab2012-07-10 14:34:03 -0700114 } else if (strcmp(omaha_url, kAUTestURLRequest) == 0) {
115 update_omaha_url = kAUTestURL;
116 }
Darin Petkov820a77b2011-04-27 16:48:58 -0700117 }
David Zeuthen75a4c3e2013-09-06 11:36:59 -0700118 if (flags & kAttemptUpdateFlagNonInteractive)
119 interactive = false;
Darin Petkov296889c2010-07-23 16:20:54 -0700120 LOG(INFO) << "Attempt update: app_version=\"" << update_app_version << "\" "
Jay Srinivasane73acab2012-07-10 14:34:03 -0700121 << "omaha_url=\"" << update_omaha_url << "\" "
David Zeuthen75a4c3e2013-09-06 11:36:59 -0700122 << "flags=0x" << std::hex << flags << " "
Gilad Arnoldb92f0df2013-01-10 16:32:45 -0800123 << "interactive=" << (interactive? "yes" : "no");
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700124 self->system_state_->update_attempter()->CheckForUpdate(update_app_version,
125 update_omaha_url,
126 interactive);
Darin Petkov296889c2010-07-23 16:20:54 -0700127 return TRUE;
128}
129
Chris Sosad317e402013-06-12 13:47:09 -0700130gboolean update_engine_service_attempt_rollback(UpdateEngineService* self,
Alex Deymoad923732013-08-29 16:13:49 -0700131 gboolean powerwash,
Chris Sosad317e402013-06-12 13:47:09 -0700132 GError **error) {
133 LOG(INFO) << "Attempting rollback to non-active partitions.";
Chris Sosa76a29ae2013-07-11 17:59:24 -0700134 return self->system_state_->update_attempter()->Rollback(powerwash, NULL);
Chris Sosad317e402013-06-12 13:47:09 -0700135}
136
Jay Srinivasanc1ba09a2012-08-14 14:15:57 -0700137gboolean update_engine_service_reset_status(UpdateEngineService* self,
138 GError **error) {
139 *error = NULL;
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700140 return self->system_state_->update_attempter()->ResetStatus();
Jay Srinivasanc1ba09a2012-08-14 14:15:57 -0700141}
142
143
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700144gboolean update_engine_service_get_status(UpdateEngineService* self,
145 int64_t* last_checked_time,
146 double* progress,
147 gchar** current_operation,
148 gchar** new_version,
149 int64_t* new_size,
150 GError **error) {
151 string current_op;
152 string new_version_str;
Darin Petkov5a7f5652010-07-22 21:40:09 -0700153
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700154 CHECK(self->system_state_->update_attempter()->GetStatus(last_checked_time,
155 progress,
156 &current_op,
157 &new_version_str,
158 new_size));
Darin Petkov5a7f5652010-07-22 21:40:09 -0700159
Satoru Takabayashid6982312010-11-29 12:54:12 +0900160 *current_operation = g_strdup(current_op.c_str());
161 *new_version = g_strdup(new_version_str.c_str());
Chris Masonec6c57a52010-09-23 13:06:14 -0700162 if (!(*current_operation && *new_version)) {
163 *error = NULL;
164 return FALSE;
165 }
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700166 return TRUE;
167}
168
Darin Petkov296889c2010-07-23 16:20:54 -0700169gboolean update_engine_service_reboot_if_needed(UpdateEngineService* self,
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700170 GError **error) {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700171 if (!self->system_state_->update_attempter()->RebootIfNeeded()) {
Darin Petkov296889c2010-07-23 16:20:54 -0700172 *error = NULL;
173 return FALSE;
174 }
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700175 return TRUE;
176}
177
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700178gboolean update_engine_service_set_channel(UpdateEngineService* self,
179 gchar* target_channel,
Alex Deymoad923732013-08-29 16:13:49 -0700180 gboolean is_powerwash_allowed,
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700181 GError **error) {
182 if (!target_channel)
183 return FALSE;
184
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700185 const policy::DevicePolicy* device_policy =
186 self->system_state_->device_policy();
Chris Sosacb7fa882013-07-25 17:02:59 -0700187
188 // The device_policy is loaded in a lazy way before an update check. Load it
189 // now from the libchromeos cache if it wasn't already loaded.
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700190 if (!device_policy) {
Chris Sosacb7fa882013-07-25 17:02:59 -0700191 chromeos_update_engine::UpdateAttempter* update_attempter =
192 self->system_state_->update_attempter();
193 if (update_attempter) {
194 update_attempter->RefreshDevicePolicy();
195 device_policy = self->system_state_->device_policy();
196 }
Darin Petkov8daa3242010-10-25 13:28:47 -0700197 }
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700198
199 bool delegated = false;
Chris Sosacb7fa882013-07-25 17:02:59 -0700200 if (device_policy &&
201 device_policy->GetReleaseChannelDelegated(&delegated) && !delegated) {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700202 LOG(INFO) << "Cannot set target channel explicitly when channel "
203 "policy/settings is not delegated";
204 return FALSE;
205 }
206
207 LOG(INFO) << "Setting destination channel to: " << target_channel;
208 if (!self->system_state_->request_params()->SetTargetChannel(
209 target_channel, is_powerwash_allowed)) {
210 *error = NULL;
211 return FALSE;
212 }
213
214 return TRUE;
215}
216
217gboolean update_engine_service_get_channel(UpdateEngineService* self,
Alex Deymoad923732013-08-29 16:13:49 -0700218 gboolean get_current_channel,
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700219 gchar** channel,
220 GError **error) {
221 chromeos_update_engine::OmahaRequestParams* rp =
222 self->system_state_->request_params();
223
224 string channel_str = get_current_channel ?
225 rp->current_channel() : rp->target_channel();
226
227 *channel = g_strdup(channel_str.c_str());
Darin Petkov8daa3242010-10-25 13:28:47 -0700228 return TRUE;
229}
230
Alex Deymo5fdf7762013-07-17 20:01:40 -0700231gboolean update_engine_service_set_p2p_update_permission(
232 UpdateEngineService* self,
233 gboolean enabled,
234 GError **error) {
235 chromeos_update_engine::PrefsInterface* prefs = self->system_state_->prefs();
236 chromeos_update_engine::P2PManager* p2p_manager =
237 self->system_state_->p2p_manager();
238
239 bool p2p_was_enabled = p2p_manager && p2p_manager->IsP2PEnabled();
240
241 if (!prefs->SetBoolean(chromeos_update_engine::kPrefsP2PEnabled, enabled)) {
242 LOG(ERROR) << "Error setting the update over cellular to "
243 << (enabled ? "true" : "false");
244 *error = NULL;
245 return FALSE;
246 }
247
248 // If P2P is being effectively disabled (IsP2PEnabled() reports the change)
249 // then we need to shutdown the service.
250 if (p2p_was_enabled && !p2p_manager->IsP2PEnabled())
251 p2p_manager->EnsureP2PNotRunning();
252
253 return TRUE;
254}
255
256gboolean update_engine_service_get_p2p_update_permission(
257 UpdateEngineService* self,
258 gboolean* enabled,
259 GError **error) {
260 chromeos_update_engine::PrefsInterface* prefs = self->system_state_->prefs();
261
262 // The default for not present setting is false.
263 if (!prefs->Exists(chromeos_update_engine::kPrefsP2PEnabled)) {
264 *enabled = false;
265 return TRUE;
266 }
267
268 bool p2p_pref = false;
269 if (!prefs->GetBoolean(chromeos_update_engine::kPrefsP2PEnabled, &p2p_pref)) {
270 LOG(ERROR) << "Error getting the P2PEnabled setting.";
271 *error = NULL;
272 return FALSE;
273 }
274
275 *enabled = p2p_pref;
276 return TRUE;
277}
278
Alex Deymof4867c42013-06-28 14:41:39 -0700279gboolean update_engine_service_set_update_over_cellular_permission(
280 UpdateEngineService* self,
Alex Deymoad923732013-08-29 16:13:49 -0700281 gboolean allowed,
Alex Deymof4867c42013-06-28 14:41:39 -0700282 GError **error) {
283 set<string> allowed_types;
284 const policy::DevicePolicy* device_policy =
285 self->system_state_->device_policy();
286
287 // The device_policy is loaded in a lazy way before an update check. Load it
288 // now from the libchromeos cache if it wasn't already loaded.
289 if (!device_policy) {
290 chromeos_update_engine::UpdateAttempter* update_attempter =
291 self->system_state_->update_attempter();
292 if (update_attempter) {
293 update_attempter->RefreshDevicePolicy();
Chris Sosacb7fa882013-07-25 17:02:59 -0700294 device_policy = self->system_state_->device_policy();
Alex Deymof4867c42013-06-28 14:41:39 -0700295 }
296 }
297
298 // Check if this setting is allowed by the device policy.
299 if (device_policy &&
300 device_policy->GetAllowedConnectionTypesForUpdate(&allowed_types)) {
301 LOG(INFO) << "Ignoring the update over cellular setting since there's "
302 "a device policy enforcing this setting.";
303 *error = NULL;
304 return FALSE;
305 }
306
307 // If the policy wasn't loaded yet, then it is still OK to change the local
308 // setting because the policy will be checked again during the update check.
309
310 chromeos_update_engine::PrefsInterface* prefs = self->system_state_->prefs();
311
Alex Deymoefb7c4c2013-07-09 14:34:00 -0700312 if (!prefs->SetBoolean(
Alex Deymof4867c42013-06-28 14:41:39 -0700313 chromeos_update_engine::kPrefsUpdateOverCellularPermission,
Alex Deymoefb7c4c2013-07-09 14:34:00 -0700314 allowed)) {
Alex Deymof4867c42013-06-28 14:41:39 -0700315 LOG(ERROR) << "Error setting the update over cellular to "
Alex Deymoefb7c4c2013-07-09 14:34:00 -0700316 << (allowed ? "true" : "false");
Alex Deymof4867c42013-06-28 14:41:39 -0700317 *error = NULL;
318 return FALSE;
319 }
320
321 return TRUE;
322}
323
324gboolean update_engine_service_get_update_over_cellular_permission(
325 UpdateEngineService* self,
Alex Deymoad923732013-08-29 16:13:49 -0700326 gboolean* allowed,
Alex Deymof4867c42013-06-28 14:41:39 -0700327 GError **/*error*/) {
328 chromeos_update_engine::ConnectionManager* cm =
329 self->system_state_->connection_manager();
330
331 // The device_policy is loaded in a lazy way before an update check and is
332 // used to determine if an update is allowed over cellular. Load the device
333 // policy now from the libchromeos cache if it wasn't already loaded.
334 if (!self->system_state_->device_policy()) {
335 chromeos_update_engine::UpdateAttempter* update_attempter =
336 self->system_state_->update_attempter();
337 if (update_attempter)
338 update_attempter->RefreshDevicePolicy();
339 }
340
341 // Return the current setting based on the same logic used while checking for
342 // updates. A log message could be printed as the result of this test.
343 LOG(INFO) << "Checking if updates over cellular networks are allowed:";
344 *allowed = cm->IsUpdateAllowedOver(chromeos_update_engine::kNetCellular);
345
346 return TRUE;
347}
348
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700349gboolean update_engine_service_emit_status_update(
350 UpdateEngineService* self,
351 gint64 last_checked_time,
352 gdouble progress,
353 const gchar* current_operation,
354 const gchar* new_version,
355 gint64 new_size) {
356 g_signal_emit(self,
357 status_update_signal,
358 0,
359 last_checked_time,
360 progress,
361 current_operation,
362 new_version,
363 new_size);
364 return TRUE;
365}