Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / ui / webui / help / version_updater_win.cc
blob9825fe02ff594e9ff129e41332640258b8937fea
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 "base/memory/ref_counted.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/memory/weak_ptr.h"
8 #include "base/strings/string16.h"
9 #include "base/version.h"
10 #include "base/win/win_util.h"
11 #include "base/win/windows_version.h"
12 #include "chrome/browser/google/google_update_win.h"
13 #include "chrome/browser/lifetime/application_lifetime.h"
14 #include "chrome/browser/ui/browser.h"
15 #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"
19 #include "chrome/installer/util/browser_distribution.h"
20 #include "chrome/installer/util/install_util.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/gfx/native_widget_types.h"
24 #include "ui/views/widget/widget.h"
26 using content::BrowserThread;
28 namespace {
30 // Windows implementation of version update functionality, used by the WebUI
31 // About/Help page.
32 class VersionUpdaterWin : public VersionUpdater {
33 private:
34 friend class VersionReader;
35 friend class VersionUpdater;
37 // Clients must use VersionUpdater::Create().
38 VersionUpdaterWin();
39 virtual ~VersionUpdaterWin();
41 // VersionUpdater implementation.
42 virtual void CheckForUpdate(const StatusCallback& callback) override;
43 virtual void RelaunchBrowser() const override;
45 // chrome::UpdateCheckCallback.
46 void OnUpdateCheckResults(GoogleUpdateUpgradeResult result,
47 GoogleUpdateErrorCode error_code,
48 const base::string16& error_message,
49 const base::string16& version);
51 // Update the UI to show the status of the upgrade.
52 void UpdateStatus(GoogleUpdateUpgradeResult result,
53 GoogleUpdateErrorCode error_code,
54 const base::string16& error_message);
56 // Got the intalled version so the handling of the UPGRADE_ALREADY_UP_TO_DATE
57 // result case can now be completeb on the UI thread.
58 void GotInstalledVersion(const Version& version);
60 // Returns a window that can be used for elevation.
61 gfx::AcceleratedWidget GetElevationParent();
63 void BeginUpdateCheckOnFileThread(bool install_if_newer);
65 // Used for callbacks.
66 base::WeakPtrFactory<VersionUpdaterWin> weak_factory_;
68 // Callback used to communicate update status to the client.
69 StatusCallback callback_;
71 DISALLOW_COPY_AND_ASSIGN(VersionUpdaterWin);
74 // This class is used to read the version on the FILE thread and then call back
75 // the version updater in the UI thread. Using a class helps better control
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) {
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_);
94 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
95 &VersionReader::SetVersionInUIThread, this));
98 void SetVersionInUIThread() {
99 if (version_updater_.get() != NULL)
100 version_updater_->GotInstalledVersion(installed_version_);
103 private:
104 friend class base::RefCountedThreadSafe<VersionReader>;
106 // The version updater that must be called back when we are done.
107 // We use a weak pointer in case the updater gets destroyed while waiting.
108 base::WeakPtr<VersionUpdaterWin> version_updater_;
110 // This is the version that gets read in the FILE thread and set on the
111 // the updater in the UI thread.
112 Version installed_version_;
115 VersionUpdaterWin::VersionUpdaterWin()
116 : weak_factory_(this) {
119 VersionUpdaterWin::~VersionUpdaterWin() {
122 void VersionUpdaterWin::CheckForUpdate(const StatusCallback& callback) {
123 callback_ = callback;
125 // On-demand updates for Chrome don't work in Vista RTM when UAC is turned
126 // off. So, in this case, the version updater must not mention
127 // on-demand updates. Silent updates (in the background) should still
128 // work as before - enabling UAC or installing the latest service pack
129 // for Vista is another option.
130 if (!(base::win::GetVersion() == base::win::VERSION_VISTA &&
131 (base::win::OSInfo::GetInstance()->service_pack().major == 0) &&
132 !base::win::UserAccountControlIsEnabled())) {
133 UpdateStatus(UPGRADE_CHECK_STARTED, GOOGLE_UPDATE_NO_ERROR,
134 base::string16());
135 // Specify false to not upgrade yet.
136 BeginUpdateCheckOnFileThread(false);
140 void VersionUpdaterWin::RelaunchBrowser() const {
141 chrome::AttemptRestart();
144 void VersionUpdaterWin::OnUpdateCheckResults(
145 GoogleUpdateUpgradeResult result,
146 GoogleUpdateErrorCode error_code,
147 const base::string16& error_message,
148 const base::string16& version) {
149 UpdateStatus(result, error_code, error_message);
152 void VersionUpdaterWin::UpdateStatus(GoogleUpdateUpgradeResult result,
153 GoogleUpdateErrorCode error_code,
154 const base::string16& error_message) {
155 // For Chromium builds it would show an error message.
156 // But it looks weird because in fact there is no error,
157 // just the update server is not available for non-official builds.
158 #if defined(GOOGLE_CHROME_BUILD)
159 Status status = UPDATED;
160 base::string16 message;
162 switch (result) {
163 case UPGRADE_CHECK_STARTED: {
164 status = CHECKING;
165 break;
167 case UPGRADE_STARTED: {
168 status = UPDATING;
169 break;
171 case UPGRADE_IS_AVAILABLE: {
172 UpdateStatus(UPGRADE_STARTED, GOOGLE_UPDATE_NO_ERROR, base::string16());
173 // Specify true to upgrade now.
174 BeginUpdateCheckOnFileThread(true);
175 return;
177 case UPGRADE_ALREADY_UP_TO_DATE: {
178 // Google Update reported that Chrome is up-to-date.
179 // To confirm the updated version is running, the reading
180 // must be done on the file thread. The rest of this case
181 // will be handled within GotInstalledVersion.
182 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
183 &VersionReader::GetVersionFromFileThread,
184 new VersionReader(weak_factory_.GetWeakPtr())));
185 return;
187 case UPGRADE_SUCCESSFUL: {
188 status = NEARLY_UPDATED;
189 break;
191 case UPGRADE_ERROR: {
192 status = FAILED;
193 if (error_code == GOOGLE_UPDATE_DISABLED_BY_POLICY) {
194 message =
195 l10n_util::GetStringUTF16(IDS_UPGRADE_DISABLED_BY_POLICY);
196 } else if (error_code == GOOGLE_UPDATE_DISABLED_BY_POLICY_AUTO_ONLY) {
197 message =
198 l10n_util::GetStringUTF16(IDS_UPGRADE_DISABLED_BY_POLICY_MANUAL);
199 } else {
200 message =
201 l10n_util::GetStringFUTF16Int(IDS_UPGRADE_ERROR, error_code);
204 if (!error_message.empty()) {
205 message +=
206 l10n_util::GetStringFUTF16(IDS_ABOUT_BOX_ERROR_DURING_UPDATE_CHECK,
207 error_message);
209 break;
213 // TODO(mad): Get proper progress value instead of passing 0.
214 // http://crbug.com/136117
215 callback_.Run(status, 0, message);
216 #endif // defined(GOOGLE_CHROME_BUILD)
219 void VersionUpdaterWin::GotInstalledVersion(const Version& version) {
220 // This must be called on the UI thread so that callback_ can be called.
221 DCHECK_CURRENTLY_ON(BrowserThread::UI);
223 // Make sure that the latest version is running and if not,
224 // notify the user by setting the status to NEARLY_UPDATED.
226 // The extra version check is necessary on Windows because the application
227 // may be already up to date on disk though the running app is still
228 // out of date.
229 chrome::VersionInfo version_info;
230 Version running_version(version_info.Version());
231 callback_.Run((version.IsValid() && version.CompareTo(running_version) > 0)
232 ? NEARLY_UPDATED
233 : UPDATED,
235 base::string16());
238 BOOL CALLBACK WindowEnumeration(HWND window, LPARAM param) {
239 if (IsWindowVisible(window)) {
240 HWND* returned_window = reinterpret_cast<HWND*>(param);
241 *returned_window = window;
242 return FALSE;
244 return TRUE;
247 gfx::AcceleratedWidget VersionUpdaterWin::GetElevationParent() {
248 // Look for a visible window belonging to the UI thread.
249 DCHECK_CURRENTLY_ON(BrowserThread::UI);
250 HWND window = NULL;
251 EnumThreadWindows(GetCurrentThreadId(),
252 WindowEnumeration,
253 reinterpret_cast<LPARAM>(&window));
254 return window;
257 void VersionUpdaterWin::BeginUpdateCheckOnFileThread(bool install_if_newer) {
258 scoped_refptr<base::TaskRunner> task_runner(
259 content::BrowserThread::GetMessageLoopProxyForThread(
260 content::BrowserThread::FILE));
261 BeginUpdateCheck(task_runner, install_if_newer, GetElevationParent(),
262 base::Bind(&VersionUpdaterWin::OnUpdateCheckResults,
263 weak_factory_.GetWeakPtr()));
266 } // namespace
268 VersionUpdater* VersionUpdater::Create(content::BrowserContext* /* context */) {
269 return new VersionUpdaterWin;