Add DBus methods to allow/disallow updates over 3G

This fix adds a new DBus pair of methods to allow/disallow the
updates over cellular networks and get the current state of this
setting. The setting is overridden by the device policy and the
SetUpdateOverCellularPermission() method fails if called on an
enrolled device that has the autoupdate settings in the device
policy.

BUG=chromium:213401
TEST=unittests for connection_manager changes. Manual test for the DBus service, see below.

Manual test procedure.
======================
Run on a shell:

1. Test for the default setting.
$ update_engine_client -show_update_over_cellular
[0701/183633:INFO:update_engine_client.cc(371)] Current update over cellular network setting: DISABLED
[0701/183633:INFO:update_engine_client.cc(443)] Done.

2. Test that enable works.
$ update_engine_client -update_over_cellular=yes -show_update_over_cellular
[0701/183655:INFO:update_engine_client.cc(371)] Current update over cellular network setting: ENABLED
[0701/183655:INFO:update_engine_client.cc(443)] Done.

3. Test that disable works.
$ update_engine_client -update_over_cellular=no -show_update_over_cellular
[0701/183659:INFO:update_engine_client.cc(371)] Current update over cellular network setting: DISABLED
[0701/183659:INFO:update_engine_client.cc(443)] Done.

4. Enable again the update over cellular, connect the chromebook to a 3G
and perform an update check.

Change-Id: Ic234a3ef8898b1e60e26277208276a958b7e0d94
Reviewed-on: https://gerrit.chromium.org/gerrit/60716
Reviewed-by: Chris Sosa <sosa@chromium.org>
Commit-Queue: Alex Deymo <deymo@chromium.org>
Tested-by: Alex Deymo <deymo@chromium.org>
diff --git a/dbus_service.cc b/dbus_service.cc
index e75b2b2..1a209cd 100644
--- a/dbus_service.cc
+++ b/dbus_service.cc
@@ -4,15 +4,20 @@
 
 #include "update_engine/dbus_service.h"
 
+#include <set>
 #include <string>
 
 #include <base/logging.h>
 #include <policy/device_policy.h>
 
+#include "update_engine/connection_manager.h"
 #include "update_engine/marshal.glibmarshal.h"
 #include "update_engine/omaha_request_params.h"
+#include "update_engine/update_attempter.h"
+#include "update_engine/prefs.h"
 #include "update_engine/utils.h"
 
+using std::set;
 using std::string;
 
 static const char kAUTestURLRequest[] = "autest";
@@ -219,6 +224,76 @@
   return TRUE;
 }
 
+gboolean update_engine_service_set_update_over_cellular_permission(
+    UpdateEngineService* self,
+    bool allowed,
+    GError **error) {
+  set<string> allowed_types;
+  const policy::DevicePolicy* device_policy =
+      self->system_state_->device_policy();
+
+  // The device_policy is loaded in a lazy way before an update check. Load it
+  // now from the libchromeos cache if it wasn't already loaded.
+  if (!device_policy) {
+    chromeos_update_engine::UpdateAttempter* update_attempter =
+        self->system_state_->update_attempter();
+    if (update_attempter) {
+      update_attempter->RefreshDevicePolicy();
+      device_policy = self->system_state_->device_policy();;
+    }
+  }
+
+  // Check if this setting is allowed by the device policy.
+  if (device_policy &&
+      device_policy->GetAllowedConnectionTypesForUpdate(&allowed_types)) {
+    LOG(INFO) << "Ignoring the update over cellular setting since there's "
+                 "a device policy enforcing this setting.";
+    *error = NULL;
+    return FALSE;
+  }
+
+  // If the policy wasn't loaded yet, then it is still OK to change the local
+  // setting because the policy will be checked again during the update check.
+
+  chromeos_update_engine::PrefsInterface* prefs = self->system_state_->prefs();
+
+  if (!prefs->SetInt64(
+      chromeos_update_engine::kPrefsUpdateOverCellularPermission,
+      allowed ? 1 : 0)) {
+    LOG(ERROR) << "Error setting the update over cellular to "
+               << (allowed ? 1 : 0);
+    *error = NULL;
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+gboolean update_engine_service_get_update_over_cellular_permission(
+    UpdateEngineService* self,
+    bool* allowed,
+    GError **/*error*/) {
+  chromeos_update_engine::ConnectionManager* cm =
+      self->system_state_->connection_manager();
+
+  // The device_policy is loaded in a lazy way before an update check and is
+  // used to determine if an update is allowed over cellular. Load the device
+  // policy now from the libchromeos cache if it wasn't already loaded.
+  if (!self->system_state_->device_policy()) {
+    chromeos_update_engine::UpdateAttempter* update_attempter =
+        self->system_state_->update_attempter();
+    if (update_attempter)
+      update_attempter->RefreshDevicePolicy();
+  }
+
+  // Return the current setting based on the same logic used while checking for
+  // updates. A log message could be printed as the result of this test.
+  LOG(INFO) << "Checking if updates over cellular networks are allowed:";
+  *allowed = cm->IsUpdateAllowedOver(chromeos_update_engine::kNetCellular);
+
+  return TRUE;
+}
+
 gboolean update_engine_service_emit_status_update(
     UpdateEngineService* self,
     gint64 last_checked_time,