Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / google / google_update_win.cc
blob791279a8cbfade3198e3f6417e2212043b3aa9b6
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/google/google_update_win.h"
7 #include <atlbase.h>
8 #include <atlcom.h>
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/files/file_path.h"
13 #include "base/location.h"
14 #include "base/metrics/histogram.h"
15 #include "base/metrics/sparse_histogram.h"
16 #include "base/path_service.h"
17 #include "base/strings/string_util.h"
18 #include "base/strings/stringprintf.h"
19 #include "base/task_runner.h"
20 #include "base/thread_task_runner_handle.h"
21 #include "base/win/windows_version.h"
22 #include "chrome/grit/generated_resources.h"
23 #include "chrome/installer/util/browser_distribution.h"
24 #include "chrome/installer/util/google_update_settings.h"
25 #include "chrome/installer/util/helper.h"
26 #include "chrome/installer/util/install_util.h"
27 #include "content/public/browser/browser_thread.h"
28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/base/win/atl_module.h"
31 namespace {
33 OnDemandAppsClassFactory* g_google_update_factory = nullptr;
35 // Check if the currently running instance can be updated by Google Update.
36 // Returns GOOGLE_UPDATE_NO_ERROR only if the instance running is a Google
37 // Chrome distribution installed in a standard location.
38 GoogleUpdateErrorCode CanUpdateCurrentChrome(
39 const base::FilePath& chrome_exe_path,
40 bool system_level) {
41 #if !defined(GOOGLE_CHROME_BUILD)
42 return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY;
43 #else
44 DCHECK_NE(InstallUtil::IsPerUserInstall(chrome_exe_path), system_level);
45 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
46 base::FilePath user_exe_path = installer::GetChromeInstallPath(false, dist);
47 base::FilePath machine_exe_path = installer::GetChromeInstallPath(true, dist);
48 if (!base::FilePath::CompareEqualIgnoreCase(chrome_exe_path.value(),
49 user_exe_path.value()) &&
50 !base::FilePath::CompareEqualIgnoreCase(chrome_exe_path.value(),
51 machine_exe_path.value())) {
52 return CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY;
55 base::string16 app_guid = installer::GetAppGuidForUpdates(system_level);
56 DCHECK(!app_guid.empty());
58 GoogleUpdateSettings::UpdatePolicy update_policy =
59 GoogleUpdateSettings::GetAppUpdatePolicy(app_guid, NULL);
61 if (update_policy == GoogleUpdateSettings::UPDATES_DISABLED)
62 return GOOGLE_UPDATE_DISABLED_BY_POLICY;
64 if (update_policy == GoogleUpdateSettings::AUTO_UPDATES_ONLY)
65 return GOOGLE_UPDATE_DISABLED_BY_POLICY_AUTO_ONLY;
67 return GOOGLE_UPDATE_NO_ERROR;
68 #endif
71 // Creates an instance of a COM Local Server class using either plain vanilla
72 // CoCreateInstance, or using the Elevation moniker if running on Vista.
73 // hwnd must refer to a foregound window in order to get the UAC prompt
74 // showing up in the foreground if running on Vista. It can also be NULL if
75 // background UAC prompts are desired.
76 HRESULT CoCreateInstanceAsAdmin(REFCLSID class_id,
77 REFIID interface_id,
78 gfx::AcceleratedWidget hwnd,
79 void** interface_ptr) {
80 if (!interface_ptr)
81 return E_POINTER;
83 // For Vista, need to instantiate the COM server via the elevation
84 // moniker. This ensures that the UAC dialog shows up.
85 if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
86 wchar_t class_id_as_string[MAX_PATH] = {};
87 StringFromGUID2(class_id, class_id_as_string,
88 arraysize(class_id_as_string));
90 base::string16 elevation_moniker_name =
91 base::StringPrintf(L"Elevation:Administrator!new:%ls",
92 class_id_as_string);
94 BIND_OPTS3 bind_opts;
95 // An explicit memset is needed rather than relying on value initialization
96 // since BIND_OPTS3 is not an aggregate (it is a derived type).
97 memset(&bind_opts, 0, sizeof(bind_opts));
98 bind_opts.cbStruct = sizeof(bind_opts);
99 bind_opts.dwClassContext = CLSCTX_LOCAL_SERVER;
100 bind_opts.hwnd = hwnd;
102 return CoGetObject(elevation_moniker_name.c_str(), &bind_opts, interface_id,
103 interface_ptr);
106 return CoCreateInstance(class_id, NULL, CLSCTX_LOCAL_SERVER, interface_id,
107 interface_ptr);
110 HRESULT CreateOnDemandAppsClass(
111 bool system_level,
112 bool install_if_newer,
113 gfx::AcceleratedWidget elevation_window,
114 base::win::ScopedComPtr<IGoogleUpdate>* on_demand) {
115 if (g_google_update_factory)
116 return g_google_update_factory->Run(on_demand);
118 // For a user-level install, update checks and updates can both be done by a
119 // normal user with the UserAppsClass.
120 if (!system_level)
121 return on_demand->CreateInstance(CLSID_OnDemandUserAppsClass);
123 // For a system-level install, update checks can be done by a normal user with
124 // the MachineAppsClass.
125 if (!install_if_newer)
126 return on_demand->CreateInstance(CLSID_OnDemandMachineAppsClass);
128 // For a system-level install, an update requires Admin privileges for writing
129 // to %ProgramFiles%. Elevate while instantiating the MachineAppsClass.
130 return CoCreateInstanceAsAdmin(CLSID_OnDemandMachineAppsClass,
131 IID_IGoogleUpdate, elevation_window,
132 on_demand->ReceiveVoid());
136 // GoogleUpdateJobObserver -----------------------------------------------------
138 // The GoogleUpdateJobObserver COM class is responsible for receiving status
139 // reports from google Update. It keeps track of the progress as Google Update
140 // notifies this observer and runs a completion callback once Google Update
141 // reports that it is done.
142 class GoogleUpdateJobObserver : public CComObjectRootEx<CComSingleThreadModel>,
143 public IJobObserver {
144 public:
145 BEGIN_COM_MAP(GoogleUpdateJobObserver)
146 COM_INTERFACE_ENTRY(IJobObserver)
147 END_COM_MAP()
149 GoogleUpdateJobObserver();
150 virtual ~GoogleUpdateJobObserver();
152 // Sets the callback to be invoked when Google Update reports that the job is
153 // done.
154 void set_on_complete_callback(const base::Closure& on_complete_callback) {
155 on_complete_callback_ = on_complete_callback;
158 // Returns the results of the update operation.
159 GoogleUpdateUpgradeResult result() const {
160 // Intermediary steps should never be reported to the client.
161 DCHECK_NE(UPGRADE_STARTED, result_);
162 DCHECK_NE(UPGRADE_CHECK_STARTED, result_);
163 return result_;
166 // Returns which version Google Update found on the server (if a more
167 // recent version was found). Otherwise, this will be blank.
168 base::string16 new_version() const { return new_version_; }
170 // Returns the Google Update supplied error string that describes the error
171 // that occurred during the update check/upgrade.
172 base::string16 error_message() const { return error_message_; }
174 private:
175 // IJobObserver:
176 STDMETHOD(OnShow)();
177 STDMETHOD(OnCheckingForUpdate)();
178 STDMETHOD(OnUpdateAvailable)(const TCHAR* version_string);
179 STDMETHOD(OnWaitingToDownload)();
180 STDMETHOD(OnDownloading)(int time_remaining_ms, int pos);
181 STDMETHOD(OnWaitingToInstall)();
182 STDMETHOD(OnInstalling)();
183 STDMETHOD(OnPause)();
184 STDMETHOD(OnComplete)(LegacyCompletionCodes code, const TCHAR* text);
185 STDMETHOD(SetEventSink)(IProgressWndEvents* event_sink);
187 // The task runner associated with the thread in which the job runs.
188 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
190 // A callback to be run to complete processing;
191 base::Closure on_complete_callback_;
193 // The status/result of the Google Update operation.
194 GoogleUpdateUpgradeResult result_;
196 // The version string Google Update found.
197 base::string16 new_version_;
199 // An error message, if any.
200 base::string16 error_message_;
202 // Allows us control the upgrade process to a small degree. After OnComplete
203 // has been called, this object can not be used.
204 base::win::ScopedComPtr<IProgressWndEvents> event_sink_;
206 DISALLOW_COPY_AND_ASSIGN(GoogleUpdateJobObserver);
209 GoogleUpdateJobObserver::GoogleUpdateJobObserver()
210 : task_runner_(base::ThreadTaskRunnerHandle::Get()),
211 result_(UPGRADE_ERROR) {
214 GoogleUpdateJobObserver::~GoogleUpdateJobObserver() {
217 STDMETHODIMP GoogleUpdateJobObserver::OnShow() {
218 return S_OK;
221 STDMETHODIMP GoogleUpdateJobObserver::OnCheckingForUpdate() {
222 result_ = UPGRADE_CHECK_STARTED;
223 return S_OK;
226 STDMETHODIMP GoogleUpdateJobObserver::OnUpdateAvailable(
227 const TCHAR* version_string) {
228 result_ = UPGRADE_IS_AVAILABLE;
229 new_version_ = version_string;
230 return S_OK;
233 STDMETHODIMP GoogleUpdateJobObserver::OnWaitingToDownload() {
234 return S_OK;
237 STDMETHODIMP GoogleUpdateJobObserver::OnDownloading(int time_remaining_ms,
238 int pos) {
239 return S_OK;
242 STDMETHODIMP GoogleUpdateJobObserver::OnWaitingToInstall() {
243 return S_OK;
246 STDMETHODIMP GoogleUpdateJobObserver::OnInstalling() {
247 result_ = UPGRADE_STARTED;
248 return S_OK;
251 STDMETHODIMP GoogleUpdateJobObserver::OnPause() {
252 return S_OK;
255 STDMETHODIMP GoogleUpdateJobObserver::OnComplete(LegacyCompletionCodes code,
256 const TCHAR* text) {
257 if (code == COMPLETION_CODE_ERROR) {
258 error_message_ = text;
259 result_ = UPGRADE_ERROR;
260 } else {
261 // Everything that isn't an error is some form of success. Chrome doesn't
262 // support any of the fancy codes (e.g., COMPLETION_CODE_REBOOT), but they
263 // shouldn't be generated anyway.
264 LOG_IF(DFATAL, (code != COMPLETION_CODE_SUCCESS &&
265 code != COMPLETION_CODE_SUCCESS_CLOSE_UI))
266 << "Unexpected LegacyCompletionCode from IGoogleUpdate: " << code;
267 if (result_ == UPGRADE_STARTED)
268 result_ = UPGRADE_SUCCESSFUL;
269 else if (result_ == UPGRADE_CHECK_STARTED)
270 result_ = UPGRADE_ALREADY_UP_TO_DATE;
273 event_sink_ = NULL;
275 task_runner_->PostTask(FROM_HERE, on_complete_callback_);
276 return S_OK;
279 STDMETHODIMP GoogleUpdateJobObserver::SetEventSink(
280 IProgressWndEvents* event_sink) {
281 event_sink_ = event_sink;
282 return S_OK;
286 // UpdateCheckDriver -----------------------------------------------------------
288 // A driver that is created and destroyed on the caller's thread and drives
289 // Google Update on another.
290 class UpdateCheckDriver {
291 public:
292 // Runs an update check on |task_runner|, invoking |callback| on the caller's
293 // thread upon completion. |task_runner| must run a TYPE_UI message loop if
294 // the default IGoogleUpdate on-demand COM class is used.
295 static void RunUpdateCheck(const scoped_refptr<base::TaskRunner>& task_runner,
296 bool install_if_newer,
297 gfx::AcceleratedWidget elevation_window,
298 const UpdateCheckCallback& callback);
300 private:
301 friend class base::DeleteHelper<UpdateCheckDriver>;
303 explicit UpdateCheckDriver(const UpdateCheckCallback& callback);
305 // Runs the caller's update check callback with the results of the operation.
306 ~UpdateCheckDriver();
308 // Starts an update check.
309 void BeginUpdateCheck(bool install_if_newer,
310 gfx::AcceleratedWidget elevation_window);
312 // Helper function for starting an update check. Returns true if the check was
313 // properly started, in which case CompleteUpdateCheck will be invoked upon
314 // completion to return results to the caller on its own thread.
315 bool BeginUpdateCheckInternal(bool install_if_newer,
316 gfx::AcceleratedWidget elevation_window);
318 // Invoked when results are in from Google Update.
319 void CompleteUpdateCheck();
321 // Prepares |results| to return the upgrade error indicated by |error_code|
322 // and |hr|. The string " -- system level" is included in the generated error
323 // message when |system_level| is true.
324 void OnUpgradeError(GoogleUpdateErrorCode error_code,
325 HRESULT hr,
326 bool system_level);
328 // The caller's task runner, on which |result_callback_| will be run.
329 scoped_refptr<base::SingleThreadTaskRunner> result_runner_;
331 // The caller's callback to be run when the update check is compelte.
332 UpdateCheckCallback result_callback_;
334 // The results of the update check.
335 GoogleUpdateUpgradeResult result_;
336 GoogleUpdateErrorCode error_code_;
337 base::string16 error_message_;
338 base::string16 version_;
339 HRESULT hresult_;
341 // A direct pointer to the job observer by which the driver is notified of
342 // interesting events from Google Update.
343 CComObject<GoogleUpdateJobObserver>* job_observer_;
345 // A scoped pointer to |job_observer_| that holds a reference to it, keeping
346 // it alive.
347 base::win::ScopedComPtr<IJobObserver> job_holder_;
349 // The on-demand updater that is doing the work.
350 base::win::ScopedComPtr<IGoogleUpdate> on_demand_;
352 DISALLOW_COPY_AND_ASSIGN(UpdateCheckDriver);
355 // static
356 void UpdateCheckDriver::RunUpdateCheck(
357 const scoped_refptr<base::TaskRunner>& task_runner,
358 bool install_if_newer,
359 gfx::AcceleratedWidget elevation_window,
360 const UpdateCheckCallback& callback) {
361 // The driver is owned by itself, and will self-destruct when its work is
362 // done.
363 UpdateCheckDriver* driver = new UpdateCheckDriver(callback);
364 task_runner->PostTask(
365 FROM_HERE,
366 base::Bind(&UpdateCheckDriver::BeginUpdateCheck, base::Unretained(driver),
367 install_if_newer, elevation_window));
370 // Runs on the caller's thread.
371 UpdateCheckDriver::UpdateCheckDriver(const UpdateCheckCallback& callback)
372 : result_runner_(base::ThreadTaskRunnerHandle::Get()),
373 result_callback_(callback),
374 result_(UPGRADE_ERROR),
375 error_code_(GOOGLE_UPDATE_NO_ERROR),
376 hresult_(S_OK),
377 job_observer_(nullptr) {
380 UpdateCheckDriver::~UpdateCheckDriver() {
381 DCHECK(result_runner_->BelongsToCurrentThread());
382 // If there is an error, then error_code must not be blank, and vice versa.
383 DCHECK_NE(result_ == UPGRADE_ERROR, error_code_ == GOOGLE_UPDATE_NO_ERROR);
384 UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.UpgradeResult", result_,
385 NUM_UPGRADE_RESULTS);
386 if (result_ == UPGRADE_ERROR) {
387 UMA_HISTOGRAM_ENUMERATION("GoogleUpdate.UpdateErrorCode", error_code_,
388 NUM_ERROR_CODES);
389 if (hresult_ != S_OK)
390 UMA_HISTOGRAM_SPARSE_SLOWLY("GoogleUpdate.ErrorHresult", hresult_);
392 result_callback_.Run(result_, error_code_, error_message_, version_);
395 void UpdateCheckDriver::BeginUpdateCheck(
396 bool install_if_newer,
397 gfx::AcceleratedWidget elevation_window) {
398 // Return results immediately if the driver is not waiting for Google Update.
399 if (!BeginUpdateCheckInternal(install_if_newer, elevation_window))
400 result_runner_->DeleteSoon(FROM_HERE, this);
403 bool UpdateCheckDriver::BeginUpdateCheckInternal(
404 bool install_if_newer,
405 gfx::AcceleratedWidget elevation_window) {
406 base::FilePath chrome_exe;
407 if (!PathService::Get(base::DIR_EXE, &chrome_exe))
408 NOTREACHED();
410 const bool system_level = !InstallUtil::IsPerUserInstall(chrome_exe);
412 // The failures handled here are:
413 // CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY,
414 // GOOGLE_UPDATE_DISABLED_BY_POLICY, and
415 // GOOGLE_UPDATE_DISABLED_BY_POLICY_AUTO_ONLY.
416 error_code_ = CanUpdateCurrentChrome(chrome_exe, system_level);
417 if (error_code_ != GOOGLE_UPDATE_NO_ERROR) {
418 // These failures are handled in the UX with custom messages.
419 result_ = UPGRADE_ERROR;
420 return false;
423 // Make sure ATL is initialized in this module.
424 ui::win::CreateATLModuleIfNeeded();
426 HRESULT hr =
427 CComObject<GoogleUpdateJobObserver>::CreateInstance(&job_observer_);
428 if (hr != S_OK) {
429 // Most of the error messages come straight from Google Update. This one is
430 // deemed worthy enough to also warrant its own error.
431 OnUpgradeError(GOOGLE_UPDATE_JOB_SERVER_CREATION_FAILED, hr, false);
432 return false;
434 // Hold a reference on the observer for the lifetime of the driver.
435 job_holder_ = job_observer_;
437 job_observer_->set_on_complete_callback(base::Bind(
438 &UpdateCheckDriver::CompleteUpdateCheck, base::Unretained(this)));
440 hr = CreateOnDemandAppsClass(system_level, install_if_newer, elevation_window,
441 &on_demand_);
442 if (hr != S_OK) {
443 OnUpgradeError(GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND, hr, system_level);
444 return false;
447 base::string16 app_guid = installer::GetAppGuidForUpdates(system_level);
448 DCHECK(!app_guid.empty());
450 if (install_if_newer)
451 hr = on_demand_->Update(app_guid.c_str(), job_observer_);
452 else
453 hr = on_demand_->CheckForUpdate(app_guid.c_str(), job_observer_);
455 if (hr != S_OK) {
456 OnUpgradeError(GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR, hr,
457 system_level);
458 return false;
460 return true;
463 void UpdateCheckDriver::CompleteUpdateCheck() {
464 result_ = job_observer_->result();
465 if (result_ == UPGRADE_ERROR) {
466 error_code_ = GOOGLE_UPDATE_ERROR_UPDATING;
467 error_message_ = job_observer_->error_message();
468 } else {
469 version_ = job_observer_->new_version();
472 // Release the reference on the COM objects before bouncing back to the
473 // caller's thread.
474 on_demand_.Release();
475 job_holder_.Release();
476 job_observer_ = nullptr;
478 result_runner_->DeleteSoon(FROM_HERE, this);
481 void UpdateCheckDriver::OnUpgradeError(GoogleUpdateErrorCode error_code,
482 HRESULT hr,
483 bool system_level) {
484 result_ = UPGRADE_ERROR;
485 error_code_ = error_code;
486 hresult_ = hr;
487 base::string16 error_msg =
488 base::StringPrintf(L"%d: 0x%x", error_code_, hresult_);
489 if (system_level)
490 error_msg += L" -- system level";
491 error_message_ = l10n_util::GetStringFUTF16(
492 IDS_ABOUT_BOX_ERROR_UPDATE_CHECK_FAILED, error_msg);
495 } // namespace
498 // Globals ---------------------------------------------------------------------
500 void BeginUpdateCheck(const scoped_refptr<base::TaskRunner>& task_runner,
501 bool install_if_newer,
502 gfx::AcceleratedWidget elevation_window,
503 const UpdateCheckCallback& callback) {
504 UpdateCheckDriver::RunUpdateCheck(task_runner, install_if_newer,
505 elevation_window, callback);
509 // Private API exposed for testing. --------------------------------------------
511 void SetGoogleUpdateFactoryForTesting(
512 const OnDemandAppsClassFactory& google_update_factory) {
513 if (g_google_update_factory) {
514 delete g_google_update_factory;
515 g_google_update_factory = nullptr;
517 if (!google_update_factory.is_null()) {
518 g_google_update_factory =
519 new OnDemandAppsClassFactory(google_update_factory);