Index: chrome/browser/chromeos/system/statistics_provider.cc |
diff --git a/chrome/browser/chromeos/system/statistics_provider.cc b/chrome/browser/chromeos/system/statistics_provider.cc |
index 28118635c75ba22ebcadc78211511a041f5f2bff..fcfd52b261a562351153b54c150e42a7990645c2 100644 |
--- a/chrome/browser/chromeos/system/statistics_provider.cc |
+++ b/chrome/browser/chromeos/system/statistics_provider.cc |
@@ -10,6 +10,9 @@ |
#include "base/file_util.h" |
#include "base/logging.h" |
#include "base/memory/singleton.h" |
+#include "base/memory/weak_ptr.h" |
+#include "base/metrics/histogram.h" |
+#include "base/observer_list.h" |
#include "base/synchronization/waitable_event.h" |
#include "base/threading/thread_restrictions.h" |
#include "base/time.h" |
@@ -72,6 +75,9 @@ class StatisticsProviderImpl : public StatisticsProvider { |
virtual bool GetMachineStatistic(const std::string& name, |
std::string* result) OVERRIDE; |
+ virtual void AddObserver(Observer* observer) OVERRIDE; |
+ virtual void RemoveObserver(Observer* observer) OVERRIDE; |
+ |
static StatisticsProviderImpl* GetInstance(); |
private: |
@@ -82,19 +88,27 @@ class StatisticsProviderImpl : public StatisticsProvider { |
// Starts loading the machine statistcs. |
void StartLoadingMachineStatistics(); |
- // Loads the machine statistcs by examining the system. |
- void LoadMachineStatistics(); |
+ // Loads the machine statistics by examining the system. |
+ // This is executed on the blocking pool, and replies by posting a task to |
+ // the UI thread using |weak_this|. |
+ void LoadMachineStatistics(base::WeakPtr<StatisticsProviderImpl> weak_this, |
+ base::Time start_time); |
+ |
+ // Posted to UI from LoadMachineStatistics() once the info has been read. |
+ void OnStatisticsLoaded(base::Time start_time); |
NameValuePairsParser::NameValueMap machine_info_; |
base::WaitableEvent on_statistics_loaded_; |
+ base::WeakPtrFactory<StatisticsProviderImpl> weak_factory_; |
+ ObserverList<Observer, true> observer_list_; |
DISALLOW_COPY_AND_ASSIGN(StatisticsProviderImpl); |
}; |
-bool StatisticsProviderImpl::GetMachineStatistic( |
- const std::string& name, std::string* result) { |
+bool StatisticsProviderImpl::GetMachineStatistic(const std::string& name, |
+ std::string* result) { |
VLOG(1) << "Statistic is requested for " << name; |
- // Block if the statistics are not loaded yet. Per LOG(WARNING) below, |
+ // Block if the statistics are not loaded yet. Per DLOG(WARNING) below, |
// the statistics are loaded before requested as of now. For regular |
// sessions (i.e. not OOBE), statistics are first requested when the |
// user is logging in so we have plenty of time to load the data |
@@ -105,15 +119,16 @@ bool StatisticsProviderImpl::GetMachineStatistic( |
// very early stage of the browser startup. The statistic name should be |
// helpful to identify the caller. |
if (!on_statistics_loaded_.IsSignaled()) { |
- LOG(WARNING) << "Waiting to load statistics. Requested statistic: " |
- << name; |
+ DLOG(WARNING) << "Waiting to load statistics. Requested statistic: " |
+ << name; |
// http://crbug.com/125385 |
base::ThreadRestrictions::ScopedAllowWait allow_wait; |
on_statistics_loaded_.TimedWait(base::TimeDelta::FromSeconds(kTimeoutSecs)); |
if (!on_statistics_loaded_.IsSignaled()) { |
- LOG(ERROR) << "Statistics weren't loaded after waiting! " |
- << "Requested statistic: " << name; |
+ DLOG(ERROR) << "Statistics weren't loaded after waiting! " |
+ << "Requested statistic: " << name; |
+ UMA_HISTOGRAM_BOOLEAN("Cros.StatisticsProviderTimedOut", true); |
return false; |
} |
} |
@@ -126,10 +141,24 @@ bool StatisticsProviderImpl::GetMachineStatistic( |
return false; |
} |
+void StatisticsProviderImpl::AddObserver(Observer* observer) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ if (on_statistics_loaded_.IsSignaled()) { |
jar (doing other things)
2012/05/21 18:10:02
This confuses me a bit, as we're doing signalling,
Joao da Silva
2012/05/22 14:55:25
Removing the signal would require refactoring all
|
+ observer->OnMachineStatisticsReady(); |
+ } else { |
+ observer_list_.AddObserver(observer); |
jar (doing other things)
2012/05/21 18:10:02
I see an observer optionally being added... but I
Joao da Silva
2012/05/22 14:55:25
Right, this is a bit confusing. Removing an observ
Joao da Silva
2012/05/22 19:10:09
I'd like your take on this matter before proceedin
jar (doing other things)
2012/05/22 20:09:30
The "callback" version was re-inventing the wheel.
|
+ } |
+} |
+ |
+void StatisticsProviderImpl::RemoveObserver(Observer* observer) { |
+ observer_list_.RemoveObserver(observer); |
+} |
+ |
// manual_reset needs to be true, as we want to keep the signaled state. |
StatisticsProviderImpl::StatisticsProviderImpl() |
: on_statistics_loaded_(true /* manual_reset */, |
- false /* initially_signaled */) { |
+ false /* initially_signaled */), |
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
StartLoadingMachineStatistics(); |
} |
@@ -138,18 +167,23 @@ void StatisticsProviderImpl::StartLoadingMachineStatistics() { |
BrowserThread::PostBlockingPoolTask( |
FROM_HERE, |
base::Bind(&StatisticsProviderImpl::LoadMachineStatistics, |
- base::Unretained(this))); |
+ base::Unretained(this), |
+ weak_factory_.GetWeakPtr(), |
+ base::Time::Now())); |
} |
-void StatisticsProviderImpl::LoadMachineStatistics() { |
+void StatisticsProviderImpl::LoadMachineStatistics( |
+ base::WeakPtr<StatisticsProviderImpl> weak_this, |
+ base::Time start_time) { |
NameValuePairsParser parser(&machine_info_); |
// Parse all of the key/value pairs from the crossystem tool. |
if (!parser.ParseNameValuePairsFromTool( |
arraysize(kCrosSystemTool), kCrosSystemTool, kCrosSystemEq, |
kCrosSystemDelim, kCrosSystemCommentDelim)) { |
- LOG(WARNING) << "There were errors parsing the output of " |
- << kCrosSystemTool << "."; |
+ DLOG(WARNING) << "There were errors parsing the output of " |
+ << kCrosSystemTool << "."; |
+ UMA_HISTOGRAM_BOOLEAN("Cros.CrosSystemParsingFailed", true); |
} |
// Ensure that the hardware class key is present with the expected |
@@ -175,6 +209,12 @@ void StatisticsProviderImpl::LoadMachineStatistics() { |
on_statistics_loaded_.Signal(); |
VLOG(1) << "Finished loading statistics"; |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(&StatisticsProviderImpl::OnStatisticsLoaded, |
+ weak_this, |
+ start_time)); |
+ |
#if defined(GOOGLE_CHROME_BUILD) |
// TODO(kochi): This is for providing a channel information to |
// chrome::VersionInfo::GetChannel()/GetVersionStringModifier(), |
@@ -199,6 +239,13 @@ void StatisticsProviderImpl::LoadMachineStatistics() { |
#endif |
} |
+void StatisticsProviderImpl::OnStatisticsLoaded(base::Time start_time) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ base::TimeDelta elapsed = base::Time::Now() - start_time; |
+ UMA_HISTOGRAM_LONG_TIMES("Cros.StatisticsProviderReadyDelay", elapsed); |
+ FOR_EACH_OBSERVER(Observer, observer_list_, OnMachineStatisticsReady()); |
jar (doing other things)
2012/05/21 18:10:02
This, for instance, would be a great place to remo
jar (doing other things)
2012/05/22 20:09:30
Note that it would get messy if you tried to use a
|
+} |
+ |
StatisticsProviderImpl* StatisticsProviderImpl::GetInstance() { |
return Singleton<StatisticsProviderImpl, |
DefaultSingletonTraits<StatisticsProviderImpl> >::get(); |
@@ -213,6 +260,13 @@ class StatisticsProviderStubImpl : public StatisticsProvider { |
return false; |
} |
+ virtual void AddObserver(Observer* observer) OVERRIDE { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ observer->OnMachineStatisticsReady(); |
+ } |
+ |
+ virtual void RemoveObserver(Observer* observer) OVERRIDE {} |
+ |
static StatisticsProviderStubImpl* GetInstance() { |
return Singleton<StatisticsProviderStubImpl, |
DefaultSingletonTraits<StatisticsProviderStubImpl> >::get(); |