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

Side by Side Diff: chrome/browser/ui/webui/help/version_updater_win.cc

Issue 1117263002: Switch on-demand update checks to the less-old GoogleUpdate3 API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: latest comments, better parent window handling, proper Google Update API Created 5 years, 7 months 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/memory/ref_counted.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/memory/weak_ptr.h" 5 #include "base/memory/weak_ptr.h"
8 #include "base/strings/string16.h" 6 #include "base/strings/string16.h"
9 #include "base/version.h"
10 #include "base/win/win_util.h" 7 #include "base/win/win_util.h"
11 #include "base/win/windows_version.h" 8 #include "base/win/windows_version.h"
9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/first_run/upgrade_util_win.h"
12 #include "chrome/browser/google/google_update_win.h" 11 #include "chrome/browser/google/google_update_win.h"
13 #include "chrome/browser/lifetime/application_lifetime.h" 12 #include "chrome/browser/lifetime/application_lifetime.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/webui/help/version_updater.h" 13 #include "chrome/browser/ui/webui/help/version_updater.h"
16 #include "chrome/common/chrome_version_info.h"
17 #include "chrome/grit/chromium_strings.h"
18 #include "chrome/grit/generated_resources.h" 14 #include "chrome/grit/generated_resources.h"
19 #include "chrome/installer/util/browser_distribution.h"
20 #include "chrome/installer/util/install_util.h"
21 #include "content/public/browser/browser_thread.h" 15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/web_contents.h"
17 #include "ui/aura/window.h"
18 #include "ui/aura/window_tree_host.h"
22 #include "ui/base/l10n/l10n_util.h" 19 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/gfx/native_widget_types.h" 20 #include "ui/gfx/native_widget_types.h"
24 #include "ui/views/widget/widget.h"
25
26 using content::BrowserThread;
27 21
28 namespace { 22 namespace {
29 23
30 // Windows implementation of version update functionality, used by the WebUI 24 // Windows implementation of version update functionality, used by the WebUI
31 // About/Help page. 25 // About/Help page.
32 class VersionUpdaterWin : public VersionUpdater { 26 class VersionUpdaterWin : public VersionUpdater, public UpdateCheckDelegate {
33 private: 27 public:
34 friend class VersionReader; 28 // |owner_widget| is the parent widget hosting the update check UI. Any UI
35 friend class VersionUpdater; 29 // needed to install an update (e.g., a UAC prompt for a system-level install)
36 30 // will be parented to this widget.
37 // Clients must use VersionUpdater::Create(). 31 explicit VersionUpdaterWin(gfx::AcceleratedWidget owner_widget);
38 VersionUpdaterWin();
39 ~VersionUpdaterWin() override; 32 ~VersionUpdaterWin() override;
40 33
41 // VersionUpdater implementation. 34 // VersionUpdater:
42 void CheckForUpdate(const StatusCallback& callback) override; 35 void CheckForUpdate(const StatusCallback& callback) override;
43 void RelaunchBrowser() const override; 36 void RelaunchBrowser() const override;
44 37
45 // chrome::UpdateCheckCallback. 38 // UpdateCheckDelegate:
46 void OnUpdateCheckResults(GoogleUpdateUpgradeResult result, 39 void OnUpdateCheckComplete(const base::string16& new_version) override;
47 GoogleUpdateErrorCode error_code, 40 void OnUpgradeProgress(int progress,
48 const base::string16& error_message, 41 const base::string16& new_version) override;
49 const base::string16& version); 42 void OnUpgradeComplete(const base::string16& new_version) override;
43 void OnError(GoogleUpdateErrorCode error_code,
44 const base::string16& error_message,
45 const base::string16& new_version) override;
50 46
51 // Update the UI to show the status of the upgrade. 47 private:
52 void UpdateStatus(GoogleUpdateUpgradeResult result, 48 #if defined(GOOGLE_CHROME_BUILD)
53 GoogleUpdateErrorCode error_code, 49 void BeginUpdateCheckOnFileThread(bool install_update_if_possible);
54 const base::string16& error_message); 50 #endif // GOOGLE_CHROME_BUILD
55 51
56 // Got the intalled version so the handling of the UPGRADE_ALREADY_UP_TO_DATE 52 // The widget owning the UI for the update check.
57 // result case can now be completeb on the UI thread. 53 gfx::AcceleratedWidget owner_widget_;
58 void GotInstalledVersion(const Version& version);
59
60 // Returns a window that can be used for elevation.
61 gfx::AcceleratedWidget GetElevationParent();
62
63 void BeginUpdateCheckOnFileThread(bool install_if_newer);
64 54
65 // Callback used to communicate update status to the client. 55 // Callback used to communicate update status to the client.
66 StatusCallback callback_; 56 StatusCallback callback_;
67 57
68 // Used for callbacks. 58 // Used for callbacks.
69 base::WeakPtrFactory<VersionUpdaterWin> weak_factory_; 59 base::WeakPtrFactory<VersionUpdaterWin> weak_factory_;
70 60
71 DISALLOW_COPY_AND_ASSIGN(VersionUpdaterWin); 61 DISALLOW_COPY_AND_ASSIGN(VersionUpdaterWin);
72 }; 62 };
73 63
74 // This class is used to read the version on the FILE thread and then call back 64 VersionUpdaterWin::VersionUpdaterWin(gfx::AcceleratedWidget owner_widget)
75 // the version updater in the UI thread. Using a class helps better control 65 : owner_widget_(owner_widget), weak_factory_(this) {
76 // the lifespan of the Version independently of the lifespan of the version
77 // updater, which may die while asynchonicity is happening, thus the usage of
78 // the WeakPtr, which can only be used from the thread that created it.
79 class VersionReader
80 : public base::RefCountedThreadSafe<VersionReader> {
81 public:
82 explicit VersionReader(
83 const base::WeakPtr<VersionUpdaterWin>& version_updater)
84 : version_updater_(version_updater) {
85 }
86
87 void GetVersionFromFileThread() {
88 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
89 InstallUtil::GetChromeVersion(dist, false, &installed_version_);
90 if (!installed_version_.IsValid()) {
91 // User-level Chrome is not installed, check system-level.
92 InstallUtil::GetChromeVersion(dist, true, &installed_version_);
93 }
94 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
95 &VersionReader::SetVersionInUIThread, this));
96 }
97
98 void SetVersionInUIThread() {
99 if (version_updater_.get() != NULL)
100 version_updater_->GotInstalledVersion(installed_version_);
101 }
102
103 private:
104 friend class base::RefCountedThreadSafe<VersionReader>;
105
106 ~VersionReader() {}
107
108 // The version updater that must be called back when we are done.
109 // We use a weak pointer in case the updater gets destroyed while waiting.
110 base::WeakPtr<VersionUpdaterWin> version_updater_;
111
112 // This is the version that gets read in the FILE thread and set on the
113 // the updater in the UI thread.
114 Version installed_version_;
115 };
116
117 VersionUpdaterWin::VersionUpdaterWin()
118 : weak_factory_(this) {
119 } 66 }
120 67
121 VersionUpdaterWin::~VersionUpdaterWin() { 68 VersionUpdaterWin::~VersionUpdaterWin() {
122 } 69 }
123 70
124 void VersionUpdaterWin::CheckForUpdate(const StatusCallback& callback) { 71 void VersionUpdaterWin::CheckForUpdate(const StatusCallback& callback) {
72 // There is no supported integration with Google Update for Chromium.
73 #if defined(GOOGLE_CHROME_BUILD)
125 callback_ = callback; 74 callback_ = callback;
126 75
127 // On-demand updates for Chrome don't work in Vista RTM when UAC is turned 76 // On-demand updates for Chrome don't work in Vista RTM when UAC is turned
128 // off. So, in this case, the version updater must not mention 77 // off. So, in this case, the version updater must not mention
129 // on-demand updates. Silent updates (in the background) should still 78 // on-demand updates. Silent updates (in the background) should still
130 // work as before - enabling UAC or installing the latest service pack 79 // work as before - enabling UAC or installing the latest service pack
131 // for Vista is another option. 80 // for Vista is another option.
132 if (!(base::win::GetVersion() == base::win::VERSION_VISTA && 81 if (!(base::win::GetVersion() == base::win::VERSION_VISTA &&
133 (base::win::OSInfo::GetInstance()->service_pack().major == 0) && 82 (base::win::OSInfo::GetInstance()->service_pack().major == 0) &&
134 !base::win::UserAccountControlIsEnabled())) { 83 !base::win::UserAccountControlIsEnabled())) {
135 UpdateStatus(UPGRADE_CHECK_STARTED, GOOGLE_UPDATE_NO_ERROR, 84 callback_.Run(CHECKING, 0, base::string16());
136 base::string16()); 85 BeginUpdateCheckOnFileThread(false /* !install_update_if_possible */);
137 // Specify false to not upgrade yet.
138 BeginUpdateCheckOnFileThread(false);
139 } 86 }
87 #endif
140 } 88 }
141 89
142 void VersionUpdaterWin::RelaunchBrowser() const { 90 void VersionUpdaterWin::RelaunchBrowser() const {
143 chrome::AttemptRestart(); 91 chrome::AttemptRestart();
144 } 92 }
145 93
146 void VersionUpdaterWin::OnUpdateCheckResults( 94 void VersionUpdaterWin::OnUpdateCheckComplete(
147 GoogleUpdateUpgradeResult result, 95 const base::string16& new_version) {
148 GoogleUpdateErrorCode error_code, 96 #if defined(GOOGLE_CHROME_BUILD)
Peter Kasting 2015/05/12 22:04:34 Do we need to #if out the contents of these next f
grt (UTC plus 2) 2015/05/13 13:04:05 Agreed. I'm going to land this as-is. I think a be
149 const base::string16& error_message, 97 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
150 const base::string16& version) { 98 Status status = CHECKING;
151 UpdateStatus(result, error_code, error_message); 99 if (new_version.empty()) {
100 // Google Update says that no new version is available. Check to see if a
101 // restart is needed for a previously-applied update to take effect.
102 status = upgrade_util::IsRunningOldChrome() ? NEARLY_UPDATED : UPDATED;
103 } else {
104 // Notify the caller that the update is now beginning and initiate it.
105 status = UPDATING;
106 BeginUpdateCheckOnFileThread(true /* install_update_if_possible */);
107 }
108 callback_.Run(status, 0, base::string16());
109 #endif // GOOGLE_CHROME_BUILD
152 } 110 }
153 111
154 void VersionUpdaterWin::UpdateStatus(GoogleUpdateUpgradeResult result, 112 void VersionUpdaterWin::OnUpgradeProgress(int progress,
155 GoogleUpdateErrorCode error_code, 113 const base::string16& new_version) {
156 const base::string16& error_message) {
157 // For Chromium builds it would show an error message.
158 // But it looks weird because in fact there is no error,
159 // just the update server is not available for non-official builds.
160 #if defined(GOOGLE_CHROME_BUILD) 114 #if defined(GOOGLE_CHROME_BUILD)
161 Status status = UPDATED; 115 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
116 callback_.Run(UPDATING, progress, base::string16());
117 #endif // GOOGLE_CHROME_BUILD
118 }
119
120 void VersionUpdaterWin::OnUpgradeComplete(const base::string16& new_version) {
121 #if defined(GOOGLE_CHROME_BUILD)
122 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
123 callback_.Run(NEARLY_UPDATED, 0, base::string16());
124 #endif // GOOGLE_CHROME_BUILD
125 }
126
127 void VersionUpdaterWin::OnError(GoogleUpdateErrorCode error_code,
128 const base::string16& error_message,
129 const base::string16& new_version) {
130 #if defined(GOOGLE_CHROME_BUILD)
131 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
162 base::string16 message; 132 base::string16 message;
163 133
164 switch (result) { 134 // Current versions of Google Update provide a nice message for the policy
165 case UPGRADE_CHECK_STARTED: { 135 // case. Use this generic error for the policy case only if no message from
166 status = CHECKING; 136 // Google Update is present.
167 break; 137 if (error_code != GOOGLE_UPDATE_DISABLED_BY_POLICY || error_message.empty())
168 } 138 message = l10n_util::GetStringFUTF16Int(IDS_UPGRADE_ERROR, error_code);
169 case UPGRADE_STARTED: {
170 status = UPDATING;
171 break;
172 }
173 case UPGRADE_IS_AVAILABLE: {
174 UpdateStatus(UPGRADE_STARTED, GOOGLE_UPDATE_NO_ERROR, base::string16());
175 // Specify true to upgrade now.
176 BeginUpdateCheckOnFileThread(true);
177 return;
178 }
179 case UPGRADE_ALREADY_UP_TO_DATE: {
180 // Google Update reported that Chrome is up-to-date.
181 // To confirm the updated version is running, the reading
182 // must be done on the file thread. The rest of this case
183 // will be handled within GotInstalledVersion.
184 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
185 &VersionReader::GetVersionFromFileThread,
186 new VersionReader(weak_factory_.GetWeakPtr())));
187 return;
188 }
189 case UPGRADE_SUCCESSFUL: {
190 status = NEARLY_UPDATED;
191 break;
192 }
193 case UPGRADE_ERROR: {
194 status = FAILED;
195 if (error_code == GOOGLE_UPDATE_DISABLED_BY_POLICY) {
196 message =
197 l10n_util::GetStringUTF16(IDS_UPGRADE_DISABLED_BY_POLICY);
198 } else if (error_code == GOOGLE_UPDATE_DISABLED_BY_POLICY_AUTO_ONLY) {
199 message =
200 l10n_util::GetStringUTF16(IDS_UPGRADE_DISABLED_BY_POLICY_MANUAL);
201 } else {
202 message =
203 l10n_util::GetStringFUTF16Int(IDS_UPGRADE_ERROR, error_code);
204 }
205 139
206 if (!error_message.empty()) { 140 if (!error_message.empty()) {
207 message += 141 message += l10n_util::GetStringFUTF16(
208 l10n_util::GetStringFUTF16(IDS_ABOUT_BOX_ERROR_DURING_UPDATE_CHECK, 142 IDS_ABOUT_BOX_ERROR_DURING_UPDATE_CHECK, error_message);
209 error_message);
210 }
211 break;
212 }
213 } 143 }
214 144 callback_.Run(FAILED, 0, message);
215 // TODO(mad): Get proper progress value instead of passing 0. 145 #endif // GOOGLE_CHROME_BUILD
216 // http://crbug.com/136117
217 callback_.Run(status, 0, message);
218 #endif // defined(GOOGLE_CHROME_BUILD)
219 } 146 }
220 147
221 void VersionUpdaterWin::GotInstalledVersion(const Version& version) { 148 #if defined(GOOGLE_CHROME_BUILD)
222 // This must be called on the UI thread so that callback_ can be called. 149 void VersionUpdaterWin::BeginUpdateCheckOnFileThread(
223 DCHECK_CURRENTLY_ON(BrowserThread::UI); 150 bool install_update_if_possible) {
224 151 BeginUpdateCheck(content::BrowserThread::GetMessageLoopProxyForThread(
225 // Make sure that the latest version is running and if not, 152 content::BrowserThread::FILE),
Peter Kasting 2015/05/12 22:04:34 Perhaps outside the scope of this CL, but with my
grt (UTC plus 2) 2015/05/13 13:04:05 I tried that early on in this change and found tha
Sorin Jianu 2015/05/18 20:32:45 re: COM on FILE thread, I am interested in the sol
226 // notify the user by setting the status to NEARLY_UPDATED. 153 g_browser_process->GetApplicationLocale(),
227 // 154 install_update_if_possible, owner_widget_,
228 // The extra version check is necessary on Windows because the application 155 weak_factory_.GetWeakPtr());
229 // may be already up to date on disk though the running app is still
230 // out of date.
231 chrome::VersionInfo version_info;
232 Version running_version(version_info.Version());
233 callback_.Run((version.IsValid() && version.CompareTo(running_version) > 0)
234 ? NEARLY_UPDATED
235 : UPDATED,
236 0,
237 base::string16());
238 } 156 }
239 157 #endif // GOOGLE_CHROME_BUILD
240 BOOL CALLBACK WindowEnumeration(HWND window, LPARAM param) {
241 if (IsWindowVisible(window)) {
242 HWND* returned_window = reinterpret_cast<HWND*>(param);
243 *returned_window = window;
244 return FALSE;
245 }
246 return TRUE;
247 }
248
249 gfx::AcceleratedWidget VersionUpdaterWin::GetElevationParent() {
250 // Look for a visible window belonging to the UI thread.
251 DCHECK_CURRENTLY_ON(BrowserThread::UI);
252 HWND window = NULL;
253 EnumThreadWindows(GetCurrentThreadId(),
254 WindowEnumeration,
255 reinterpret_cast<LPARAM>(&window));
256 return window;
257 }
258
259 void VersionUpdaterWin::BeginUpdateCheckOnFileThread(bool install_if_newer) {
260 scoped_refptr<base::TaskRunner> task_runner(
261 content::BrowserThread::GetMessageLoopProxyForThread(
262 content::BrowserThread::FILE));
263 BeginUpdateCheck(task_runner, install_if_newer, GetElevationParent(),
264 base::Bind(&VersionUpdaterWin::OnUpdateCheckResults,
265 weak_factory_.GetWeakPtr()));
266 }
267 158
268 } // namespace 159 } // namespace
269 160
270 VersionUpdater* VersionUpdater::Create(content::BrowserContext* /* context */) { 161 VersionUpdater* VersionUpdater::Create(content::WebContents* web_contents) {
271 return new VersionUpdaterWin; 162 // Retrieve the HWND for the browser window that is hosting the update check.
163 // This will be used as the parent for a UAC prompt, if needed. It's possible
164 // this this window will no longer have focus by the time UAC is needed. In
165 // that case, the UAC prompt will appear in the taskbar and will require a
166 // user click. This is the least surprising thing we can do for the user, and
167 // is the intended behavior for Windows applications. It's also possible that
168 // the browser window hosting the update check will have been closed by the
169 // time the UAC prompt is needed. This will behave similarly.
170 return new VersionUpdaterWin(web_contents->GetTopLevelNativeWindow()
171 ->GetHost()
172 ->GetAcceleratedWidget());
272 } 173 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698