Index: chromeos/system/statistics_provider.cc |
diff --git a/chrome/browser/chromeos/system/statistics_provider.cc b/chromeos/system/statistics_provider.cc |
similarity index 46% |
rename from chrome/browser/chromeos/system/statistics_provider.cc |
rename to chromeos/system/statistics_provider.cc |
index e5fd3dce5620a10065a1c4aa16e807fdf6f238e2..d4cd748a4cb82a9512b24b434362bf3d1dbefa5e 100644 |
--- a/chrome/browser/chromeos/system/statistics_provider.cc |
+++ b/chromeos/system/statistics_provider.cc |
@@ -2,28 +2,29 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "chrome/browser/chromeos/system/statistics_provider.h" |
+#include "chromeos/system/statistics_provider.h" |
#include "base/bind.h" |
#include "base/command_line.h" |
#include "base/files/file_path.h" |
+#include "base/location.h" |
#include "base/logging.h" |
#include "base/memory/singleton.h" |
#include "base/path_service.h" |
+#include "base/synchronization/cancellation_flag.h" |
#include "base/synchronization/waitable_event.h" |
#include "base/sys_info.h" |
+#include "base/task_runner.h" |
#include "base/threading/thread_restrictions.h" |
#include "base/time/time.h" |
#include "chromeos/app_mode/kiosk_oem_manifest_parser.h" |
#include "chromeos/chromeos_constants.h" |
#include "chromeos/chromeos_switches.h" |
#include "chromeos/system/name_value_pairs_parser.h" |
-#include "content/public/browser/browser_thread.h" |
- |
-using content::BrowserThread; |
namespace chromeos { |
namespace system { |
+ |
namespace { |
// Path to the tool used to get system info, and delimiters for the output |
@@ -35,7 +36,6 @@ const char kCrosSystemCommentDelim[] = "#"; |
const char kCrosSystemUnknownValue[] = "(error)"; |
const char kHardwareClassCrosSystemKey[] = "hwid"; |
-const char kHardwareClassKey[] = "hardware_class"; |
const char kUnknownHardwareClass[] = "unknown"; |
// File to get machine hardware info from, and key/value delimiters of |
@@ -67,144 +67,171 @@ const CommandLine::CharType kOemManifestFilePath[] = |
// Key values for GetMachineStatistic()/GetMachineFlag() calls. |
const char kDevSwitchBootMode[] = "devsw_boot"; |
-const char kHardwareClass[] = "hardware_class"; |
+const char kHardwareClassKey[] = "hardware_class"; |
const char kOffersCouponCodeKey[] = "ubind_attribute"; |
const char kOffersGroupCodeKey[] = "gbind_attribute"; |
-const char kOemCanExitEnterpriseEnrollmentKey[] = |
- "oem_can_exit_enrollment"; |
-const char kOemDeviceRequisitionKey[] = |
- "oem_device_requisition"; |
-const char kOemIsEnterpriseManagedKey[] = |
- "oem_enterprise_managed"; |
-const char kOemKeyboardDrivenOobeKey[] = |
- "oem_keyboard_driven_oobe"; |
+const char kOemCanExitEnterpriseEnrollmentKey[] = "oem_can_exit_enrollment"; |
+const char kOemDeviceRequisitionKey[] = "oem_device_requisition"; |
+const char kOemIsEnterpriseManagedKey[] = "oem_enterprise_managed"; |
+const char kOemKeyboardDrivenOobeKey[] = "oem_keyboard_driven_oobe"; |
// The StatisticsProvider implementation used in production. |
class StatisticsProviderImpl : public StatisticsProvider { |
public: |
// StatisticsProvider implementation: |
- virtual void Init() OVERRIDE; |
- virtual void StartLoadingMachineStatistics() OVERRIDE; |
+ virtual void StartLoadingMachineStatistics( |
+ const scoped_refptr<base::TaskRunner>& file_task_runner, |
+ bool load_oem_manifest) OVERRIDE; |
virtual bool GetMachineStatistic(const std::string& name, |
std::string* result) OVERRIDE; |
- virtual bool GetMachineFlag(const std::string& name, |
- bool* result) OVERRIDE; |
- virtual void LoadOemManifest() OVERRIDE; |
+ virtual bool GetMachineFlag(const std::string& name, bool* result) OVERRIDE; |
+ virtual void Shutdown() OVERRIDE; |
static StatisticsProviderImpl* GetInstance(); |
protected: |
- StatisticsProviderImpl(); |
- void LoadOemManifestFromFile(const base::FilePath& file); |
- |
- private: |
typedef std::map<std::string, bool> MachineFlags; |
friend struct DefaultSingletonTraits<StatisticsProviderImpl>; |
- // Loads the machine statistcs by examining the system. |
- void LoadMachineStatistics(); |
+ StatisticsProviderImpl(); |
+ virtual ~StatisticsProviderImpl(); |
+ |
+ // Waits up to |kTimeoutSecs| for statistics to be loaded. Returns true if |
+ // they were loaded successfully. |
+ bool WaitForStatisticsLoaded(); |
+ |
+ // Loads the machine statistics off of disk. Runs on the file thread. |
+ void LoadMachineStatistics(bool load_oem_manifest); |
+ |
+ // Loads the OEM statistics off of disk. Runs on the file thread. |
+ void LoadOemManifestFromFile(const base::FilePath& file); |
- bool initialized_; |
bool load_statistics_started_; |
NameValuePairsParser::NameValueMap machine_info_; |
MachineFlags machine_flags_; |
+ base::CancellationFlag cancellation_flag_; |
+ // |on_statistics_loaded_| protects |machine_info_| and |machine_flags_|. |
base::WaitableEvent on_statistics_loaded_; |
+ private: |
DISALLOW_COPY_AND_ASSIGN(StatisticsProviderImpl); |
}; |
-void StatisticsProviderImpl::Init() { |
- DCHECK(!initialized_); |
- initialized_ = true; |
+bool StatisticsProviderImpl::WaitForStatisticsLoaded() { |
+ CHECK(load_statistics_started_); |
+ if (on_statistics_loaded_.IsSignaled()) |
+ return true; |
+ |
+ // Block if the statistics are not loaded yet. Normally this shouldn't |
+ // happen excpet during OOBE. |
+ base::Time start_time = base::Time::Now(); |
+ base::ThreadRestrictions::ScopedAllowWait allow_wait; |
+ on_statistics_loaded_.TimedWait(base::TimeDelta::FromSeconds(kTimeoutSecs)); |
+ |
+ base::TimeDelta dtime = base::Time::Now() - start_time; |
+ if (on_statistics_loaded_.IsSignaled()) { |
+ LOG(ERROR) << "Statistics loaded after waiting " |
+ << dtime.InMilliseconds() << "ms. "; |
+ return true; |
+ } |
+ |
+ LOG(ERROR) << "Statistics not loaded after waiting " |
+ << dtime.InMilliseconds() << "ms. "; |
+ return false; |
} |
-bool StatisticsProviderImpl::GetMachineStatistic( |
- const std::string& name, std::string* result) { |
- CHECK(initialized_); |
- CHECK(load_statistics_started_) |
- << "GetMachineStatistic called before load started: " << name; |
- |
- VLOG(1) << "Statistic is requested for " << name; |
- // Block if the statistics are not loaded yet. Per LOG(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 |
- // beforehand. |
- // |
- // If you see the warning appeared for regular sessions, it probably |
- // means that there is new client code that uses the statistics in the |
- // very early stage of the browser startup. The statistic name should be |
- // helpful to identify the caller. |
- if (!on_statistics_loaded_.IsSignaled()) { |
- // http://crbug.com/125385 |
- base::Time start_time = base::Time::Now(); |
- base::ThreadRestrictions::ScopedAllowWait allow_wait; |
- on_statistics_loaded_.TimedWait(base::TimeDelta::FromSeconds(kTimeoutSecs)); |
- base::TimeDelta dtime = base::Time::Now() - start_time; |
- if (!on_statistics_loaded_.IsSignaled()) { |
- LOG(ERROR) << "Statistics weren't loaded after waiting " |
- << dtime.InMilliseconds() << "ms. " |
- << "Requested statistic: " << name; |
- return false; |
- } else { |
- LOG(ERROR) << "Statistic loaded after waiting " |
- << dtime.InMilliseconds() << "ms. " |
- << "Requested statistic: " << name; |
- } |
+bool StatisticsProviderImpl::GetMachineStatistic(const std::string& name, |
+ std::string* result) { |
+ VLOG(1) << "Machine Statistic requested: " << name; |
+ if (!WaitForStatisticsLoaded()) { |
+ LOG(ERROR) << "GetMachineStatistic called before load started: " << name; |
+ return false; |
} |
NameValuePairsParser::NameValueMap::iterator iter = machine_info_.find(name); |
- if (iter != machine_info_.end()) { |
- *result = iter->second; |
- return true; |
+ if (iter == machine_info_.end()) { |
+ if (base::SysInfo::IsRunningOnChromeOS()) |
+ LOG(WARNING) << "Requested statistic not found: " << name; |
+ return false; |
} |
- return false; |
+ *result = iter->second; |
+ return true; |
} |
-bool StatisticsProviderImpl::GetMachineFlag( |
- const std::string& name, bool* result) { |
- MachineFlags::const_iterator iter = machine_flags_.find(name); |
- if (iter != machine_flags_.end()) { |
- *result = iter->second; |
- return true; |
+bool StatisticsProviderImpl::GetMachineFlag(const std::string& name, |
+ bool* result) { |
+ VLOG(1) << "Machine Flag requested: " << name; |
+ if (!WaitForStatisticsLoaded()) { |
+ LOG(ERROR) << "GetMachineFlag called before load started: " << name; |
+ return false; |
} |
- return false; |
+ MachineFlags::const_iterator iter = machine_flags_.find(name); |
+ if (iter == machine_flags_.end()) { |
+ if (base::SysInfo::IsRunningOnChromeOS()) |
+ LOG(WARNING) << "Requested machine flag not found: " << name; |
+ return false; |
+ } |
+ *result = iter->second; |
+ return true; |
} |
-void StatisticsProviderImpl::LoadOemManifest() { |
- LoadOemManifestFromFile(base::FilePath(kOemManifestFilePath)); |
+void StatisticsProviderImpl::Shutdown() { |
+ cancellation_flag_.Set(); // Cancel any pending loads |
} |
-// manual_reset needs to be true, as we want to keep the signaled state. |
StatisticsProviderImpl::StatisticsProviderImpl() |
- : initialized_(false), |
- load_statistics_started_(false), |
+ : load_statistics_started_(false), |
on_statistics_loaded_(true /* manual_reset */, |
false /* initially_signaled */) { |
} |
-void StatisticsProviderImpl::StartLoadingMachineStatistics() { |
- DCHECK(initialized_); |
- DCHECK(!load_statistics_started_); |
+StatisticsProviderImpl::~StatisticsProviderImpl() { |
+} |
+ |
+void StatisticsProviderImpl::StartLoadingMachineStatistics( |
+ const scoped_refptr<base::TaskRunner>& file_task_runner, |
+ bool load_oem_manifest) { |
+ CHECK(!load_statistics_started_); |
load_statistics_started_ = true; |
- VLOG(1) << "Started loading statistics"; |
- BrowserThread::PostBlockingPoolTask( |
+ VLOG(1) << "Started loading statistics. Load OEM Manifest: " |
+ << load_oem_manifest; |
+ |
+ file_task_runner->PostTask( |
FROM_HERE, |
base::Bind(&StatisticsProviderImpl::LoadMachineStatistics, |
- base::Unretained(this))); |
+ base::Unretained(this), |
+ load_oem_manifest)); |
} |
-void StatisticsProviderImpl::LoadMachineStatistics() { |
- NameValuePairsParser parser(&machine_info_); |
+void StatisticsProviderImpl::LoadMachineStatistics(bool load_oem_manifest) { |
+ // Run from the file task runner. StatisticsProviderImpl is a Singleton<> and |
+ // will not be destroyed until after threads have been stopped, so this test |
+ // is always safe. |
+ if (cancellation_flag_.IsSet()) |
+ return; |
- // 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 << "."; |
+ if (base::SysInfo::IsRunningOnChromeOS()) { |
+ // Parse all of the key/value pairs from the crossystem tool. |
+ NameValuePairsParser parser(&machine_info_); |
+ if (!parser.ParseNameValuePairsFromTool(arraysize(kCrosSystemTool), |
+ kCrosSystemTool, |
+ kCrosSystemEq, |
+ kCrosSystemDelim, |
+ kCrosSystemCommentDelim)) { |
+ LOG(ERROR) << "Errors parsing output from: " << kCrosSystemTool; |
+ } |
+ |
+ parser.GetNameValuePairsFromFile(base::FilePath(kMachineHardwareInfoFile), |
+ kMachineHardwareInfoEq, |
+ kMachineHardwareInfoDelim); |
+ parser.GetNameValuePairsFromFile(base::FilePath(kEchoCouponFile), |
+ kEchoCouponEq, |
+ kEchoCouponDelim); |
+ parser.GetNameValuePairsFromFile(base::FilePath(kVpdFile), |
+ kVpdEq, |
+ kVpdDelim); |
} |
// Ensure that the hardware class key is present with the expected |
@@ -215,25 +242,33 @@ void StatisticsProviderImpl::LoadMachineStatistics() { |
else |
machine_info_[kHardwareClassKey] = hardware_class; |
- parser.GetNameValuePairsFromFile(base::FilePath(kMachineHardwareInfoFile), |
- kMachineHardwareInfoEq, |
- kMachineHardwareInfoDelim); |
- parser.GetNameValuePairsFromFile(base::FilePath(kEchoCouponFile), |
- kEchoCouponEq, |
- kEchoCouponDelim); |
- parser.GetNameValuePairsFromFile(base::FilePath(kVpdFile), kVpdEq, kVpdDelim); |
+ if (load_oem_manifest) { |
+ // If kAppOemManifestFile switch is specified, load OEM Manifest file. |
+ CommandLine* command_line = CommandLine::ForCurrentProcess(); |
+ if (command_line->HasSwitch(switches::kAppOemManifestFile)) { |
+ LoadOemManifestFromFile( |
+ command_line->GetSwitchValuePath(switches::kAppOemManifestFile)); |
+ } else if (base::SysInfo::IsRunningOnChromeOS()) { |
+ LoadOemManifestFromFile(base::FilePath(kOemManifestFilePath)); |
+ } |
+ } |
// Finished loading the statistics. |
on_statistics_loaded_.Signal(); |
- VLOG(1) << "Finished loading statistics"; |
+ VLOG(1) << "Finished loading statistics."; |
} |
void StatisticsProviderImpl::LoadOemManifestFromFile( |
const base::FilePath& file) { |
- KioskOemManifestParser::Manifest oem_manifest; |
- if (!KioskOemManifestParser::Load(file, &oem_manifest)) |
+ // Called from LoadMachineStatistics. Check cancellation_flag_ again here. |
+ if (cancellation_flag_.IsSet()) |
return; |
+ KioskOemManifestParser::Manifest oem_manifest; |
+ if (!KioskOemManifestParser::Load(file, &oem_manifest)) { |
+ LOG(WARNING) << "Unable to load OEM Manifest file: " << file.value(); |
+ return; |
+ } |
machine_info_[kOemDeviceRequisitionKey] = |
oem_manifest.device_requisition; |
machine_flags_[kOemIsEnterpriseManagedKey] = |
@@ -242,6 +277,8 @@ void StatisticsProviderImpl::LoadOemManifestFromFile( |
oem_manifest.can_exit_enrollment; |
machine_flags_[kOemKeyboardDrivenOobeKey] = |
oem_manifest.keyboard_driven_oobe; |
+ |
+ VLOG(1) << "Loaded OEM Manifest statistics from " << file.value(); |
} |
StatisticsProviderImpl* StatisticsProviderImpl::GetInstance() { |
@@ -249,62 +286,18 @@ StatisticsProviderImpl* StatisticsProviderImpl::GetInstance() { |
DefaultSingletonTraits<StatisticsProviderImpl> >::get(); |
} |
-// The stub StatisticsProvider implementation used on Linux desktop. |
-class StatisticsProviderStubImpl : public StatisticsProviderImpl { |
- public: |
- // StatisticsProvider implementation: |
- virtual void Init() OVERRIDE {} |
- |
- virtual void StartLoadingMachineStatistics() OVERRIDE {} |
- |
- virtual bool GetMachineStatistic(const std::string& name, |
- std::string* result) OVERRIDE { |
- if (name == "CHROMEOS_RELEASE_BOARD") { |
- // Note: syncer::GetSessionNameSynchronously() also uses the mechanism |
- // below to determine the CrOs release board. However, it cannot include |
- // statistics_provider.h and use this method because of the mutual |
- // dependency that creates between sync.gyp:sync and chrome.gyp:browser. |
- // TODO(rsimha): Update syncer::GetSessionNameSynchronously() if this code |
- // is ever moved into base/. See http://crbug.com/126732. |
- const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
- if (command_line->HasSwitch(chromeos::switches::kChromeOSReleaseBoard)) { |
- *result = command_line-> |
- GetSwitchValueASCII(chromeos::switches::kChromeOSReleaseBoard); |
- return true; |
- } |
- } |
- return false; |
- } |
- |
- virtual void LoadOemManifest() OVERRIDE { |
- CommandLine* command_line = CommandLine::ForCurrentProcess(); |
- if (!command_line->HasSwitch(switches::kAppOemManifestFile)) |
- return; |
- |
- LoadOemManifestFromFile( |
- command_line->GetSwitchValuePath(switches::kAppOemManifestFile)); |
- } |
- |
- static StatisticsProviderStubImpl* GetInstance() { |
- return Singleton<StatisticsProviderStubImpl, |
- DefaultSingletonTraits<StatisticsProviderStubImpl> >::get(); |
- } |
- |
- private: |
- friend struct DefaultSingletonTraits<StatisticsProviderStubImpl>; |
- |
- StatisticsProviderStubImpl() { |
- } |
- |
- DISALLOW_COPY_AND_ASSIGN(StatisticsProviderStubImpl); |
-}; |
+static StatisticsProvider* g_test_statistics_provider = NULL; |
+// static |
StatisticsProvider* StatisticsProvider::GetInstance() { |
- if (base::SysInfo::IsRunningOnChromeOS()) { |
- return StatisticsProviderImpl::GetInstance(); |
- } else { |
- return StatisticsProviderStubImpl::GetInstance(); |
- } |
+ if (g_test_statistics_provider) |
+ return g_test_statistics_provider; |
+ return StatisticsProviderImpl::GetInstance(); |
+} |
+ |
+// static |
+void StatisticsProvider::SetTestProvider(StatisticsProvider* test_provider) { |
+ g_test_statistics_provider = test_provider; |
} |
} // namespace system |