summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorbenwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-23 06:17:00 +0000
committerbenwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-23 06:17:00 +0000
commit02d96b139b73c27ff3ceebbda132c59866de46f1 (patch)
tree1912ade2a73ddb933fb2aa66951a83c1dc98dcf2 /apps
parentcbba20e8ddf92868c097a10ea31ddf4e18f3776d (diff)
downloadchromium_src-02d96b139b73c27ff3ceebbda132c59866de46f1.zip
chromium_src-02d96b139b73c27ff3ceebbda132c59866de46f1.tar.gz
chromium_src-02d96b139b73c27ff3ceebbda132c59866de46f1.tar.bz2
Move app_host code from extensions into src/apps.
BUG=None Review URL: https://chromiumcodereview.appspot.com/12310059 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@184295 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'apps')
-rw-r--r--apps/app_host/DEPS3
-rw-r--r--apps/app_host/OWNERS1
-rw-r--r--apps/app_host/app_host.rc46
-rw-r--r--apps/app_host/app_host_main.cc53
-rw-r--r--apps/app_host/app_host_resource.h5
-rw-r--r--apps/app_host/binaries_installer.cc327
-rw-r--r--apps/app_host/binaries_installer.h19
-rw-r--r--apps/app_host/update.cc102
-rw-r--r--apps/app_host/update.h16
-rw-r--r--apps/apps.gypi39
10 files changed, 611 insertions, 0 deletions
diff --git a/apps/app_host/DEPS b/apps/app_host/DEPS
new file mode 100644
index 0000000..7251c42
--- /dev/null
+++ b/apps/app_host/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+google_update",
+]
diff --git a/apps/app_host/OWNERS b/apps/app_host/OWNERS
new file mode 100644
index 0000000..82e44d8
--- /dev/null
+++ b/apps/app_host/OWNERS
@@ -0,0 +1 @@
+erikwright@chromium.org
diff --git a/apps/app_host/app_host.rc b/apps/app_host/app_host.rc
new file mode 100644
index 0000000..f4fedec
--- /dev/null
+++ b/apps/app_host/app_host.rc
@@ -0,0 +1,46 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "app_host_resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_APP_HOST_MAIN ICON "..\\..\\chrome\\app\\theme\\app_list.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// GOOGLEUPDATEAPPLICATIONCOMMANDS is a "well-known" marker resource defined
+// by Omaha. Executables must both be signed by Google and contain the marker
+// in order to expose application commands.
+//
+#define IDR_GOOGLE_UPDATE_APP_COMMANDS_MARKUP 1
+
+IDR_GOOGLE_UPDATE_APP_COMMANDS_MARKUP GOOGLEUPDATEAPPLICATIONCOMMANDS { 1L }
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
diff --git a/apps/app_host/app_host_main.cc b/apps/app_host/app_host_main.cc
new file mode 100644
index 0000000..64de547
--- /dev/null
+++ b/apps/app_host/app_host_main.cc
@@ -0,0 +1,53 @@
+// Copyright (c) 2012 The Chromium 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 <windows.h>
+
+#include "apps/app_host/binaries_installer.h"
+#include "apps/app_host/update.h"
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/process_util.h"
+#include "chrome/installer/launcher_support/chrome_launcher_support.h"
+
+int APIENTRY wWinMain(HINSTANCE, HINSTANCE, wchar_t*, int) {
+ base::AtExitManager exit_manager;
+
+ // Initialize the commandline singleton from the environment.
+ CommandLine::Init(0, NULL);
+
+ base::FilePath chrome_exe(chrome_launcher_support::GetAnyChromePath());
+ if (chrome_exe.empty()) {
+ LOG(INFO) << "No Chrome executable could be found. Let's install it.";
+ HRESULT hr = app_host::InstallBinaries();
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to install the Chrome Binaries. Error: " << hr;
+ return 1;
+ } else {
+ chrome_exe = chrome_launcher_support::GetAnyChromePath();
+ if (chrome_exe.empty()) {
+ LOG(ERROR) << "Failed to find the Chrome Binaries despite a "
+ << "'successful' installation.";
+ return 1;
+ }
+ }
+ }
+
+ CommandLine chrome_exe_command_line(chrome_exe);
+ chrome_exe_command_line.AppendArguments(
+ *CommandLine::ForCurrentProcess(), false);
+ // Launch Chrome before checking for update, for faster user experience.
+ bool launch_result = base::LaunchProcess(chrome_exe_command_line,
+ base::LaunchOptions(), NULL);
+ if (launch_result)
+ LOG(INFO) << "Delegated to Chrome executable at " << chrome_exe.value();
+ else
+ LOG(INFO) << "Failed to launch Chrome executable at " << chrome_exe.value();
+
+ app_host::EnsureAppHostUpToDate();
+
+ return !launch_result;
+}
diff --git a/apps/app_host/app_host_resource.h b/apps/app_host/app_host_resource.h
new file mode 100644
index 0000000..29d289c
--- /dev/null
+++ b/apps/app_host/app_host_resource.h
@@ -0,0 +1,5 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#define IDI_APP_HOST_MAIN 101
diff --git a/apps/app_host/binaries_installer.cc b/apps/app_host/binaries_installer.cc
new file mode 100644
index 0000000..ce72888
--- /dev/null
+++ b/apps/app_host/binaries_installer.cc
@@ -0,0 +1,327 @@
+// Copyright (c) 2012 The Chromium 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 "apps/app_host/binaries_installer.h"
+
+#include "base/logging.h"
+#include "base/threading/platform_thread.h"
+#include "base/win/scoped_bstr.h"
+#include "base/win/scoped_com_initializer.h"
+#include "base/win/scoped_comptr.h"
+#include "google_update/google_update_idl.h"
+
+
+namespace app_host {
+
+// Helpers --------------------------------------------------------------------
+
+namespace {
+
+const wchar_t kAppHostAppId[] = L"{FDA71E6F-AC4C-4a00-8B70-9958A68906BF}";
+const wchar_t kBinariesAppId[] = L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}";
+const int kInstallationPollingIntervalMs = 50;
+
+HRESULT CreateInstalledApp(IAppBundle* app_bundle,
+ const wchar_t* app_guid,
+ IApp** app) {
+ base::win::ScopedComPtr<IDispatch> idispatch;
+ HRESULT hr = app_bundle->createInstalledApp(base::win::ScopedBstr(app_guid),
+ idispatch.Receive());
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to configure App Bundle: " << hr;
+ return hr;
+ }
+
+ base::win::ScopedComPtr<IApp> temp_app;
+ hr = temp_app.QueryFrom(idispatch);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Unexpected error querying IApp from "
+ << "IAppBundle->createInstalledApp return value: " << hr;
+ } else {
+ *app = temp_app.Detach();
+ }
+ return hr;
+}
+
+HRESULT GetAppHostApValue(IGoogleUpdate3* update3,
+ IAppBundle* app_bundle,
+ BSTR* ap_value) {
+ base::win::ScopedComPtr<IApp> app;
+ HRESULT hr = CreateInstalledApp(app_bundle, kAppHostAppId, app.Receive());
+ if (FAILED(hr))
+ return hr;
+
+ hr = app->get_ap(ap_value);
+ if (FAILED(hr))
+ LOG(ERROR) << "Failed to get the App Launcher AP value.";
+ return hr;
+}
+
+HRESULT GetCurrentState(IApp* app,
+ ICurrentState** current_state,
+ CurrentState* state_value) {
+ base::win::ScopedComPtr<IDispatch> idispatch;
+ HRESULT hr = app->get_currentState(idispatch.Receive());
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to get App Bundle state: " << hr;
+ return hr;
+ }
+
+ base::win::ScopedComPtr<ICurrentState> temp_current_state;
+ hr = temp_current_state.QueryFrom(idispatch);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Unexpected error querying ICurrentState from "
+ << "IApp::get_currentState return value: " << hr;
+ return hr;
+ }
+
+ LONG long_state_value;
+ hr = temp_current_state->get_stateValue(&long_state_value);
+ if (SUCCEEDED(hr)) {
+ *state_value = static_cast<CurrentState>(long_state_value);
+ *current_state = temp_current_state.Detach();
+ } else {
+ LOG(ERROR) << "Failed to get App Bundle state value: " << hr;
+ }
+ return hr;
+}
+
+bool CheckIsBusy(IAppBundle* app_bundle, HRESULT* hr) {
+ VARIANT_BOOL variant_is_busy = VARIANT_TRUE;
+ *hr = app_bundle->isBusy(&variant_is_busy);
+ if (FAILED(*hr))
+ LOG(ERROR) << "Failed to check app_bundle->isBusy: " << *hr;
+ return (variant_is_busy == VARIANT_TRUE);
+}
+
+void OnUpdateAvailable(IAppBundle* app_bundle, HRESULT* hr) {
+ // If the app bundle is busy we will just wait some more.
+ if (CheckIsBusy(app_bundle, hr) || FAILED(*hr))
+ return;
+ *hr = app_bundle->download();
+ if (FAILED(*hr))
+ LOG(ERROR) << "Failed to initiate bundle download: " << *hr;
+}
+
+void OnReadyToInstall(IAppBundle* app_bundle, HRESULT* hr) {
+ // If the app bundle is busy we will just wait some more.
+ if (CheckIsBusy(app_bundle, hr) || FAILED(*hr))
+ return;
+ *hr = app_bundle->install();
+ if (FAILED(*hr))
+ LOG(ERROR) << "Failed to initiate bundle install: " << *hr;
+}
+
+HRESULT OnError(ICurrentState* current_state) {
+ LONG error_code;
+ HRESULT hr = current_state->get_errorCode(&error_code);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to retrieve bundle error code: " << hr;
+ return hr;
+ }
+
+ base::win::ScopedBstr completion_message;
+ HRESULT completion_message_hr =
+ current_state->get_completionMessage(completion_message.Receive());
+ if (FAILED(completion_message_hr)) {
+ LOG(ERROR) << "Bundle installation failed with error " << error_code
+ << ". Error message retrieval failed with error: "
+ << completion_message_hr;
+ } else {
+ LOG(ERROR) << "Bundle installation failed with error " << error_code << ": "
+ << completion_message;
+ }
+ return error_code;
+}
+
+HRESULT CreateGoogleUpdate3(IGoogleUpdate3** update3) {
+ base::win::ScopedComPtr<IGoogleUpdate3> temp_update3;
+ HRESULT hr = temp_update3.CreateInstance(CLSID_GoogleUpdate3UserClass);
+ if (SUCCEEDED(hr)) {
+ *update3 = temp_update3.Detach();
+ } else {
+ // TODO(erikwright): Try in-proc to support running elevated? According
+ // to update3_utils.cc (CreateGoogleUpdate3UserClass):
+ // The primary reason for the LocalServer activation failing on Vista/Win7
+ // is that COM does not look at HKCU registration when the code is running
+ // elevated. We fall back to an in-proc mode. The in-proc mode is limited to
+ // one install at a time, so we use it only as a backup mechanism.
+ LOG(ERROR) << "Failed to instantiate GoogleUpdate3: " << hr;
+ }
+ return hr;
+}
+
+HRESULT CreateAppBundle(IGoogleUpdate3* update3, IAppBundle** app_bundle) {
+ base::win::ScopedComPtr<IDispatch> idispatch;
+ HRESULT hr = update3->createAppBundle(idispatch.Receive());
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to createAppBundle: " << hr;
+ return hr;
+ }
+
+ base::win::ScopedComPtr<IAppBundle> temp_app_bundle;
+ hr = temp_app_bundle.QueryFrom(idispatch);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Unexpected error querying IAppBundle from "
+ << "IGoogleUpdate3->createAppBundle return value: " << hr;
+ return hr;
+ }
+
+ hr = temp_app_bundle->initialize();
+ if (FAILED(hr))
+ LOG(ERROR) << "Failed to initialize App Bundle: " << hr;
+ else
+ *app_bundle = temp_app_bundle.Detach();
+ return hr;
+}
+
+HRESULT SelectBinariesApValue(IGoogleUpdate3* update3,
+ IAppBundle* app_bundle,
+ BSTR* ap_value) {
+ HRESULT hr = GetAppHostApValue(update3, app_bundle, ap_value);
+ if (SUCCEEDED(hr))
+ return hr;
+
+ // TODO(erikwright): distinguish between AppHost not installed and an
+ // error in GetAppHostApValue.
+ // TODO(erikwright): Use stable by default when App Host support is in
+ // stable.
+ base::win::ScopedBstr temp_ap_value;
+ if (temp_ap_value.Allocate(L"2.0-dev-multi-apphost") == NULL) {
+ LOG(ERROR) << "Unexpected error in ScopedBstr::Allocate.";
+ return E_FAIL;
+ }
+ *ap_value = temp_ap_value.Release();
+ return S_OK;
+}
+
+HRESULT CreateBinariesIApp(IAppBundle* app_bundle, BSTR ap, IApp** app) {
+ base::win::ScopedComPtr<IDispatch> idispatch;
+ HRESULT hr = app_bundle->createApp(base::win::ScopedBstr(kBinariesAppId),
+ idispatch.Receive());
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to configure App Bundle: " << hr;
+ return hr;
+ }
+
+ base::win::ScopedComPtr<IApp> temp_app;
+ hr = temp_app.QueryFrom(idispatch);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Unexpected error querying IApp from "
+ << "IAppBundle->createApp return value: " << hr;
+ return hr;
+ }
+
+ hr = temp_app->put_isEulaAccepted(VARIANT_TRUE);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to set 'EULA Accepted': " << hr;
+ return hr;
+ }
+
+ hr = temp_app->put_ap(ap);
+ if (FAILED(hr))
+ LOG(ERROR) << "Failed to set AP value: " << hr;
+ else
+ *app = temp_app.Detach();
+ return hr;
+}
+
+bool CheckIfDone(IAppBundle* app_bundle, IApp* app, HRESULT* hr) {
+ base::win::ScopedComPtr<ICurrentState> current_state;
+ CurrentState state_value;
+ *hr = GetCurrentState(app, current_state.Receive(), &state_value);
+ if (FAILED(*hr))
+ return true;
+
+ switch (state_value) {
+ case STATE_WAITING_TO_CHECK_FOR_UPDATE:
+ case STATE_CHECKING_FOR_UPDATE:
+ case STATE_WAITING_TO_DOWNLOAD:
+ case STATE_RETRYING_DOWNLOAD:
+ case STATE_DOWNLOADING:
+ case STATE_WAITING_TO_INSTALL:
+ case STATE_INSTALLING:
+ case STATE_DOWNLOAD_COMPLETE:
+ case STATE_EXTRACTING:
+ case STATE_APPLYING_DIFFERENTIAL_PATCH:
+ // These states will all transition on their own.
+ return false;
+
+ case STATE_UPDATE_AVAILABLE:
+ OnUpdateAvailable(app_bundle, hr);
+ return FAILED(*hr);
+
+ case STATE_READY_TO_INSTALL:
+ OnReadyToInstall(app_bundle, hr);
+ return FAILED(*hr);
+
+ case STATE_NO_UPDATE:
+ LOG(INFO) << "Google Update reports that the binaries are already "
+ << "installed and up-to-date.";
+ return true;
+
+ case STATE_INSTALL_COMPLETE:
+ return true;
+
+ case STATE_ERROR:
+ *hr = OnError(current_state);
+ return FAILED(*hr);
+
+ case STATE_INIT:
+ case STATE_PAUSED:
+ default:
+ LOG(ERROR) << "Unexpected bundle state: " << state_value << ".";
+ *hr = E_FAIL;
+ return true;
+ }
+}
+
+} // namespace
+
+
+// Globals --------------------------------------------------------------------
+
+HRESULT InstallBinaries() {
+ base::win::ScopedCOMInitializer initialize_com;
+ if (!initialize_com.succeeded()) {
+ LOG(ERROR) << "COM initialization failed";
+ return E_FAIL;
+ }
+
+ base::win::ScopedComPtr<IGoogleUpdate3> update3;
+ HRESULT hr = CreateGoogleUpdate3(update3.Receive());
+ if (FAILED(hr))
+ return hr;
+
+ base::win::ScopedComPtr<IAppBundle> app_bundle;
+ hr = CreateAppBundle(update3, app_bundle.Receive());
+ if (FAILED(hr))
+ return hr;
+
+ base::win::ScopedBstr ap_value;
+ hr = SelectBinariesApValue(update3, app_bundle, ap_value.Receive());
+ if (FAILED(hr))
+ return hr;
+
+ base::win::ScopedComPtr<IApp> app;
+ hr = CreateBinariesIApp(app_bundle, ap_value, app.Receive());
+ if (FAILED(hr))
+ return hr;
+
+ hr = app_bundle->checkForUpdate();
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to initiate update check: " << hr;
+ return hr;
+ }
+
+ // We rely upon Omaha to eventually time out and transition to a failure
+ // state.
+ while (!CheckIfDone(app_bundle, app, &hr)) {
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
+ kInstallationPollingIntervalMs));
+ }
+ return hr;
+}
+
+} // namespace app_host
diff --git a/apps/app_host/binaries_installer.h b/apps/app_host/binaries_installer.h
new file mode 100644
index 0000000..8c70146
--- /dev/null
+++ b/apps/app_host/binaries_installer.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2012 The Chromium 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 APPS_APP_HOST_BINARIES_INSTALLER_H_
+#define APPS_APP_HOST_BINARIES_INSTALLER_H_
+
+#include <windows.h>
+
+namespace app_host {
+
+// Attempts to install the Chrome Binaries. Blocks until the installation
+// process is complete. The AP value, if any, from the currently installed App
+// Host will be used.
+HRESULT InstallBinaries();
+
+} // namespace app_host
+
+#endif // APPS_APP_HOST_BINARIES_INSTALLER_H_
diff --git a/apps/app_host/update.cc b/apps/app_host/update.cc
new file mode 100644
index 0000000..e8b14be8
--- /dev/null
+++ b/apps/app_host/update.cc
@@ -0,0 +1,102 @@
+// Copyright (c) 2012 The Chromium 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 "apps/app_host/update.h"
+
+#include <windows.h>
+#include "base/command_line.h"
+#include "base/file_version_info.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/process_util.h"
+#include "base/string16.h"
+#include "base/string_util.h"
+#include "base/version.h"
+#include "base/win/registry.h"
+#include "chrome/installer/launcher_support/chrome_launcher_support.h"
+
+namespace app_host {
+
+namespace {
+
+// TODO(huangs) Refactor the constants: http://crbug.com/148538
+const wchar_t kGoogleRegClientsKey[] = L"Software\\Google\\Update\\Clients\\";
+
+// Copied from util_constants.cc.
+const char kMultiInstall[] = "multi-install";
+const char kChromeAppHost[] = "app-host";
+const char kVerboseLogging[] = "verbose-logging";
+
+// Copied from google_update_constants.cc.
+const wchar_t kRegVersionField[] = L"pv";
+
+// Copied from chrome_appid.cc.
+const wchar_t kBinariesAppGuid[] = L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}";
+
+// Copied from google_chrome_distribution.cc.
+const wchar_t kBrowserAppGuid[] = L"{8A69D345-D564-463c-AFF1-A69D9E530F96}";
+
+// Fetches the version of the App Host, directly from the image's version
+// resource.
+Version GetAppHostVersion() {
+ scoped_ptr<FileVersionInfo> version_info(
+ FileVersionInfo::CreateFileVersionInfoForCurrentModule());
+ Version app_host_version(WideToASCII(version_info->product_version()));
+ DCHECK(app_host_version.IsValid());
+ return app_host_version;
+}
+
+// Fetches the app version ("pv" entry) of a Google product from the
+// system-level registry, given the app GUID ("{###...###}").
+Version GetAppVersionFromRegistry(const wchar_t* app_guid) {
+ HKEY root_key = HKEY_LOCAL_MACHINE;
+ string16 client_key(kGoogleRegClientsKey);
+ client_key.append(app_guid);
+ base::win::RegKey reg_key;
+ string16 version_str;
+ if ((reg_key.Open(root_key, client_key.c_str(),
+ KEY_QUERY_VALUE) == ERROR_SUCCESS) &&
+ (reg_key.ReadValue(kRegVersionField, &version_str) == ERROR_SUCCESS)) {
+ return Version(WideToASCII(version_str));
+ }
+ return Version();
+}
+
+// Calls setup.exe to update App Host, using the system-level setup.exe.
+bool LaunchAppHostUpdate() {
+ // Get the path to the setup.exe.
+ base::FilePath setup_exe(
+ chrome_launcher_support::GetSetupExeForInstallationLevel(
+ chrome_launcher_support::SYSTEM_LEVEL_INSTALLATION));
+ if (setup_exe.empty()) {
+ LOG(ERROR) << "Failed to find setup.exe";
+ return false;
+ }
+ CommandLine cmd_line(setup_exe);
+ cmd_line.AppendSwitch(kMultiInstall);
+ cmd_line.AppendSwitch(kChromeAppHost);
+ cmd_line.AppendSwitch(kVerboseLogging);
+ LOG(INFO) << "Launching: " << cmd_line.GetCommandLineString();
+ return base::LaunchProcess(cmd_line, base::LaunchOptions(), NULL);
+}
+
+} // namespace
+
+void EnsureAppHostUpToDate() {
+ // Check version from Chrome Binaries first, then Chrome (all system-level).
+ Version new_version(GetAppVersionFromRegistry(kBinariesAppGuid));
+ if (!new_version.IsValid())
+ new_version = GetAppVersionFromRegistry(kBrowserAppGuid);
+ if (!new_version.IsValid())
+ return; // Not an error: System-level Chrome might not be installed.
+ Version app_host_version(GetAppHostVersion());
+ if (app_host_version.CompareTo(new_version) < 0) {
+ LOG(INFO) << "Updating App Launcher from " << app_host_version.GetString()
+ << " to " << new_version.GetString();
+ if (!LaunchAppHostUpdate())
+ LOG(ERROR) << "Failed to launch App Launcher update.";
+ }
+}
+
+} // namespace app_host
diff --git a/apps/app_host/update.h b/apps/app_host/update.h
new file mode 100644
index 0000000..b72c985
--- /dev/null
+++ b/apps/app_host/update.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2012 The Chromium 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 APPS_APP_HOST_UPDATE_H_
+#define APPS_APP_HOST_UPDATE_H_
+
+namespace app_host {
+
+// If system-level Chrome Binary is installed, and if its version is
+// newer than App Host's, then udpate App Host by calling setup.exe.
+void EnsureAppHostUpToDate();
+
+} // namespace app_host
+
+#endif // APPS_APP_HOST_UPDATE_H_
diff --git a/apps/apps.gypi b/apps/apps.gypi
index 257195d..76bca7e 100644
--- a/apps/apps.gypi
+++ b/apps/apps.gypi
@@ -44,4 +44,43 @@
'msvs_disabled_warnings': [ 4267, ],
},
],
+ 'conditions': [
+ ['OS=="win"', {
+ 'targets': [
+ {
+ 'target_name': 'app_host',
+ 'type': 'executable',
+ 'include_dirs': [
+ '..',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '..',
+ ],
+ },
+ 'dependencies': [
+ '<(DEPTH)/base/base.gyp:base',
+ '<(DEPTH)/chrome/chrome.gyp:chrome_version_resources',
+ '<(DEPTH)/chrome/chrome.gyp:launcher_support',
+ '<(DEPTH)/google_update/google_update.gyp:google_update',
+ ],
+ 'sources': [
+ 'app_host/app_host.rc',
+ 'app_host/app_host_main.cc',
+ 'app_host/app_host_resource.h',
+ 'app_host/binaries_installer.cc',
+ 'app_host/binaries_installer.h',
+ 'app_host/update.cc',
+ 'app_host/update.h',
+ '<(SHARED_INTERMEDIATE_DIR)/chrome_version/app_host_exe_version.rc',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'SubSystem': '2', # Set /SUBSYSTEM:WINDOWS
+ },
+ },
+ },
+ ],
+ },], # 'OS=="win"'
+ ], # 'conditions'
}