Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Unified Diff: chrome/browser/google/google_update_win.cc

Issue 729273002: Modernize on-demand update checks on Windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comments Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/google/google_update_win.cc
diff --git a/chrome/browser/google/google_update_win.cc b/chrome/browser/google/google_update_win.cc
index adeb33c8f729d951267472dfaec3b6f3f0bc6457..97920cd435f787993fc26f7dbe7a7becac530fc0 100644
--- a/chrome/browser/google/google_update_win.cc
+++ b/chrome/browser/google/google_update_win.cc
@@ -8,15 +8,16 @@
#include <atlcom.h>
#include "base/bind.h"
+#include "base/callback.h"
#include "base/files/file_path.h"
-#include "base/message_loop/message_loop.h"
+#include "base/location.h"
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "base/threading/thread.h"
-#include "base/win/scoped_comptr.h"
+#include "base/task_runner.h"
+#include "base/thread_task_runner_handle.h"
#include "base/win/windows_version.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/installer/util/browser_distribution.h"
@@ -24,25 +25,24 @@
#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/install_util.h"
#include "content/public/browser/browser_thread.h"
-#include "google_update/google_update_idl.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/win/atl_module.h"
-#include "ui/views/widget/widget.h"
-
-using content::BrowserThread;
namespace {
+internal::OnDemandAppsClassFactory* g_google_update_factory = nullptr;
+
// Check if the currently running instance can be updated by Google Update.
// Returns GOOGLE_UPDATE_NO_ERROR only if the instance running is a Google
// Chrome distribution installed in a standard location.
GoogleUpdateErrorCode CanUpdateCurrentChrome(
- const base::FilePath& chrome_exe_path) {
+ const base::FilePath& chrome_exe_path,
+ bool system_level) {
#if !defined(GOOGLE_CHROME_BUILD)
return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY;
#else
- // TODO(tommi): Check if using the default distribution is always the right
- // thing to do.
+ DCHECK_NE(InstallUtil::IsPerUserInstall(chrome_exe_path.value().c_str()),
+ system_level);
BrowserDistribution* dist = BrowserDistribution::GetDistribution();
base::FilePath user_exe_path = installer::GetChromeInstallPath(false, dist);
base::FilePath machine_exe_path = installer::GetChromeInstallPath(true, dist);
@@ -50,16 +50,10 @@ GoogleUpdateErrorCode CanUpdateCurrentChrome(
user_exe_path.value()) &&
!base::FilePath::CompareEqualIgnoreCase(chrome_exe_path.value(),
machine_exe_path.value())) {
- LOG(ERROR) << L"Google Update cannot update Chrome installed in a "
- << L"non-standard location: " << chrome_exe_path.value().c_str()
- << L". The standard location is: "
- << user_exe_path.value().c_str()
- << L" or " << machine_exe_path.value().c_str() << L".";
return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY;
}
- base::string16 app_guid = installer::GetAppGuidForUpdates(
- !InstallUtil::IsPerUserInstall(chrome_exe_path.value().c_str()));
+ base::string16 app_guid = installer::GetAppGuidForUpdates(system_level);
DCHECK(!app_guid.empty());
GoogleUpdateSettings::UpdatePolicy update_policy =
@@ -88,7 +82,7 @@ HRESULT CoCreateInstanceAsAdmin(REFCLSID class_id, REFIID interface_id,
// For Vista, need to instantiate the COM server via the elevation
// moniker. This ensures that the UAC dialog shows up.
if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
- wchar_t class_id_as_string[MAX_PATH] = {0};
+ wchar_t class_id_as_string[MAX_PATH] = {};
StringFromGUID2(class_id, class_id_as_string,
arraysize(class_id_as_string));
@@ -96,125 +90,99 @@ HRESULT CoCreateInstanceAsAdmin(REFCLSID class_id, REFIID interface_id,
base::StringPrintf(L"Elevation:Administrator!new:%ls",
class_id_as_string);
- BIND_OPTS3 bind_opts;
- memset(&bind_opts, 0, sizeof(bind_opts));
+ BIND_OPTS3 bind_opts = {};
bind_opts.cbStruct = sizeof(bind_opts);
bind_opts.dwClassContext = CLSCTX_LOCAL_SERVER;
bind_opts.hwnd = hwnd;
- return CoGetObject(elevation_moniker_name.c_str(), &bind_opts,
- interface_id, reinterpret_cast<void**>(interface_ptr));
+ return CoGetObject(elevation_moniker_name.c_str(), &bind_opts, interface_id,
+ interface_ptr);
}
- return CoCreateInstance(class_id, NULL, CLSCTX_LOCAL_SERVER,
- interface_id,
- reinterpret_cast<void**>(interface_ptr));
+ return CoCreateInstance(class_id, NULL, CLSCTX_LOCAL_SERVER, interface_id,
+ interface_ptr);
}
+HRESULT CreateOnDemandAppsClass(
+ bool system_level,
+ bool install_if_newer,
+ HWND elevation_window,
+ base::win::ScopedComPtr<IGoogleUpdate>* on_demand) {
+ if (g_google_update_factory)
+ return g_google_update_factory->Run(on_demand);
+
+ // For a user-level install, update checks and updates can both be done by a
+ // normal user with the UserAppsClass.
+ if (!system_level)
+ return on_demand->CreateInstance(CLSID_OnDemandUserAppsClass);
+
+ // For a system-level install, update checks can be done by a normal user with
+ // the MachineAppsClass.
+ if (!install_if_newer)
+ return on_demand->CreateInstance(CLSID_OnDemandMachineAppsClass);
-} // namespace
+ // For a system-level install, an update requires Admin privileges for writing
+ // to %ProgramFiles%. Elevate while instantiating the MachineAppsClass.
+ return CoCreateInstanceAsAdmin(CLSID_OnDemandMachineAppsClass,
+ IID_IGoogleUpdate, elevation_window,
+ on_demand->ReceiveVoid());
+}
// The GoogleUpdateJobObserver COM class is responsible for receiving status
-// reports from google Update. It keeps track of the progress as GoogleUpdate
-// notifies this observer and ends the message loop that is spinning in once
-// GoogleUpdate reports that it is done.
-class GoogleUpdateJobObserver
- : public CComObjectRootEx<CComSingleThreadModel>,
- public IJobObserver {
+// reports from google Update. It keeps track of the progress as Google Update
+// notifies this observer and runs a completion callback once Google Update
+// reports that it is done.
+class GoogleUpdateJobObserver : public CComObjectRootEx<CComSingleThreadModel>,
Peter Kasting 2014/11/26 22:13:05 Nit: Because this file has several classes in it,
grt (UTC plus 2) 2014/11/27 04:44:57 git cl format doesn't like the extra blank line. :
Peter Kasting 2014/11/27 08:07:34 I prefer that people not run git cl format at all.
+ public IJobObserver {
public:
BEGIN_COM_MAP(GoogleUpdateJobObserver)
COM_INTERFACE_ENTRY(IJobObserver)
END_COM_MAP()
- GoogleUpdateJobObserver()
- : result_(UPGRADE_ERROR) {
- }
- virtual ~GoogleUpdateJobObserver() {}
+ GoogleUpdateJobObserver();
+ virtual ~GoogleUpdateJobObserver();
- // Notifications from Google Update:
- STDMETHOD(OnShow)() {
- return S_OK;
- }
- STDMETHOD(OnCheckingForUpdate)() {
- result_ = UPGRADE_CHECK_STARTED;
- return S_OK;
- }
- STDMETHOD(OnUpdateAvailable)(const TCHAR* version_string) {
- result_ = UPGRADE_IS_AVAILABLE;
- new_version_ = version_string;
- return S_OK;
- }
- STDMETHOD(OnWaitingToDownload)() {
- return S_OK;
- }
- STDMETHOD(OnDownloading)(int time_remaining_ms, int pos) {
- return S_OK;
- }
- STDMETHOD(OnWaitingToInstall)() {
- return S_OK;
- }
- STDMETHOD(OnInstalling)() {
- result_ = UPGRADE_STARTED;
- return S_OK;
- }
- STDMETHOD(OnPause)() {
- return S_OK;
- }
- STDMETHOD(OnComplete)(LegacyCompletionCodes code, const TCHAR* text) {
- switch (code) {
- case COMPLETION_CODE_SUCCESS_CLOSE_UI:
- case COMPLETION_CODE_SUCCESS: {
- if (result_ == UPGRADE_STARTED)
- result_ = UPGRADE_SUCCESSFUL;
- else if (result_ == UPGRADE_CHECK_STARTED)
- result_ = UPGRADE_ALREADY_UP_TO_DATE;
- break;
- }
- case COMPLETION_CODE_ERROR:
- error_message_ = text;
- default: {
- NOTREACHED();
- result_ = UPGRADE_ERROR;
- break;
- }
- }
-
- event_sink_ = NULL;
-
- // No longer need to spin the message loop that started spinning in
- // InitiateGoogleUpdateCheck.
- base::MessageLoop::current()->Quit();
- return S_OK;
- }
- STDMETHOD(SetEventSink)(IProgressWndEvents* event_sink) {
- event_sink_ = event_sink;
- return S_OK;
+ // Sets the callback to be invoked when Google Update reports that the job is
+ // done.
+ void set_on_complete_callback(const base::Closure& on_complete_callback) {
+ on_complete_callback_ = on_complete_callback;
}
// Returns the results of the update operation.
- STDMETHOD(GetResult)(GoogleUpdateUpgradeResult* result) {
+ GoogleUpdateUpgradeResult result() const {
// Intermediary steps should never be reported to the client.
- DCHECK(result_ != UPGRADE_STARTED && result_ != UPGRADE_CHECK_STARTED);
-
- *result = result_;
- return S_OK;
+ DCHECK_NE(result_, UPGRADE_STARTED);
+ DCHECK_NE(result_, UPGRADE_CHECK_STARTED);
Peter Kasting 2014/11/26 22:13:05 Nit: (expected, actual) for DCHECK_NE/EQ
grt (UTC plus 2) 2014/11/27 04:44:57 Is this for consistency with Google Tests's EXPECT
Peter Kasting 2014/11/27 08:07:34 Yes, that's why we instituted that practice. (We
+ return result_;
}
// Returns which version Google Update found on the server (if a more
// recent version was found). Otherwise, this will be blank.
- STDMETHOD(GetVersionInfo)(base::string16* version_string) {
- *version_string = new_version_;
- return S_OK;
- }
+ base::string16 new_version() const { return new_version_; }
// Returns the Google Update supplied error string that describes the error
// that occurred during the update check/upgrade.
- STDMETHOD(GetErrorMessage)(base::string16* error_message) {
- *error_message = error_message_;
- return S_OK;
- }
+ base::string16 error_message() const { return error_message_; }
private:
+ // IJobObserver:
+ STDMETHOD(OnShow)();
+ STDMETHOD(OnCheckingForUpdate)();
+ STDMETHOD(OnUpdateAvailable)(const TCHAR* version_string);
+ STDMETHOD(OnWaitingToDownload)();
+ STDMETHOD(OnDownloading)(int time_remaining_ms, int pos);
+ STDMETHOD(OnWaitingToInstall)();
+ STDMETHOD(OnInstalling)();
+ STDMETHOD(OnPause)();
+ STDMETHOD(OnComplete)(LegacyCompletionCodes code, const TCHAR* text);
+ STDMETHOD(SetEventSink)(IProgressWndEvents* event_sink);
+
+ // The task runner associated with the thread in which the job runs.
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ // A callback to be run to complete processing;
+ base::Closure on_complete_callback_;
+
// The status/result of the Google Update operation.
GoogleUpdateUpgradeResult result_;
@@ -227,195 +195,320 @@ class GoogleUpdateJobObserver
// Allows us control the upgrade process to a small degree. After OnComplete
// has been called, this object can not be used.
base::win::ScopedComPtr<IProgressWndEvents> event_sink_;
+
+ DISALLOW_COPY_AND_ASSIGN(GoogleUpdateJobObserver);
};
-////////////////////////////////////////////////////////////////////////////////
-// GoogleUpdate, public:
+GoogleUpdateJobObserver::GoogleUpdateJobObserver()
+ : task_runner_(base::ThreadTaskRunnerHandle::Get()),
+ result_(UPGRADE_ERROR) {
+}
+
+GoogleUpdateJobObserver::~GoogleUpdateJobObserver() {
+}
+
+STDMETHODIMP GoogleUpdateJobObserver::OnShow() {
+ return S_OK;
+}
+
+STDMETHODIMP GoogleUpdateJobObserver::OnCheckingForUpdate() {
+ result_ = UPGRADE_CHECK_STARTED;
+ return S_OK;
+}
+
+STDMETHODIMP GoogleUpdateJobObserver::OnUpdateAvailable(
+ const TCHAR* version_string) {
+ result_ = UPGRADE_IS_AVAILABLE;
+ new_version_ = version_string;
+ return S_OK;
+}
+
+STDMETHODIMP GoogleUpdateJobObserver::OnWaitingToDownload() {
+ return S_OK;
+}
+
+STDMETHODIMP GoogleUpdateJobObserver::OnDownloading(int time_remaining_ms,
+ int pos) {
+ return S_OK;
+}
+
+STDMETHODIMP GoogleUpdateJobObserver::OnWaitingToInstall() {
+ return S_OK;
+}
+
+STDMETHODIMP GoogleUpdateJobObserver::OnInstalling() {
+ result_ = UPGRADE_STARTED;
+ return S_OK;
+}
+
+STDMETHODIMP GoogleUpdateJobObserver::OnPause() {
+ return S_OK;
+}
+
+STDMETHODIMP GoogleUpdateJobObserver::OnComplete(LegacyCompletionCodes code,
+ const TCHAR* text) {
+ if (code == COMPLETION_CODE_ERROR) {
+ error_message_ = text;
+ result_ = UPGRADE_ERROR;
+ } else {
+ // Everything that isn't an error is some form of success. Chrome doesn't
+ // support any of the fancy codes (e.g., COMPLETION_CODE_REBOOT), but they
+ // shouldn't be generated anyway.
+ LOG_IF(DFATAL, (code != COMPLETION_CODE_SUCCESS &&
+ code != COMPLETION_CODE_SUCCESS_CLOSE_UI))
+ << "Unexpected LegacyCompletionCode from IGoogleUpdate: " << code;
+ if (result_ == UPGRADE_STARTED)
+ result_ = UPGRADE_SUCCESSFUL;
+ else if (result_ == UPGRADE_CHECK_STARTED)
+ result_ = UPGRADE_ALREADY_UP_TO_DATE;
+ }
+
+ event_sink_ = NULL;
+
+ task_runner_->PostTask(FROM_HERE, on_complete_callback_);
+ return S_OK;
+}
+
+STDMETHODIMP GoogleUpdateJobObserver::SetEventSink(
+ IProgressWndEvents* event_sink) {
+ event_sink_ = event_sink;
+ return S_OK;
+}
+
+// A driver that is created and destroyed on the caller's thread and drives
+// Google Update on another.
+class UpdateCheckDriver {
+ public:
+ // Runs an update check on |task_runner|, invoking |callback| on the caller's
+ // thread upon completion.
+ static void RunUpdateCheck(const scoped_refptr<base::TaskRunner>& task_runner,
+ bool install_if_newer,
+ HWND elevation_window,
+ const UpdateCheckCallback& callback);
+
+ private:
+ friend class base::DeleteHelper<UpdateCheckDriver>;
+
+ explicit UpdateCheckDriver(const UpdateCheckCallback& callback);
+
+ // Runs the caller's update check callback with the results of the operation.
+ ~UpdateCheckDriver();
+
+ // Starts an update check.
+ void BeginUpdateCheck(bool install_if_newer, HWND elevation_window);
+
+ // Helper function for starting an update check. Returns true if the check was
+ // properly started, in which case CompleteUpdateCheck will be invoked upon
+ // completion to return results to the caller on its own thread.
+ bool BeginUpdateCheckInternal(bool install_if_newer, HWND elevation_window);
+
+ // Invoked when results are in from Google Update.
+ void CompleteUpdateCheck();
+
+ // Prepares |results| to return the upgrade error indicated by |error_code|
+ // and |hr|. The string " -- system level" is included in the generated error
+ // message when |system_level| is true.
+ void OnUpgradeError(GoogleUpdateErrorCode error_code,
+ HRESULT hr,
+ bool system_level);
-GoogleUpdate::GoogleUpdate()
- : listener_(NULL) {
+ // The caller's task runner, on which |result_callback_| will be run.
+ scoped_refptr<base::SingleThreadTaskRunner> result_runner_;
+
+ // The caller's callback to be run when the update check is compelte.
+ UpdateCheckCallback result_callback_;
+
+ // The results of the update check.
+ GoogleUpdateUpgradeResult result_;
+ GoogleUpdateErrorCode error_code_;
+ base::string16 error_message_;
+ base::string16 version_;
+ HRESULT hresult_;
+
+ // A direct pointer to the job observer by which the driver is notified of
+ // interesting events from Google Update.
+ CComObject<GoogleUpdateJobObserver>* job_observer_;
+
+ // A scoped pointer to |job_observer_| that holds a reference to it, keeping
+ // it alive.
+ base::win::ScopedComPtr<IJobObserver> job_holder_;
+
+ // The on-demand updater that is doing the work.
+ base::win::ScopedComPtr<IGoogleUpdate> on_demand_;
+
+ DISALLOW_COPY_AND_ASSIGN(UpdateCheckDriver);
+};
+
+// static
+void UpdateCheckDriver::RunUpdateCheck(
+ const scoped_refptr<base::TaskRunner>& task_runner,
+ bool install_if_newer,
+ HWND elevation_window,
+ const UpdateCheckCallback& callback) {
+ // The driver is owned by itself, and will self-destruct when its work is
+ // done.
+ UpdateCheckDriver* driver = new UpdateCheckDriver(callback);
+ task_runner->PostTask(
+ FROM_HERE,
+ base::Bind(&UpdateCheckDriver::BeginUpdateCheck, base::Unretained(driver),
+ install_if_newer, elevation_window));
}
-GoogleUpdate::~GoogleUpdate() {
+// Runs on the caller's thread.
+UpdateCheckDriver::UpdateCheckDriver(const UpdateCheckCallback& callback)
+ : result_runner_(base::ThreadTaskRunnerHandle::Get()),
+ result_callback_(callback),
+ result_(UPGRADE_ERROR),
+ error_code_(GOOGLE_UPDATE_NO_ERROR),
+ hresult_(S_OK),
+ job_observer_(nullptr) {
}
-void GoogleUpdate::CheckForUpdate(bool install_if_newer, HWND window) {
- // Need to shunt this request over to InitiateGoogleUpdateCheck and have
- // it run in the file thread.
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&GoogleUpdate::InitiateGoogleUpdateCheck, this,
- install_if_newer, window, base::MessageLoop::current()));
+UpdateCheckDriver::~UpdateCheckDriver() {
+ DCHECK(result_runner_->BelongsToCurrentThread());
+ // If there is an error, then error_code must not be blank, and vice versa.
+ DCHECK_NE(result_ != UPGRADE_ERROR, error_code_ != GOOGLE_UPDATE_NO_ERROR);
Peter Kasting 2014/11/26 22:13:05 Nit: Please flip the "!="s to "=="s ... trying to
grt (UTC plus 2) 2014/11/27 04:44:57 Oops. I mis-read your previous comment. I wondered
+ UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.UpgradeResult", result_,
+ NUM_UPGRADE_RESULTS);
+ if (result_ == UPGRADE_ERROR) {
+ UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.UpdateErrorCode", error_code_,
+ NUM_ERROR_CODES);
+ if (hresult_ != S_OK)
+ UMA_HISTOGRAM_SPARSE_SLOWLY("GoogleUpdate.ErrorHresult", hresult_);
+ }
+ result_callback_.Run(result_, error_code_, error_message_, version_);
}
-////////////////////////////////////////////////////////////////////////////////
-// GoogleUpdate, private:
+void UpdateCheckDriver::BeginUpdateCheck(bool install_if_newer,
+ HWND elevation_window) {
+ // Return results immediately if the driver is not waiting for Google Update.
+ if (!BeginUpdateCheckInternal(install_if_newer, elevation_window))
+ result_runner_->DeleteSoon(FROM_HERE, this);
+}
-void GoogleUpdate::InitiateGoogleUpdateCheck(bool install_if_newer,
- HWND window,
- base::MessageLoop* main_loop) {
+bool UpdateCheckDriver::BeginUpdateCheckInternal(bool install_if_newer,
+ HWND elevation_window) {
base::FilePath chrome_exe;
if (!PathService::Get(base::DIR_EXE, &chrome_exe))
NOTREACHED();
- GoogleUpdateErrorCode error_code = CanUpdateCurrentChrome(chrome_exe);
- if (error_code != GOOGLE_UPDATE_NO_ERROR) {
- main_loop->PostTask(
- FROM_HERE,
- base::Bind(&GoogleUpdate::ReportResults, this,
- UPGRADE_ERROR, error_code, base::string16()));
- return;
+ const bool system_level =
+ !InstallUtil::IsPerUserInstall(chrome_exe.value().c_str());
+
+ // The failures handled here are:
+ // CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY,
+ // GOOGLE_UPDATE_DISABLED_BY_POLICY, and
+ // GOOGLE_UPDATE_DISABLED_BY_POLICY_AUTO_ONLY.
+ error_code_ = CanUpdateCurrentChrome(chrome_exe, system_level);
+ if (error_code_ != GOOGLE_UPDATE_NO_ERROR) {
+ // These failures are handled in the UX with custom messages.
+ result_ = UPGRADE_ERROR;
+ return false;
}
// Make sure ATL is initialized in this module.
ui::win::CreateATLModuleIfNeeded();
- CComObject<GoogleUpdateJobObserver>* job_observer;
HRESULT hr =
- CComObject<GoogleUpdateJobObserver>::CreateInstance(&job_observer);
+ CComObject<GoogleUpdateJobObserver>::CreateInstance(&job_observer_);
if (hr != S_OK) {
// Most of the error messages come straight from Google Update. This one is
// deemed worthy enough to also warrant its own error.
- GoogleUpdateErrorCode error = GOOGLE_UPDATE_JOB_SERVER_CREATION_FAILED;
- base::string16 error_code = base::StringPrintf(L"%d: 0x%x", error, hr);
- ReportFailure(
- hr, error,
- l10n_util::GetStringFUTF16(IDS_ABOUT_BOX_ERROR_UPDATE_CHECK_FAILED,
- error_code),
- main_loop);
- return;
+ OnUpgradeError(GOOGLE_UPDATE_JOB_SERVER_CREATION_FAILED, hr, false);
+ return false;
}
+ // Hold a reference on the observer for the lifetime of the driver.
+ job_holder_ = job_observer_;
- base::win::ScopedComPtr<IJobObserver> job_holder(job_observer);
-
- base::win::ScopedComPtr<IGoogleUpdate> on_demand;
-
- bool system_level = false;
-
- if (InstallUtil::IsPerUserInstall(chrome_exe.value().c_str())) {
- hr = on_demand.CreateInstance(CLSID_OnDemandUserAppsClass);
- } else {
- // The Update operation needs Admin privileges for writing
- // to %ProgramFiles%. On Vista, need to elevate before instantiating
- // the updater instance.
- if (!install_if_newer) {
- hr = on_demand.CreateInstance(CLSID_OnDemandMachineAppsClass);
- } else {
- hr = CoCreateInstanceAsAdmin(CLSID_OnDemandMachineAppsClass,
- IID_IGoogleUpdate, window,
- reinterpret_cast<void**>(on_demand.Receive()));
- }
- system_level = true;
- }
+ job_observer_->set_on_complete_callback(base::Bind(
+ &UpdateCheckDriver::CompleteUpdateCheck, base::Unretained(this)));
+ hr = CreateOnDemandAppsClass(system_level, install_if_newer, elevation_window,
+ &on_demand_);
if (hr != S_OK) {
- GoogleUpdateErrorCode error = GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND;
- base::string16 error_code = base::StringPrintf(L"%d: 0x%x", error, hr);
- if (system_level)
- error_code += L" -- system level";
- ReportFailure(hr, error,
- l10n_util::GetStringFUTF16(
- IDS_ABOUT_BOX_ERROR_UPDATE_CHECK_FAILED,
- error_code),
- main_loop);
- return;
+ OnUpgradeError(GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND, hr, system_level);
+ return false;
}
base::string16 app_guid = installer::GetAppGuidForUpdates(system_level);
DCHECK(!app_guid.empty());
- if (!install_if_newer)
- hr = on_demand->CheckForUpdate(app_guid.c_str(), job_observer);
+ if (install_if_newer)
+ hr = on_demand_->Update(app_guid.c_str(), job_observer_);
else
- hr = on_demand->Update(app_guid.c_str(), job_observer);
+ hr = on_demand_->CheckForUpdate(app_guid.c_str(), job_observer_);
if (hr != S_OK) {
- GoogleUpdateErrorCode error = GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR;
- base::string16 error_code = base::StringPrintf(L"%d: 0x%x", error, hr);
- ReportFailure(hr, error,
- l10n_util::GetStringFUTF16(
- IDS_ABOUT_BOX_ERROR_UPDATE_CHECK_FAILED,
- error_code),
- main_loop);
- return;
+ OnUpgradeError(GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR, hr,
+ system_level);
+ return false;
}
+ return true;
+}
- // Need to spin the message loop while Google Update is running so that it
- // can report back to us through GoogleUpdateJobObserver. This message loop
- // will terminate once Google Update sends us the completion status
- // (success/error). See OnComplete().
- base::MessageLoop::current()->Run();
+void UpdateCheckDriver::CompleteUpdateCheck() {
+ result_ = job_observer_->result();
+ if (result_ == UPGRADE_ERROR) {
+ error_code_ = GOOGLE_UPDATE_ERROR_UPDATING;
+ error_message_ = job_observer_->error_message();
+ } else {
+ version_ = job_observer_->new_version();
+ }
+ // Release the reference on the COM objects.
+ on_demand_ = nullptr;
+ job_observer_ = nullptr;
+ job_holder_ = nullptr;
- GoogleUpdateUpgradeResult results;
- hr = job_observer->GetResult(&results);
+ result_runner_->DeleteSoon(FROM_HERE, this);
+}
- if (hr != S_OK) {
- GoogleUpdateErrorCode error = GOOGLE_UPDATE_GET_RESULT_CALL_FAILED;
- base::string16 error_code = base::StringPrintf(L"%d: 0x%x", error, hr);
- ReportFailure(hr, error,
- l10n_util::GetStringFUTF16(
- IDS_ABOUT_BOX_ERROR_UPDATE_CHECK_FAILED,
- error_code),
- main_loop);
- return;
- }
+void UpdateCheckDriver::OnUpgradeError(GoogleUpdateErrorCode error_code,
+ HRESULT hr,
+ bool system_level) {
+ result_ = UPGRADE_ERROR;
+ error_code_ = error_code;
+ hresult_ = hr;
+ base::string16 error_msg =
+ base::StringPrintf(L"%d: 0x%x", error_code_, hresult_);
+ if (system_level)
+ error_msg += L" -- system level";
+ error_message_ = l10n_util::GetStringFUTF16(
+ IDS_ABOUT_BOX_ERROR_UPDATE_CHECK_FAILED, error_msg);
+}
- if (results == UPGRADE_ERROR) {
- base::string16 error_message;
- job_observer->GetErrorMessage(&error_message);
- ReportFailure(hr, GOOGLE_UPDATE_ERROR_UPDATING, error_message, main_loop);
- return;
- }
+} // namespace
- hr = job_observer->GetVersionInfo(&version_available_);
- if (hr != S_OK) {
- GoogleUpdateErrorCode error = GOOGLE_UPDATE_GET_VERSION_INFO_FAILED;
- base::string16 error_code = base::StringPrintf(L"%d: 0x%x", error, hr);
- ReportFailure(hr, error,
- l10n_util::GetStringFUTF16(
- IDS_ABOUT_BOX_ERROR_UPDATE_CHECK_FAILED,
- error_code),
- main_loop);
- return;
- }
+void CheckForUpdate(bool install_if_newer,
+ HWND elevation_window,
+ const UpdateCheckCallback& callback) {
+ scoped_refptr<base::TaskRunner> task_runner(
+ content::BrowserThread::GetMessageLoopProxyForThread(
+ content::BrowserThread::FILE));
- main_loop->PostTask(
- FROM_HERE,
- base::Bind(&GoogleUpdate::ReportResults, this,
- results, GOOGLE_UPDATE_NO_ERROR, base::string16()));
- job_holder = NULL;
- on_demand = NULL;
+ internal::CheckForUpdate(task_runner, install_if_newer, elevation_window,
+ callback);
}
-void GoogleUpdate::ReportResults(GoogleUpdateUpgradeResult results,
- GoogleUpdateErrorCode error_code,
- const base::string16& error_message) {
- // If there is an error, then error code must not be blank, and vice versa.
- DCHECK(results == UPGRADE_ERROR ? error_code != GOOGLE_UPDATE_NO_ERROR :
- error_code == GOOGLE_UPDATE_NO_ERROR);
- UMA_HISTOGRAM_ENUMERATION(
- "GoogleUpdate.UpgradeResult", results, NUM_UPGRADE_RESULTS);
- if (results == UPGRADE_ERROR) {
- UMA_HISTOGRAM_ENUMERATION(
- "GoogleUpdate.UpdateErrorCode", error_code, NUM_ERROR_CODES);
+namespace internal {
+
+void SetGoogleUpdateFactory(
+ const OnDemandAppsClassFactory& google_update_factory) {
+ if (g_google_update_factory) {
+ delete g_google_update_factory;
+ g_google_update_factory = nullptr;
}
- if (listener_) {
- listener_->OnReportResults(
- results, error_code, error_message, version_available_);
+ if (!google_update_factory.is_null()) {
+ g_google_update_factory =
+ new OnDemandAppsClassFactory(google_update_factory);
}
}
-bool GoogleUpdate::ReportFailure(HRESULT hr,
- GoogleUpdateErrorCode error_code,
- const base::string16& error_message,
- base::MessageLoop* main_loop) {
- DLOG(ERROR) << "Communication with Google Update failed: " << hr
- << " error: " << error_code
- << ", message: " << error_message.c_str();
- UMA_HISTOGRAM_SPARSE_SLOWLY("GoogleUpdate.ErrorHresult", hr);
- main_loop->PostTask(
- FROM_HERE,
- base::Bind(&GoogleUpdate::ReportResults, this,
- UPGRADE_ERROR, error_code, error_message));
- return false;
+void CheckForUpdate(const scoped_refptr<base::TaskRunner>& task_runner,
+ bool install_if_newer,
+ HWND elevation_window,
+ const UpdateCheckCallback& callback) {
+ UpdateCheckDriver::RunUpdateCheck(task_runner, install_if_newer,
+ elevation_window, callback);
}
+
+} // namespace internal

Powered by Google App Engine
This is Rietveld 408576698