| 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 f7b88ff1d3504bf5ea5f538d4e6a5ce5be6fbfdf..7d82cd0ddbd0582672291e8fbb2609e075cb7aa4 100644
|
| --- a/chrome/browser/chromeos/system/statistics_provider.cc
|
| +++ b/chrome/browser/chromeos/system/statistics_provider.cc
|
| @@ -5,11 +5,14 @@
|
| #include "chrome/browser/chromeos/system/statistics_provider.h"
|
|
|
| #include "base/bind.h"
|
| +#include "base/bind_helpers.h"
|
| #include "base/chromeos/chromeos_version.h"
|
| #include "base/file_path.h"
|
| #include "base/file_util.h"
|
| #include "base/logging.h"
|
| #include "base/memory/singleton.h"
|
| +#include "base/message_loop.h"
|
| +#include "base/metrics/histogram.h"
|
| #include "base/synchronization/waitable_event.h"
|
| #include "base/time.h"
|
| #include "base/chromeos/chromeos_version.h"
|
| @@ -62,6 +65,15 @@ const char kVpdDelim[] = "\n";
|
| // Timeout that we should wait for statistics to get loaded
|
| const int kTimeoutSecs = 3;
|
|
|
| +// Helper to invoke |callbacks| on the UI thread.
|
| +void NotifyOnUI(const std::vector<base::Closure>& callbacks) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + for (std::vector<base::Closure>::const_iterator it = callbacks.begin();
|
| + it != callbacks.end(); ++it) {
|
| + it->Run();
|
| + }
|
| +}
|
| +
|
| } // namespace
|
|
|
| // The StatisticsProvider implementation used in production.
|
| @@ -71,6 +83,8 @@ class StatisticsProviderImpl : public StatisticsProvider {
|
| virtual bool GetMachineStatistic(const std::string& name,
|
| std::string* result) OVERRIDE;
|
|
|
| + virtual void WhenReady(const base::Closure& callback) OVERRIDE;
|
| +
|
| static StatisticsProviderImpl* GetInstance();
|
|
|
| private:
|
| @@ -86,14 +100,16 @@ class StatisticsProviderImpl : public StatisticsProvider {
|
|
|
| NameValuePairsParser::NameValueMap machine_info_;
|
| base::WaitableEvent on_statistics_loaded_;
|
| + std::vector<base::Closure> callbacks_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(StatisticsProviderImpl);
|
| };
|
|
|
| bool StatisticsProviderImpl::GetMachineStatistic(
|
| - const std::string& name, std::string* result) {
|
| + 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
|
| @@ -104,13 +120,13 @@ 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;
|
| 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;
|
| return false;
|
| }
|
| }
|
| @@ -123,6 +139,16 @@ bool StatisticsProviderImpl::GetMachineStatistic(
|
| return false;
|
| }
|
|
|
| +void StatisticsProviderImpl::WhenReady(const base::Closure& callback) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + if (on_statistics_loaded_.IsSignaled()) {
|
| + // Don't assume the caller is re-entrant.
|
| + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
|
| + } else {
|
| + callbacks_.push_back(callback);
|
| + }
|
| +}
|
| +
|
| // manual_reset needs to be true, as we want to keep the signaled state.
|
| StatisticsProviderImpl::StatisticsProviderImpl()
|
| : on_statistics_loaded_(true /* manual_reset */,
|
| @@ -145,8 +171,9 @@ void StatisticsProviderImpl::LoadMachineStatistics() {
|
| 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
|
| @@ -172,6 +199,13 @@ void StatisticsProviderImpl::LoadMachineStatistics() {
|
| on_statistics_loaded_.Signal();
|
| VLOG(1) << "Finished loading statistics";
|
|
|
| + // Any callbacks registed before Signal() are in |callbacks_|. Any registed
|
| + // after Signal() will be immediately posted. NotifyOnUI() posts the callbacks
|
| + // in |callbacks_| from the UI loop.
|
| + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
| + base::Bind(NotifyOnUI, callbacks_));
|
| + callbacks_.clear();
|
| +
|
| #if defined(GOOGLE_CHROME_BUILD)
|
| // TODO(kochi): This is for providing a channel information to
|
| // chrome::VersionInfo::GetChannel()/GetVersionStringModifier(),
|
| @@ -210,6 +244,11 @@ class StatisticsProviderStubImpl : public StatisticsProvider {
|
| return false;
|
| }
|
|
|
| + virtual void WhenReady(const base::Closure& callback) OVERRIDE {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
|
| + }
|
| +
|
| static StatisticsProviderStubImpl* GetInstance() {
|
| return Singleton<StatisticsProviderStubImpl,
|
| DefaultSingletonTraits<StatisticsProviderStubImpl> >::get();
|
|
|