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

Side by Side Diff: chrome/browser/upgrade_detector_impl.cc

Issue 11440020: Add an outdated upgrade bubble view. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years 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 | Annotate | Revision Log
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 "chrome/browser/upgrade_detector_impl.h" 5 #include "chrome/browser/upgrade_detector_impl.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/file_path.h" 11 #include "base/file_path.h"
12 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
13 #include "base/memory/singleton.h" 13 #include "base/memory/singleton.h"
14 #include "base/path_service.h" 14 #include "base/path_service.h"
15 #include "base/string_number_conversions.h" 15 #include "base/string_number_conversions.h"
16 #include "base/string_util.h" 16 #include "base/string_util.h"
17 #include "base/time.h" 17 #include "base/time.h"
18 #include "base/utf_string_conversions.h" 18 #include "base/utf_string_conversions.h"
19 #include "chrome/common/chrome_notification_types.h"
19 #include "chrome/common/chrome_switches.h" 20 #include "chrome/common/chrome_switches.h"
20 #include "chrome/common/chrome_version_info.h" 21 #include "chrome/common/chrome_version_info.h"
21 #include "chrome/installer/util/browser_distribution.h" 22 #include "chrome/installer/util/browser_distribution.h"
22 #include "content/public/browser/browser_thread.h" 23 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/notification_service.h"
25 #include "content/public/browser/user_metrics.h"
23 #include "ui/base/resource/resource_bundle.h" 26 #include "ui/base/resource/resource_bundle.h"
24 27
25 #if defined(OS_WIN) 28 #if defined(OS_WIN)
29 #include "chrome/browser/google/google_update_win.h"
30 #include "chrome/installer/util/google_update_settings.h"
26 #include "chrome/installer/util/install_util.h" 31 #include "chrome/installer/util/install_util.h"
27 #elif defined(OS_MACOSX) 32 #elif defined(OS_MACOSX)
28 #include "chrome/browser/mac/keystone_glue.h" 33 #include "chrome/browser/mac/keystone_glue.h"
29 #elif defined(OS_POSIX) 34 #elif defined(OS_POSIX)
30 #include "base/process_util.h" 35 #include "base/process_util.h"
31 #include "base/version.h" 36 #include "base/version.h"
32 #endif 37 #endif
33 38
34 using content::BrowserThread; 39 using content::BrowserThread;
35 40
(...skipping 25 matching lines...) Expand all
61 int GetCheckForUpgradeEveryMs() { 66 int GetCheckForUpgradeEveryMs() {
62 // Check for a value passed via the command line. 67 // Check for a value passed via the command line.
63 int interval_ms; 68 int interval_ms;
64 std::string interval = CmdLineInterval(); 69 std::string interval = CmdLineInterval();
65 if (!interval.empty() && base::StringToInt(interval, &interval_ms)) 70 if (!interval.empty() && base::StringToInt(interval, &interval_ms))
66 return interval_ms * 1000; // Command line value is in seconds. 71 return interval_ms * 1000; // Command line value is in seconds.
67 72
68 return kCheckForUpgradeMs; 73 return kCheckForUpgradeMs;
69 } 74 }
70 75
71 // This task checks the currently running version of Chrome against the
72 // installed version. If the installed version is newer, it runs the passed
73 // callback task. Otherwise it just deletes the task.
74 void DetectUpgradeTask(const base::Closure& upgrade_detected_task,
75 bool* is_unstable_channel,
76 bool* is_critical_upgrade) {
77 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
78
79 Version installed_version;
80 Version critical_update;
81
82 #if defined(OS_WIN) 76 #if defined(OS_WIN)
77 // This code can be used by both regular and outdated upgrades.
Finnur 2012/12/06 19:53:16 nit: suggest: by both regular upgrades and for che
MAD 2013/01/22 15:18:29 This is gone... Reworking the whole thing...
78 // |critical_update| can be NULL if not needed.
79 void GetInstalledAndCriticalVersion(Version* installed_version,
80 Version* critical_update) {
83 // Get the version of the currently *installed* instance of Chrome, 81 // Get the version of the currently *installed* instance of Chrome,
84 // which might be newer than the *running* instance if we have been 82 // which might be newer than the *running* instance if we have been
85 // upgraded in the background. 83 // upgraded in the background.
86 FilePath exe_path; 84 FilePath exe_path;
87 if (!PathService::Get(base::DIR_EXE, &exe_path)) { 85 if (!PathService::Get(base::DIR_EXE, &exe_path)) {
88 NOTREACHED() << "Failed to find executable path"; 86 NOTREACHED() << "Failed to find executable path";
89 return; 87 return;
90 } 88 }
91 89
92 bool system_install = 90 bool system_install =
93 !InstallUtil::IsPerUserInstall(exe_path.value().c_str()); 91 !InstallUtil::IsPerUserInstall(exe_path.value().c_str());
94 92
95 // TODO(tommi): Check if using the default distribution is always the right 93 // TODO(tommi): Check if using the default distribution is always the right
96 // thing to do. 94 // thing to do.
97 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 95 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
98 InstallUtil::GetChromeVersion(dist, system_install, &installed_version); 96 DCHECK(installed_version);
97 InstallUtil::GetChromeVersion(dist, system_install, installed_version);
99 98
100 if (installed_version.IsValid()) { 99 if (critical_update && installed_version->IsValid()) {
101 InstallUtil::GetCriticalUpdateVersion(dist, system_install, 100 InstallUtil::GetCriticalUpdateVersion(dist, system_install,
102 &critical_update); 101 critical_update);
103 } 102 }
103 }
104 #endif // defined(OS_WIN)
105
106 // This task checks the currently running version of Chrome against the
107 // installed version. If the installed version is newer, it runs the passed
108 // callback task. Otherwise it just deletes the task.
109 void DetectUpgradeTask(const base::Closure& upgrade_detected_task,
110 bool* is_unstable_channel,
111 bool* is_critical_upgrade) {
112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
113
114 Version installed_version;
115 Version critical_update;
116
117 #if defined(OS_WIN)
118 GetInstalledAndCriticalVersion(&installed_version, &critical_update);
104 #elif defined(OS_MACOSX) 119 #elif defined(OS_MACOSX)
105 installed_version = 120 installed_version =
106 Version(UTF16ToASCII(keystone_glue::CurrentlyInstalledVersion())); 121 Version(UTF16ToASCII(keystone_glue::CurrentlyInstalledVersion()));
107 #elif defined(OS_POSIX) 122 #elif defined(OS_POSIX)
108 // POSIX but not Mac OS X: Linux, etc. 123 // POSIX but not Mac OS X: Linux, etc.
109 CommandLine command_line(*CommandLine::ForCurrentProcess()); 124 CommandLine command_line(*CommandLine::ForCurrentProcess());
110 command_line.AppendSwitch(switches::kProductVersion); 125 command_line.AppendSwitch(switches::kProductVersion);
111 std::string reply; 126 std::string reply;
112 if (!base::GetAppOutput(command_line, &reply)) { 127 if (!base::GetAppOutput(command_line, &reply)) {
113 DLOG(ERROR) << "Failed to get current file version"; 128 DLOG(ERROR) << "Failed to get current file version";
(...skipping 29 matching lines...) Expand all
143 *is_critical_upgrade = 158 *is_critical_upgrade =
144 critical_update.IsValid() && 159 critical_update.IsValid() &&
145 (critical_update.CompareTo(running_version) > 0); 160 (critical_update.CompareTo(running_version) > 0);
146 161
147 // Fire off the upgrade detected task. 162 // Fire off the upgrade detected task.
148 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 163 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
149 upgrade_detected_task); 164 upgrade_detected_task);
150 } 165 }
151 } 166 }
152 167
168 #if defined(OS_WIN)
Finnur 2012/12/06 19:53:16 I would probably have moved this to a _win.cc file
MAD 2013/01/22 15:18:29 Gone!
169 // Implementation of a GoogleUpdateStatusListener (only available on Windows),
170 // so we can get the available version and identify if we are outdated.
171 class UpgradeStatusListener : public GoogleUpdateStatusListener {
172 public:
173 explicit UpgradeStatusListener(const base::Closure& notify_outdated_callback)
174 : google_updater_(new GoogleUpdate()),
175 got_installed_version_(false),
176 got_available_version_(false),
177 notify_outdated_callback_(notify_outdated_callback) {
178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
179 google_updater_->set_status_listener(this);
180 // false is for |install_if_newer|, we just want the available version.
181 // And when we use false, we don't need to specify a |window|, so NULL.
182 google_updater_->CheckForUpdate(false, NULL);
183
184 // We use FILE as the thread to get the installed version
185 // since it requires reading a file. And it is safe to use an unretained
186 // this pointer since GetInstalledVersion must be called before destruction.
187 BrowserThread::PostTask(
188 BrowserThread::FILE, FROM_HERE,
189 base::Bind(&UpgradeStatusListener::GetInstalledVersion,
190 base::Unretained(this)));
191 }
192
193 virtual ~UpgradeStatusListener() {
194 google_updater_->set_status_listener(NULL);
195 }
196
197 // GoogleUpdateStatusListener implementation.
198 virtual void OnReportResults(GoogleUpdateUpgradeResult result,
199 GoogleUpdateErrorCode error_code,
200 const string16& error_message,
201 const string16& version) OVERRIDE {
202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
203 // The google update class is never supposed to sent these two to listeners.
Finnur 2012/12/06 19:53:16 nit: s/sent/send/
MAD 2013/01/22 15:18:29 Gone!
204 DCHECK(result != UPGRADE_STARTED && result != UPGRADE_CHECK_STARTED);
205
206 // Since false was specified for |install_if_newer|, this shouldn't happen.
207 DCHECK(result != UPGRADE_SUCCESSFUL);
208
209 switch (result) {
210 case UPGRADE_ALREADY_UP_TO_DATE: {
211 // Nothing needs to be done.
212 break;
213 }
214 case UPGRADE_ERROR: {
215 // Record these errors in UMA to see if something should be added here.
216 content::RecordAction(content::UserMetricsAction("UpgradeCheck_Error"));
217 break;
218 }
219 case UPGRADE_IS_AVAILABLE: {
220 available_version_ = Version(UTF16ToASCII(version));
221 break;
222 }
223 default: {
224 NOTREACHED();
225 }
226 }
227 got_available_version_ = true;
Finnur 2012/12/06 19:53:16 This variable is actually misnamed because you don
MAD 2013/01/22 15:18:29 Gone!
228 if (got_installed_version_)
229 CheckForOutdated();
230 }
231
232 private:
233 void GetInstalledVersion() {
234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
235 Version installed_version;
236 // We only check for outdated when there are no group policies preventing
Finnur 2012/12/06 19:53:16 s/outdated/outdated version/
MAD 2013/01/22 15:18:29 Gone!
237 // regular upgrades. The test is done here because it needs access to the
238 // registry, which must be done on the FILE thread.
239 BrowserDistribution* distribution = BrowserDistribution::GetDistribution();
240 DCHECK(distribution);
241 if (GoogleUpdateSettings::GetAppUpdatePolicy(distribution->GetAppGuid(),
242 NULL) ==
243 GoogleUpdateSettings::AUTOMATIC_UPDATES) {
244 // An uninitialized install version prevents an outdated notification.
Finnur 2012/12/06 19:53:16 Not sure I understand this comment...
MAD 2013/01/22 15:18:29 Gone!
245 GetInstalledAndCriticalVersion(&installed_version, NULL);
246 }
247 BrowserThread::PostTask(
248 BrowserThread::UI, FROM_HERE,
249 base::Bind(&UpgradeStatusListener::GotInstalledVersion,
250 base::Unretained(this), installed_version));
251 }
252
253 void GotInstalledVersion(const Version& installed_version) {
254 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
255 installed_version_ = installed_version;
256 got_installed_version_ = true;
257 if (got_available_version_)
258 CheckForOutdated();
259 }
260
261 void CheckForOutdated() {
Finnur 2012/12/06 19:53:16 nit: Suggest: CheckIfOutdatedVersion or NotifyIfOu
MAD 2013/01/22 15:18:29 Gone!
262 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
263 DCHECK(got_available_version_ && got_installed_version_);
264 if (available_version_.IsValid() && installed_version_.IsValid() &&
265 available_version_.components()[0] >
266 installed_version_.components()[0] + 1) {
267 notify_outdated_callback_.Run();
268 }
269 delete this;
270 }
271
272 // The class that communicates with Google Update to find out if an update is
273 // available and asks it to start an upgrade.
274 scoped_refptr<GoogleUpdate> google_updater_;
275
276 // The value returned by GetInstalledAndCriticalVersion might be invalid
277 // so a bool is also needed to identify that we at least tried to read it.
278 Version installed_version_;
279 bool got_installed_version_;
280
281 // The value returned by google_updater_ might also be invalid
282 // so a bool is also needed to identify that we at least tried to read it.
283 Version available_version_;
284 bool got_available_version_;
285
286 // A callback to notify of an outdated install.
287 base::Closure notify_outdated_callback_;
288
289 DISALLOW_COPY_AND_ASSIGN(UpgradeStatusListener);
290 };
291
292 #endif // defined(OS_WIN)
293
153 } // namespace 294 } // namespace
154 295
155 UpgradeDetectorImpl::UpgradeDetectorImpl() 296 UpgradeDetectorImpl::UpgradeDetectorImpl()
156 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), 297 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
157 is_unstable_channel_(false) { 298 is_unstable_channel_(false) {
158 CommandLine command_line(*CommandLine::ForCurrentProcess()); 299 CommandLine command_line(*CommandLine::ForCurrentProcess());
159 if (command_line.HasSwitch(switches::kDisableBackgroundNetworking)) 300 if (command_line.HasSwitch(switches::kDisableBackgroundNetworking))
160 return; 301 return;
161 if (command_line.HasSwitch(switches::kSimulateUpgrade)) { 302 if (command_line.HasSwitch(switches::kSimulateUpgrade)) {
162 UpgradeDetected(); 303 UpgradeDetected();
163 return; 304 return;
164 } 305 }
165 // Windows: only enable upgrade notifications for official builds. 306 // Windows: only enable upgrade notifications for official builds.
166 // Mac: only enable them if the updater (Keystone) is present. 307 // Mac: only enable them if the updater (Keystone) is present.
167 // Linux (and other POSIX): always enable regardless of branding. 308 // Linux (and other POSIX): always enable regardless of branding.
168 #if (defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)) || defined(OS_POSIX) 309 #if (defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)) || defined(OS_POSIX)
169 #if defined(OS_MACOSX) 310 #if defined(OS_MACOSX)
170 if (keystone_glue::KeystoneEnabled()) 311 if (keystone_glue::KeystoneEnabled())
171 #endif 312 #endif
172 { 313 {
173 detect_upgrade_timer_.Start(FROM_HERE, 314 detect_upgrade_timer_.Start(FROM_HERE,
174 base::TimeDelta::FromMilliseconds(GetCheckForUpgradeEveryMs()), 315 base::TimeDelta::FromMilliseconds(GetCheckForUpgradeEveryMs()),
175 this, &UpgradeDetectorImpl::CheckForUpgrade); 316 this, &UpgradeDetectorImpl::CheckForUpgrade);
176 } 317 }
177 #endif 318 #endif
319 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
320 // On Windows, we also check for an outdated version so we use this listener
321 // of Google update to asynchronously fetch the available version.
322 // This object will self-destruct when done.
323 new UpgradeStatusListener(base::Bind(&UpgradeDetectorImpl::NotifyOutdated,
324 weak_factory_.GetWeakPtr()));
325 #endif // defined(OS_WIN)
178 } 326 }
179 327
180 UpgradeDetectorImpl::~UpgradeDetectorImpl() { 328 UpgradeDetectorImpl::~UpgradeDetectorImpl() {
181 } 329 }
182 330
183 void UpgradeDetectorImpl::CheckForUpgrade() { 331 void UpgradeDetectorImpl::CheckForUpgrade() {
184 weak_factory_.InvalidateWeakPtrs(); 332 weak_factory_.InvalidateWeakPtrs();
185 base::Closure callback_task = 333 base::Closure callback_task =
186 base::Bind(&UpgradeDetectorImpl::UpgradeDetected, 334 base::Bind(&UpgradeDetectorImpl::UpgradeDetected,
187 weak_factory_.GetWeakPtr()); 335 weak_factory_.GetWeakPtr());
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 } else if (time_passed >= kLowThreshold) { 409 } else if (time_passed >= kLowThreshold) {
262 set_upgrade_notification_stage(UPGRADE_ANNOYANCE_LOW); 410 set_upgrade_notification_stage(UPGRADE_ANNOYANCE_LOW);
263 } else { 411 } else {
264 return; // Not ready to recommend upgrade. 412 return; // Not ready to recommend upgrade.
265 } 413 }
266 } 414 }
267 415
268 NotifyUpgradeRecommended(); 416 NotifyUpgradeRecommended();
269 } 417 }
270 418
419 void UpgradeDetectorImpl::NotifyOutdated() {
420 // Stop the recurring timer (that is checking for changes).
421 detect_upgrade_timer_.Stop();
422 set_upgrade_notification_stage(UPGRADE_ANNOYANCE_CRITICAL);
423
424 content::NotificationService::current()->Notify(
425 chrome::NOTIFICATION_OUTDATED_INSTALL,
426 content::Source<UpgradeDetector>(this),
427 content::NotificationService::NoDetails());
428
429 NotifyUpgradeRecommended();
430 }
431
271 // static 432 // static
272 UpgradeDetectorImpl* UpgradeDetectorImpl::GetInstance() { 433 UpgradeDetectorImpl* UpgradeDetectorImpl::GetInstance() {
273 return Singleton<UpgradeDetectorImpl>::get(); 434 return Singleton<UpgradeDetectorImpl>::get();
274 } 435 }
275 436
276 // static 437 // static
277 UpgradeDetector* UpgradeDetector::GetInstance() { 438 UpgradeDetector* UpgradeDetector::GetInstance() {
278 return UpgradeDetectorImpl::GetInstance(); 439 return UpgradeDetectorImpl::GetInstance();
279 } 440 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698