blob: bc84858068d7a27bc3df2aecb385d6ded258c7ce [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"
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070014#include "update_engine/marshal.glibmarshal.h"
Darin Petkov49d91322010-10-25 16:34:58 -070015#include "update_engine/omaha_request_params.h"
Alex Deymof4867c42013-06-28 14:41:39 -070016#include "update_engine/update_attempter.h"
17#include "update_engine/prefs.h"
Darin Petkova07586b2010-10-20 13:41:15 -070018#include "update_engine/utils.h"
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070019
Alex Deymof4867c42013-06-28 14:41:39 -070020using std::set;
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070021using std::string;
22
Darin Petkov820a77b2011-04-27 16:48:58 -070023static const char kAUTestURLRequest[] = "autest";
Jay Srinivasane73acab2012-07-10 14:34:03 -070024// By default autest bypasses scattering. If we want to test scattering,
25// we should use autest-scheduled. The Url used is same in both cases, but
26// different params are passed to CheckForUpdate method.
27static const char kScheduledAUTestURLRequest[] = "autest-scheduled";
28
Darin Petkov820a77b2011-04-27 16:48:58 -070029static const char kAUTestURL[] =
Darin Petkov5445e162011-11-04 10:10:27 +010030 "https://omaha.sandbox.google.com/service/update2";
Darin Petkov820a77b2011-04-27 16:48:58 -070031
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070032G_DEFINE_TYPE(UpdateEngineService, update_engine_service, G_TYPE_OBJECT)
33
34static void update_engine_service_finalize(GObject* object) {
35 G_OBJECT_CLASS(update_engine_service_parent_class)->finalize(object);
36}
37
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070038static guint status_update_signal = 0;
39
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070040static void update_engine_service_class_init(UpdateEngineServiceClass* klass) {
41 GObjectClass *object_class;
42 object_class = G_OBJECT_CLASS(klass);
43 object_class->finalize = update_engine_service_finalize;
Darin Petkov5a7f5652010-07-22 21:40:09 -070044
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070045 status_update_signal = g_signal_new(
46 "status_update",
47 G_OBJECT_CLASS_TYPE(klass),
48 G_SIGNAL_RUN_LAST,
49 0, // 0 == no class method associated
50 NULL, // Accumulator
51 NULL, // Accumulator data
52 update_engine_VOID__INT64_DOUBLE_STRING_STRING_INT64,
53 G_TYPE_NONE, // Return type
54 5, // param count:
55 G_TYPE_INT64,
56 G_TYPE_DOUBLE,
57 G_TYPE_STRING,
58 G_TYPE_STRING,
59 G_TYPE_INT64);
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070060}
61
62static void update_engine_service_init(UpdateEngineService* object) {
63}
64
65UpdateEngineService* update_engine_service_new(void) {
66 return reinterpret_cast<UpdateEngineService*>(
67 g_object_new(UPDATE_ENGINE_TYPE_SERVICE, NULL));
68}
69
Darin Petkov296889c2010-07-23 16:20:54 -070070gboolean update_engine_service_attempt_update(UpdateEngineService* self,
71 gchar* app_version,
72 gchar* omaha_url,
73 GError **error) {
Darin Petkova07586b2010-10-20 13:41:15 -070074 string update_app_version;
75 string update_omaha_url;
Gilad Arnoldb92f0df2013-01-10 16:32:45 -080076 bool interactive = true;
Jay Srinivasane73acab2012-07-10 14:34:03 -070077
Darin Petkova07586b2010-10-20 13:41:15 -070078 // Only non-official (e.g., dev and test) builds can override the current
Darin Petkov820a77b2011-04-27 16:48:58 -070079 // version and update server URL over D-Bus. However, pointing to the
80 // hardcoded test update server URL is always allowed.
Darin Petkova07586b2010-10-20 13:41:15 -070081 if (!chromeos_update_engine::utils::IsOfficialBuild()) {
82 if (app_version) {
83 update_app_version = app_version;
84 }
85 if (omaha_url) {
86 update_omaha_url = omaha_url;
87 }
88 }
Jay Srinivasane73acab2012-07-10 14:34:03 -070089 if (omaha_url) {
90 if (strcmp(omaha_url, kScheduledAUTestURLRequest) == 0) {
91 update_omaha_url = kAUTestURL;
92 // pretend that it's not user-initiated even though it is,
93 // so as to test scattering logic, etc. which get kicked off
94 // only in scheduled update checks.
Gilad Arnoldb92f0df2013-01-10 16:32:45 -080095 interactive = false;
Jay Srinivasane73acab2012-07-10 14:34:03 -070096 } else if (strcmp(omaha_url, kAUTestURLRequest) == 0) {
97 update_omaha_url = kAUTestURL;
98 }
Darin Petkov820a77b2011-04-27 16:48:58 -070099 }
Darin Petkov296889c2010-07-23 16:20:54 -0700100 LOG(INFO) << "Attempt update: app_version=\"" << update_app_version << "\" "
Jay Srinivasane73acab2012-07-10 14:34:03 -0700101 << "omaha_url=\"" << update_omaha_url << "\" "
Gilad Arnoldb92f0df2013-01-10 16:32:45 -0800102 << "interactive=" << (interactive? "yes" : "no");
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700103 self->system_state_->update_attempter()->CheckForUpdate(update_app_version,
104 update_omaha_url,
105 interactive);
Darin Petkov296889c2010-07-23 16:20:54 -0700106 return TRUE;
107}
108
Chris Sosad317e402013-06-12 13:47:09 -0700109gboolean update_engine_service_attempt_rollback(UpdateEngineService* self,
110 bool powerwash,
111 GError **error) {
112 LOG(INFO) << "Attempting rollback to non-active partitions.";
Chris Sosa76a29ae2013-07-11 17:59:24 -0700113 return self->system_state_->update_attempter()->Rollback(powerwash, NULL);
Chris Sosad317e402013-06-12 13:47:09 -0700114}
115
Jay Srinivasanc1ba09a2012-08-14 14:15:57 -0700116gboolean update_engine_service_reset_status(UpdateEngineService* self,
117 GError **error) {
118 *error = NULL;
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700119 return self->system_state_->update_attempter()->ResetStatus();
Jay Srinivasanc1ba09a2012-08-14 14:15:57 -0700120}
121
122
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700123gboolean update_engine_service_get_status(UpdateEngineService* self,
124 int64_t* last_checked_time,
125 double* progress,
126 gchar** current_operation,
127 gchar** new_version,
128 int64_t* new_size,
129 GError **error) {
130 string current_op;
131 string new_version_str;
Darin Petkov5a7f5652010-07-22 21:40:09 -0700132
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700133 CHECK(self->system_state_->update_attempter()->GetStatus(last_checked_time,
134 progress,
135 &current_op,
136 &new_version_str,
137 new_size));
Darin Petkov5a7f5652010-07-22 21:40:09 -0700138
Satoru Takabayashid6982312010-11-29 12:54:12 +0900139 *current_operation = g_strdup(current_op.c_str());
140 *new_version = g_strdup(new_version_str.c_str());
Chris Masonec6c57a52010-09-23 13:06:14 -0700141 if (!(*current_operation && *new_version)) {
142 *error = NULL;
143 return FALSE;
144 }
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700145 return TRUE;
146}
147
Darin Petkov296889c2010-07-23 16:20:54 -0700148gboolean update_engine_service_reboot_if_needed(UpdateEngineService* self,
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700149 GError **error) {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700150 if (!self->system_state_->update_attempter()->RebootIfNeeded()) {
Darin Petkov296889c2010-07-23 16:20:54 -0700151 *error = NULL;
152 return FALSE;
153 }
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700154 return TRUE;
155}
156
Darin Petkov8daa3242010-10-25 13:28:47 -0700157gboolean update_engine_service_set_track(UpdateEngineService* self,
158 gchar* track,
159 GError **error) {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700160 // track == target channel.
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700161 // TODO(jaysri): Remove this method once chromium:219292 is fixed.
162 // Since UI won't be ready for now, preserve the existing
163 // behavior for set_track by calling SetTargetChannel directly without the
164 // policy checks instead of calling update_engine_service_set_channel.
165 LOG(INFO) << "Setting destination track to: " << track;
166 if (!self->system_state_->request_params()->SetTargetChannel(track, false)) {
167 *error = NULL;
168 return FALSE;
169 }
170
171 return TRUE;
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700172}
173
174gboolean update_engine_service_get_track(UpdateEngineService* self,
175 gchar** track,
176 GError **error) {
177 // track == target channel.
178 return update_engine_service_get_channel(self, false, track, error);
179}
180
181gboolean update_engine_service_set_channel(UpdateEngineService* self,
182 gchar* target_channel,
183 bool is_powerwash_allowed,
184 GError **error) {
185 if (!target_channel)
186 return FALSE;
187
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700188 const policy::DevicePolicy* device_policy =
189 self->system_state_->device_policy();
190 if (!device_policy) {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700191 LOG(INFO) << "Cannot set target channel until device policy/settings are "
192 "known";
193 return FALSE;
Darin Petkov8daa3242010-10-25 13:28:47 -0700194 }
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700195
196 bool delegated = false;
Chris Sosa1ed60782013-06-18 17:05:33 -0700197 if (device_policy->GetReleaseChannelDelegated(&delegated) && !delegated) {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700198 LOG(INFO) << "Cannot set target channel explicitly when channel "
199 "policy/settings is not delegated";
200 return FALSE;
201 }
202
203 LOG(INFO) << "Setting destination channel to: " << target_channel;
204 if (!self->system_state_->request_params()->SetTargetChannel(
205 target_channel, is_powerwash_allowed)) {
206 *error = NULL;
207 return FALSE;
208 }
209
210 return TRUE;
211}
212
213gboolean update_engine_service_get_channel(UpdateEngineService* self,
214 bool get_current_channel,
215 gchar** channel,
216 GError **error) {
217 chromeos_update_engine::OmahaRequestParams* rp =
218 self->system_state_->request_params();
219
220 string channel_str = get_current_channel ?
221 rp->current_channel() : rp->target_channel();
222
223 *channel = g_strdup(channel_str.c_str());
Darin Petkov8daa3242010-10-25 13:28:47 -0700224 return TRUE;
225}
226
Alex Deymof4867c42013-06-28 14:41:39 -0700227gboolean update_engine_service_set_update_over_cellular_permission(
228 UpdateEngineService* self,
229 bool allowed,
230 GError **error) {
231 set<string> allowed_types;
232 const policy::DevicePolicy* device_policy =
233 self->system_state_->device_policy();
234
235 // The device_policy is loaded in a lazy way before an update check. Load it
236 // now from the libchromeos cache if it wasn't already loaded.
237 if (!device_policy) {
238 chromeos_update_engine::UpdateAttempter* update_attempter =
239 self->system_state_->update_attempter();
240 if (update_attempter) {
241 update_attempter->RefreshDevicePolicy();
242 device_policy = self->system_state_->device_policy();;
243 }
244 }
245
246 // Check if this setting is allowed by the device policy.
247 if (device_policy &&
248 device_policy->GetAllowedConnectionTypesForUpdate(&allowed_types)) {
249 LOG(INFO) << "Ignoring the update over cellular setting since there's "
250 "a device policy enforcing this setting.";
251 *error = NULL;
252 return FALSE;
253 }
254
255 // If the policy wasn't loaded yet, then it is still OK to change the local
256 // setting because the policy will be checked again during the update check.
257
258 chromeos_update_engine::PrefsInterface* prefs = self->system_state_->prefs();
259
Alex Deymoefb7c4c2013-07-09 14:34:00 -0700260 if (!prefs->SetBoolean(
Alex Deymof4867c42013-06-28 14:41:39 -0700261 chromeos_update_engine::kPrefsUpdateOverCellularPermission,
Alex Deymoefb7c4c2013-07-09 14:34:00 -0700262 allowed)) {
Alex Deymof4867c42013-06-28 14:41:39 -0700263 LOG(ERROR) << "Error setting the update over cellular to "
Alex Deymoefb7c4c2013-07-09 14:34:00 -0700264 << (allowed ? "true" : "false");
Alex Deymof4867c42013-06-28 14:41:39 -0700265 *error = NULL;
266 return FALSE;
267 }
268
269 return TRUE;
270}
271
272gboolean update_engine_service_get_update_over_cellular_permission(
273 UpdateEngineService* self,
274 bool* allowed,
275 GError **/*error*/) {
276 chromeos_update_engine::ConnectionManager* cm =
277 self->system_state_->connection_manager();
278
279 // The device_policy is loaded in a lazy way before an update check and is
280 // used to determine if an update is allowed over cellular. Load the device
281 // policy now from the libchromeos cache if it wasn't already loaded.
282 if (!self->system_state_->device_policy()) {
283 chromeos_update_engine::UpdateAttempter* update_attempter =
284 self->system_state_->update_attempter();
285 if (update_attempter)
286 update_attempter->RefreshDevicePolicy();
287 }
288
289 // Return the current setting based on the same logic used while checking for
290 // updates. A log message could be printed as the result of this test.
291 LOG(INFO) << "Checking if updates over cellular networks are allowed:";
292 *allowed = cm->IsUpdateAllowedOver(chromeos_update_engine::kNetCellular);
293
294 return TRUE;
295}
296
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700297gboolean update_engine_service_emit_status_update(
298 UpdateEngineService* self,
299 gint64 last_checked_time,
300 gdouble progress,
301 const gchar* current_operation,
302 const gchar* new_version,
303 gint64 new_size) {
304 g_signal_emit(self,
305 status_update_signal,
306 0,
307 last_checked_time,
308 progress,
309 current_operation,
310 new_version,
311 new_size);
312 return TRUE;
313}