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/SConstruct b/SConstruct
index 5c11b6d..9598975 100644
--- a/SConstruct
+++ b/SConstruct
@@ -39,6 +39,46 @@
single_source = 1,
suffix = '.pb.cc')
+""" Inputs:
+ target: unused
+ source: list containing the source .xml file
+ env: the scons environment in which we are compiling
+ Outputs:
+ target: the list of targets we'll emit
+ source: the list of sources we'll process"""
+def DbusBindingsEmitter(target, source, env):
+ output = str(source[0])
+ output = output[0:output.rfind('.xml')]
+ target = [
+ output + '.dbusserver.h',
+ output + '.dbusclient.h'
+ ]
+ return target, source
+
+""" Inputs:
+ source: list of sources to process
+ target: list of targets to generate
+ env: scons environment in which we are working
+ for_signature: unused
+ Outputs: a list of commands to execute to generate the targets from
+ the sources."""
+def DbusBindingsGenerator(source, target, env, for_signature):
+ commands = []
+ for target_file in target:
+ if str(target_file).endswith('.dbusserver.h'):
+ mode_flag = '--mode=glib-server '
+ else:
+ mode_flag = '--mode=glib-client '
+ cmd = '/usr/bin/dbus-binding-tool %s --prefix=update_engine_service ' \
+ '%s > %s' % (mode_flag, str(source[0]), str(target_file))
+ commands.append(cmd)
+ return commands
+
+dbus_bindings_builder = Builder(generator = DbusBindingsGenerator,
+ emitter = DbusBindingsEmitter,
+ single_source = 1,
+ suffix = 'dbusclient.h')
+
env = Environment()
for key in Split('CC CXX AR RANLIB LD NM'):
value = os.environ.get(key)
@@ -54,13 +94,17 @@
env['ENV'][key] = os.environ[key]
+ # -Wclobbered
+ # -Wempty-body
+ # -Wignored-qualifiers
+ # -Wtype-limits
env['CCFLAGS'] = ' '.join("""-g
-fno-exceptions
-fno-strict-aliasing
-Wall
- -Werror
-Wclobbered
-Wempty-body
+ -Werror
-Wignored-qualifiers
-Wmissing-field-initializers
-Wsign-compare
@@ -87,25 +131,27 @@
env['CPPPATH'] = ['..', '../../third_party/chrome/files', '../../common']
env['LIBPATH'] = ['../../third_party/chrome']
env['BUILDERS']['ProtocolBuffer'] = proto_builder
+env['BUILDERS']['DbusBindings'] = dbus_bindings_builder
# Fix issue with scons not passing pkg-config vars through the environment.
for key in Split('PKG_CONFIG_LIBDIR PKG_CONFIG_PATH'):
if os.environ.has_key(key):
env['ENV'][key] = os.environ[key]
-env.ParseConfig('pkg-config --cflags --libs glib-2.0')
+env.ParseConfig('pkg-config --cflags --libs glib-2.0 dbus-1 dbus-glib-1')
env.ProtocolBuffer('update_metadata.pb.cc', 'update_metadata.proto')
+env.DbusBindings('update_engine.dbusclient.h', 'update_engine.xml')
+
if ARGUMENTS.get('debug', 0):
env['CCFLAGS'] += ' -fprofile-arcs -ftest-coverage'
env['LIBS'] += ['bz2', 'gcov']
-
-
sources = Split("""action_processor.cc
bzip.cc
bzip_extent_writer.cc
cycle_breaker.cc
+ dbus_service.cc
decompressing_file_writer.cc
delta_diff_generator.cc
delta_performer.cc
@@ -126,6 +172,7 @@
subprocess.cc
tarjan.cc
topological_sort.cc
+ update_attempter.cc
update_check_action.cc
update_metadata.pb.cc
utils.cc""")
@@ -161,12 +208,16 @@
zip_unittest.cc""")
unittest_main = ['testrunner.cc']
+client_main = ['update_engine_client.cc']
+
delta_generator_main = ['generate_delta_main.cc']
env.Program('update_engine', sources + main)
unittest_cmd = env.Program('update_engine_unittests',
sources + unittest_sources + unittest_main)
+client_cmd = env.Program('update_engine_client', sources + client_main);
+
Clean(unittest_cmd, Glob('*.gcda') + Glob('*.gcno') + Glob('*.gcov') +
Split('html app.info'))
diff --git a/UpdateEngine.conf b/UpdateEngine.conf
new file mode 100644
index 0000000..88d6dc4
--- /dev/null
+++ b/UpdateEngine.conf
@@ -0,0 +1,23 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <policy user="root">
+ <allow own="org.chromium.UpdateEngine" />
+ <allow send_destination="org.chromium.UpdateEngine" />
+ </policy>
+ <policy user="chronos">
+ <!-- introspection is denied -->
+ <deny send_destination="org.chromium.UpdateEngine"
+ send_interface="org.freedesktop.DBus.Introspectable" />
+ <!-- properties denied -->
+ <deny send_destination="org.chromium.UpdateEngine"
+ send_interface="org.freedesktop.DBus.Properties" />
+ <!-- allow explicit methods -->
+ <allow send_destination="org.chromium.UpdateEngine"
+ send_interface="org.chromium.UpdateEngineInterface"
+ send_member="GetStatus"/>
+ </policy>
+ <policy context="default">
+ <deny send_destination="org.chromium.UpdateEngine" />
+ </policy>
+</busconfig>
diff --git a/dbus_constants.h b/dbus_constants.h
new file mode 100644
index 0000000..bd5b551
--- /dev/null
+++ b/dbus_constants.h
@@ -0,0 +1,18 @@
+// 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.
+
+#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_DBUS_CONSTANTS_H__
+#define CHROMEOS_PLATFORM_UPDATE_ENGINE_DBUS_CONSTANTS_H__
+
+namespace chromeos_update_engine {
+
+static const char* const kUpdateEngineServiceName = "org.chromium.UpdateEngine";
+static const char* const kUpdateEngineServicePath =
+ "/org/chromium/UpdateEngine";
+static const char* const kUpdateEngineServiceInterface =
+ "org.chromium.UpdateEngineInterface";
+
+} // namespace chromeos_update_engine
+
+#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_DBUS_CONSTANTS_H__
diff --git a/dbus_service.cc b/dbus_service.cc
new file mode 100644
index 0000000..8dc239f
--- /dev/null
+++ b/dbus_service.cc
@@ -0,0 +1,51 @@
+// 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.
+
+#include "update_engine/dbus_service.h"
+#include <string>
+#include "base/logging.h"
+
+using std::string;
+
+G_DEFINE_TYPE(UpdateEngineService, update_engine_service, G_TYPE_OBJECT)
+
+static void update_engine_service_finalize(GObject* object) {
+ G_OBJECT_CLASS(update_engine_service_parent_class)->finalize(object);
+}
+
+static void update_engine_service_class_init(UpdateEngineServiceClass* klass) {
+ GObjectClass *object_class;
+ object_class = G_OBJECT_CLASS(klass);
+ object_class->finalize = update_engine_service_finalize;
+}
+
+static void update_engine_service_init(UpdateEngineService* object) {
+}
+
+UpdateEngineService* update_engine_service_new(void) {
+ return reinterpret_cast<UpdateEngineService*>(
+ g_object_new(UPDATE_ENGINE_TYPE_SERVICE, NULL));
+}
+
+gboolean update_engine_service_get_status(UpdateEngineService* self,
+ int64_t* last_checked_time,
+ double* progress,
+ gchar** current_operation,
+ gchar** new_version,
+ int64_t* new_size,
+ GError **error) {
+ string current_op;
+ string new_version_str;
+
+ CHECK(self->update_attempter_->GetStatus(last_checked_time,
+ progress,
+ ¤t_op,
+ &new_version_str,
+ new_size));
+
+ *current_operation = strdup(current_op.c_str());
+ *new_version = strdup(new_version_str.c_str());
+ return TRUE;
+}
+
diff --git a/dbus_service.h b/dbus_service.h
new file mode 100644
index 0000000..1b2604e
--- /dev/null
+++ b/dbus_service.h
@@ -0,0 +1,59 @@
+// 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.
+
+#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_DBUS_SERVICE_H__
+#define CHROMEOS_PLATFORM_UPDATE_ENGINE_DBUS_SERVICE_H__
+
+#include <inttypes.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-bindings.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <glib-object.h>
+
+#include "update_engine/update_attempter.h"
+
+// Type macros:
+#define UPDATE_ENGINE_TYPE_SERVICE (update_engine_service_get_type())
+#define UPDATE_ENGINE_SERVICE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), UPDATE_ENGINE_TYPE_SERVICE, \
+ UpdateEngineService))
+#define UPDATE_ENGINE_IS_SERVICE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), UPDATE_ENGINE_TYPE_SERVICE))
+#define UPDATE_ENGINE_SERVICE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), UPDATE_ENGINE_TYPE_SERVICE, \
+ UpdateEngineService))
+#define UPDATE_ENGINE_IS_SERVICE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), UPDATE_ENGINE_TYPE_SERVICE))
+#define UPDATE_ENGINE_SERVICE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj), UPDATE_ENGINE_TYPE_SERVICE, \
+ UpdateEngineService))
+
+G_BEGIN_DECLS
+
+struct UpdateEngineService {
+ GObject parent_instance;
+
+ chromeos_update_engine::UpdateAttempter* update_attempter_;
+};
+
+struct UpdateEngineServiceClass {
+ GObjectClass parent_class;
+};
+
+UpdateEngineService* update_engine_service_new(void);
+GType update_engine_service_get_type(void);
+
+// Methods
+
+gboolean update_engine_service_get_status(UpdateEngineService* self,
+ int64_t* last_checked_time,
+ double* progress,
+ gchar** current_operation,
+ gchar** new_version,
+ int64_t* new_size,
+ GError **error);
+
+G_END_DECLS
+
+#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_DBUS_SERVICE_H__
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;
diff --git a/org.chromium.UpdateEngine.service b/org.chromium.UpdateEngine.service
new file mode 100644
index 0000000..e8b5fdc
--- /dev/null
+++ b/org.chromium.UpdateEngine.service
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.chromium.UpdateEngine
+Exec=/usr/sbin/update_engine
diff --git a/update_attempter.cc b/update_attempter.cc
new file mode 100644
index 0000000..6b8c361
--- /dev/null
+++ b/update_attempter.cc
@@ -0,0 +1,127 @@
+// 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.
+
+#include "update_engine/update_attempter.h"
+#include <tr1/memory>
+#include <string>
+#include <vector>
+#include <glib.h>
+#include "update_engine/download_action.h"
+#include "update_engine/filesystem_copier_action.h"
+#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"
+
+using std::tr1::shared_ptr;
+using std::string;
+using std::vector;
+
+namespace chromeos_update_engine {
+
+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<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>(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());
+ // TODO(adlr): Bond these actions together properly
+ // BondActions(download_action.get(), install_action.get());
+ // BondActions(install_action.get(), postinstall_runner_action.get());
+ BondActions(postinstall_runner_action.get(), set_bootable_flag_action.get());
+
+ processor_.StartProcessing();
+}
+
+// Delegate method:
+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_);
+}
+
+// Stop updating. An attempt will be made to record status to the disk
+// so that updates can be resumed later.
+void UpdateAttempter::Terminate() {
+ // TODO(adlr): implement this method.
+ NOTIMPLEMENTED();
+}
+
+// Try to resume from a previously Terminate()d update.
+void UpdateAttempter::ResumeUpdating() {
+ // TODO(adlr): implement this method.
+ NOTIMPLEMENTED();
+}
+
+bool UpdateAttempter::GetStatus(int64_t* last_checked_time,
+ double* progress,
+ std::string* current_operation,
+ std::string* new_version,
+ int64_t* new_size) {
+ // TODO(adlr): Return actual status.
+ *last_checked_time = 123;
+ *progress = 0.2223;
+ *current_operation = "DOWNLOADING";
+ *new_version = "0.2.3.8";
+ *new_size = 10002;
+ return true;
+}
+
+
+} // namespace chromeos_update_engine
diff --git a/update_attempter.h b/update_attempter.h
new file mode 100644
index 0000000..83e4737
--- /dev/null
+++ b/update_attempter.h
@@ -0,0 +1,54 @@
+// 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.
+
+#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_UPDATE_ATTEMPTER_H__
+#define CHROMEOS_PLATFORM_UPDATE_ENGINE_UPDATE_ATTEMPTER_H__
+
+#include <tr1/memory>
+#include <string>
+#include <vector>
+#include <glib.h>
+#include "update_engine/action_processor.h"
+#include "update_engine/omaha_response_handler_action.h"
+
+namespace chromeos_update_engine {
+
+class UpdateAttempter : public ActionProcessorDelegate {
+ public:
+ explicit UpdateAttempter(GMainLoop *loop)
+ : full_update_(false),
+ loop_(loop) {}
+ void Update(bool force_full_update);
+
+ // Delegate method:
+ void ProcessingDone(const ActionProcessor* processor, bool success);
+
+ // Stop updating. An attempt will be made to record status to the disk
+ // so that updates can be resumed later.
+ void Terminate();
+
+ // Try to resume from a previously Terminate()d update.
+ void ResumeUpdating();
+
+ // Returns the current status in the out params. Returns true on success.
+ bool GetStatus(int64_t* last_checked_time,
+ double* progress,
+ std::string* current_operation,
+ std::string* new_version,
+ int64_t* new_size);
+
+ private:
+ bool full_update_;
+ std::vector<std::tr1::shared_ptr<AbstractAction> > actions_;
+ ActionProcessor processor_;
+ GMainLoop *loop_;
+
+ // pointer to the OmahaResponseHandlerAction in the actions_ vector;
+ std::tr1::shared_ptr<OmahaResponseHandlerAction> response_handler_action_;
+ DISALLOW_COPY_AND_ASSIGN(UpdateAttempter);
+};
+
+} // namespace chromeos_update_engine
+
+#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_UPDATE_ATTEMPTER_H__
diff --git a/update_engine.xml b/update_engine.xml
new file mode 100644
index 0000000..11c804f
--- /dev/null
+++ b/update_engine.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!-- COPYRIGHT HERE
+ dbus-binding-tool -mode=glib-server -prefix=update_engine update_engine.xml
+ > glib_server.h
+-->
+<node name="/org/chromium">
+ <interface name="org.chromium.UpdateEngineInterface">
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol"
+ value="update_engine_service"/>
+ <method name="GetStatus">
+ <arg type="x" name="last_checked_time" direction="out" />
+ <arg type="d" name="progress" direction="out" />
+ <arg type="s" name="current_operation" direction="out" />
+ <arg type="s" name="new_version" direction="out" />
+ <arg type="x" name="new_size" direction="out" />
+ </method>
+ </interface>
+</node>
diff --git a/update_engine_client.cc b/update_engine_client.cc
new file mode 100644
index 0000000..1e273ed
--- /dev/null
+++ b/update_engine_client.cc
@@ -0,0 +1,112 @@
+// 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.
+
+#include <gflags/gflags.h>
+#include <glib.h>
+
+#include "update_engine/dbus_constants.h"
+#include "update_engine/subprocess.h"
+#include "update_engine/utils.h"
+
+extern "C" {
+#include "update_engine/update_engine.dbusclient.h"
+}
+
+using chromeos_update_engine::kUpdateEngineServiceName;
+using chromeos_update_engine::kUpdateEngineServicePath;
+using chromeos_update_engine::kUpdateEngineServiceInterface;
+
+DEFINE_bool(status, false, "Print the status to stdout.");
+DEFINE_bool(force_update, false,
+ "Force an update, even over an expensive network.");
+DEFINE_bool(check_for_update, false,
+ "Initiate check for updates.");
+
+namespace {
+
+const char* GetErrorMessage(const GError* error) {
+ if (!error)
+ return "Unknown error.";
+ return error->message;
+}
+
+bool GetStatus() {
+ 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_owner(bus,
+ kUpdateEngineServiceName,
+ kUpdateEngineServicePath,
+ kUpdateEngineServiceInterface,
+ &error);
+ if (!proxy) {
+ LOG(FATAL) << "Error getting proxy: " << GetErrorMessage(error);
+ }
+
+ gint64 last_checked_time = 0;
+ gdouble progress = 0.0;
+ char* current_op = NULL;
+ char* new_version = NULL;
+ gint64 new_size = 0;
+
+ gboolean rc = org_chromium_UpdateEngineInterface_get_status(
+ proxy,
+ &last_checked_time,
+ &progress,
+ ¤t_op,
+ &new_version,
+ &new_size,
+ &error);
+ if (rc == FALSE) {
+ LOG(INFO) << "Error getting status: " << GetErrorMessage(error);
+ }
+ printf("LAST_CHECKED_TIME=%" PRIi64 "\nPROGRESS=%f\nCURRENT_OP=%s\n"
+ "NEW_VERSION=%s\nNEW_SIZE=%" PRIi64 "\n",
+ last_checked_time,
+ progress,
+ current_op,
+ new_version,
+ new_size);
+ return true;
+}
+
+bool CheckForUpdates(bool force) {
+ return true;
+}
+
+} // namespace {}
+
+int main(int argc, char** argv) {
+ // Boilerplate init commands.
+ g_type_init();
+ g_thread_init(NULL);
+ dbus_g_thread_init();
+ chromeos_update_engine::Subprocess::Init();
+ google::ParseCommandLineFlags(&argc, &argv, true);
+
+ if (FLAGS_status) {
+ LOG(INFO) << "Querying Update Engine status...";
+ if (!GetStatus()) {
+ LOG(FATAL) << "GetStatus() failed.";
+ }
+ return 0;
+ }
+ if (FLAGS_force_update || FLAGS_check_for_update) {
+ LOG(INFO) << "Initiating update check and install.";
+ if (FLAGS_force_update) {
+ LOG(INFO) << "Will not abort due to being on expensive network.";
+ }
+ CHECK(CheckForUpdates(FLAGS_force_update))
+ << "Update check/initiate update failed.";
+ return 0;
+ }
+
+ LOG(INFO) << "No flags specified. Exiting.";
+ return 0;
+}