AU: Beginnings of dbus support.

The AU will be a daemon that runs as root. Non-root will communicate
via dbus with the updater to do things such as: query status, request
forced or full updates, etc.

New files for dbus:

UpdateEngine.conf - security configuration
dbus_constants.h - common constants
dbus_service.* - The object exposed over dbus
org.chromium.UpdateEngine.service - the dbus service file
udpate_attempter.* - Refactored this out of main.cc
update_engine_client.cc - Simple command line utility to interact with
Update Engine over dbus. Whereas Update Engine runs as root, this tool
runs as non-root user.

Review URL: http://codereview.chromium.org/1733013
diff --git a/main.cc b/main.cc
index cbd6e44..a796a98 100644
--- a/main.cc
+++ b/main.cc
@@ -1,26 +1,24 @@
-// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// TODO(adlr): get rid of commented out lines or comment them back in.
-// Look for "// re-add" next to those comments.
-
 #include <string>
 #include <tr1/memory>
 #include <vector>
 #include <gflags/gflags.h>
 #include <glib.h>
+#include "base/command_line.h"
 #include "chromeos/obsolete_logging.h"
-#include "update_engine/action_processor.h"
-#include "update_engine/download_action.h"
-#include "update_engine/filesystem_copier_action.h"
-// #include "update_engine/install_action.h"  // re-add
-#include "update_engine/libcurl_http_fetcher.h"
-#include "update_engine/omaha_request_prep_action.h"
-#include "update_engine/omaha_response_handler_action.h"
-#include "update_engine/postinstall_runner_action.h"
-#include "update_engine/set_bootable_flag_action.h"
-#include "update_engine/update_check_action.h"
+#include "update_engine/dbus_constants.h"
+#include "update_engine/dbus_service.h"
+#include "update_engine/update_attempter.h"
+
+extern "C" {
+#include "update_engine/update_engine.dbusserver.h"
+}
+
+DEFINE_bool(logtostderr, false,
+            "Write logs to stderr instead of to a file in log_dir.");
 
 using std::string;
 using std::tr1::shared_ptr;
@@ -28,121 +26,64 @@
 
 namespace chromeos_update_engine {
 
-class UpdateAttempter : public ActionProcessorDelegate {
- public:
-  UpdateAttempter(GMainLoop *loop)
-      : full_update_(false),
-        loop_(loop) {}
-  void Update(bool force_full_update);
-  
-  // Delegate method:
-  void ProcessingDone(const ActionProcessor* processor, bool success);
- private:
-  bool full_update_;
-  vector<shared_ptr<AbstractAction> > actions_;
-  ActionProcessor processor_;
-  GMainLoop *loop_;
+gboolean SetupInMainLoop(void* arg) {
+  // TODO(adlr): Tell update_attempter to start working.
+  // Comment this in for that:
+  //UpdateAttempter* update_attempter = reinterpret_cast<UpdateAttempter*>(arg);
 
-  // pointer to the OmahaResponseHandlerAction in the actions_ vector;
-  shared_ptr<OmahaResponseHandlerAction> response_handler_action_;
-  DISALLOW_COPY_AND_ASSIGN(UpdateAttempter);
-};
-
-// Returns true on success. If there was no update available, that's still
-// success.
-// If force_full is true, try to force a full update.
-void UpdateAttempter::Update(bool force_full_update) {
-  full_update_ = force_full_update;
-  CHECK(!processor_.IsRunning());
-  processor_.set_delegate(this);
-
-  // Actions:
-  shared_ptr<OmahaRequestPrepAction> request_prep_action(
-      new OmahaRequestPrepAction(force_full_update));
-  shared_ptr<UpdateCheckAction> update_check_action(
-      new UpdateCheckAction(new LibcurlHttpFetcher));
-  shared_ptr<OmahaResponseHandlerAction> response_handler_action(
-      new OmahaResponseHandlerAction);
-  shared_ptr<FilesystemCopierAction> filesystem_copier_action(
-      new FilesystemCopierAction);
-  shared_ptr<DownloadAction> download_action(
-      new DownloadAction(new LibcurlHttpFetcher));
-  // shared_ptr<InstallAction> install_action(  // re-add
-  //     new InstallAction);
-  shared_ptr<PostinstallRunnerAction> postinstall_runner_action(
-      new PostinstallRunnerAction);
-  shared_ptr<SetBootableFlagAction> set_bootable_flag_action(
-      new SetBootableFlagAction);
-      
-  response_handler_action_ = response_handler_action;
-
-  actions_.push_back(shared_ptr<AbstractAction>(request_prep_action));
-  actions_.push_back(shared_ptr<AbstractAction>(update_check_action));
-  actions_.push_back(shared_ptr<AbstractAction>(response_handler_action));
-  actions_.push_back(shared_ptr<AbstractAction>(filesystem_copier_action));
-  actions_.push_back(shared_ptr<AbstractAction>(download_action));
-  // actions_.push_back(shared_ptr<AbstractAction>(install_action));  // re-add
-  actions_.push_back(shared_ptr<AbstractAction>(postinstall_runner_action));
-  actions_.push_back(shared_ptr<AbstractAction>(set_bootable_flag_action));
-  
-  // Enqueue the actions
-  for (vector<shared_ptr<AbstractAction> >::iterator it = actions_.begin();
-       it != actions_.end(); ++it) {
-    processor_.EnqueueAction(it->get());
-  }
-
-  // Bond them together. We have to use the leaf-types when calling
-  // BondActions().
-  BondActions(request_prep_action.get(), update_check_action.get());
-  BondActions(update_check_action.get(), response_handler_action.get());
-  BondActions(response_handler_action.get(), filesystem_copier_action.get());
-  BondActions(filesystem_copier_action.get(), download_action.get());
-  // BondActions(download_action.get(), install_action.get());  // re-add
-  // BondActions(install_action.get(), postinstall_runner_action.get());
-  BondActions(postinstall_runner_action.get(), set_bootable_flag_action.get());
-
-  processor_.StartProcessing();
-}
-
-void UpdateAttempter::ProcessingDone(const ActionProcessor* processor,
-                                     bool success) {
-  CHECK(response_handler_action_);
-  if (response_handler_action_->GotNoUpdateResponse()) {
-    // All done.
-    g_main_loop_quit(loop_);
-    return;
-  }
-  if (!success) {
-    if (!full_update_) {
-      LOG(ERROR) << "Update failed. Attempting full update";
-      actions_.clear();
-      response_handler_action_.reset();
-      Update(true);
-      return;
-    } else {
-      LOG(ERROR) << "Full update failed. Aborting";
-    }
-  }
-  g_main_loop_quit(loop_);
-}
-
-gboolean UpdateInMainLoop(void* arg) {
-  UpdateAttempter* update_attempter = reinterpret_cast<UpdateAttempter*>(arg);
-  update_attempter->Update(false);
   return FALSE;  // Don't call this callback function again
 }
 
+void SetupDbusService(UpdateEngineService* service) {
+  DBusGConnection *bus;
+  DBusGProxy *proxy;
+  GError *error = NULL;
+
+  bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
+  if (!bus) {
+    LOG(FATAL) << "Failed to get bus";
+  }
+  proxy = dbus_g_proxy_new_for_name(bus,
+                                    DBUS_SERVICE_DBUS,
+                                    DBUS_PATH_DBUS,
+                                    DBUS_INTERFACE_DBUS);
+
+  guint32 request_name_ret;
+  if (!org_freedesktop_DBus_request_name(proxy,
+                                         kUpdateEngineServiceName,
+                                         0,
+                                         &request_name_ret,
+                                         &error)) {
+    LOG(FATAL) << "Failed to get name: " << error->message;
+  }
+  if (request_name_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+    g_warning("Got result code %u from requesting name", request_name_ret);
+    g_error_free(error);
+    exit(1);
+    LOG(FATAL) << "Got result code " << request_name_ret
+               << " from requesting name, but expected "
+               << DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
+  }
+  dbus_g_connection_register_g_object(bus,
+                                      "/org/chromium/UpdateEngine",
+                                      G_OBJECT(service));
+}
+
 }  // namespace chromeos_update_engine
 
 #include "update_engine/subprocess.h"
 
 int main(int argc, char** argv) {
+  ::g_type_init();
   g_thread_init(NULL);
+  dbus_g_thread_init();
   chromeos_update_engine::Subprocess::Init();
   google::ParseCommandLineFlags(&argc, &argv, true);
-  // TODO(adlr): figure out log file
-  logging::InitLogging("",
-                       logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
+  CommandLine::Init(argc, argv);
+  logging::InitLogging("logfile.txt",
+                       FLAGS_logtostderr ?
+                         logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG :
+                         logging::LOG_ONLY_TO_FILE,
                        logging::DONT_LOCK_LOG_FILE,
                        logging::APPEND_TO_OLD_LOG_FILE);
   LOG(INFO) << "Chrome OS Update Engine starting";
@@ -150,13 +91,26 @@
   // Create the single GMainLoop
   GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE);
 
+  // Create the update attempter:
   chromeos_update_engine::UpdateAttempter update_attempter(loop);
 
-  g_timeout_add(0, &chromeos_update_engine::UpdateInMainLoop,
-                &update_attempter);
+  // Create the dbus service object:
+  dbus_g_object_type_install_info(UPDATE_ENGINE_TYPE_SERVICE,
+                                  &dbus_glib_update_engine_service_object_info);
+  UpdateEngineService* service =
+      UPDATE_ENGINE_SERVICE(g_object_new(UPDATE_ENGINE_TYPE_SERVICE, NULL));
+  service->update_attempter_ = &update_attempter;
+  chromeos_update_engine::SetupDbusService(service);
 
+  // Set up init routine to run within the main loop.
+  g_timeout_add(0, &chromeos_update_engine::SetupInMainLoop, &update_attempter);
+
+  // Run the main loop until exit time:
   g_main_loop_run(loop);
+
+  // Cleanup:
   g_main_loop_unref(loop);
+  g_object_unref(G_OBJECT(service));
 
   LOG(INFO) << "Chrome OS Update Engine terminating";
   return 0;