14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file. 44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/system/statistics_provider.h" 64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/bind.h" 84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/command_line.h" 94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/files/file_path.h" 104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/location.h" 114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/logging.h" 124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/memory/singleton.h" 134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/path_service.h" 14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/synchronization/cancellation_flag.h" 164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/synchronization/waitable_event.h" 174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/sys_info.h" 184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/task_runner.h" 194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/threading/thread_restrictions.h" 204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/time/time.h" 214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/app_mode/kiosk_oem_manifest_parser.h" 224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/chromeos_constants.h" 234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/chromeos_switches.h" 244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/system/name_value_pairs_parser.h" 254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace chromeos { 274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace system { 284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace { 304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Path to the tool used to get system info, and delimiters for the output 324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// format of the tool. 334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char* kCrosSystemTool[] = { "/usr/bin/crossystem" }; 344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kCrosSystemEq[] = "="; 354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kCrosSystemDelim[] = "\n"; 364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kCrosSystemCommentDelim[] = "#"; 374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kCrosSystemUnknownValue[] = "(error)"; 384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kHardwareClassCrosSystemKey[] = "hwid"; 404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kUnknownHardwareClass[] = "unknown"; 41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kSerialNumber[] = "sn"; 424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// File to get machine hardware info from, and key/value delimiters of 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// the file. machine-info is generated only for OOBE and enterprise enrollment 45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// and may not be present. See login-manager/init/machine-info.conf. 464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kMachineHardwareInfoFile[] = "/tmp/machine-info"; 474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kMachineHardwareInfoEq[] = "="; 484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kMachineHardwareInfoDelim[] = " \n"; 494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// File to get ECHO coupon info from, and key/value delimiters of 514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// the file. 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kEchoCouponFile[] = "/var/cache/echo/vpd_echo.txt"; 534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kEchoCouponEq[] = "="; 544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kEchoCouponDelim[] = "\n"; 554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// File to get VPD info from, and key/value delimiters of the file. 574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kVpdFile[] = "/var/log/vpd_2.0.txt"; 584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kVpdEq[] = "="; 594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kVpdDelim[] = "\n"; 604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Timeout that we should wait for statistics to get loaded 624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const int kTimeoutSecs = 3; 634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// The location of OEM manifest file used to trigger OOBE flow for kiosk mode. 654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const CommandLine::CharType kOemManifestFilePath[] = 664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) FILE_PATH_LITERAL("/usr/share/oem/oobe/manifest.json"); 674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace 694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Key values for GetMachineStatistic()/GetMachineFlag() calls. 714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kDevSwitchBootMode[] = "devsw_boot"; 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char kCustomizationIdKey[] = "customization_id"; 734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kHardwareClassKey[] = "hardware_class"; 744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kOffersCouponCodeKey[] = "ubind_attribute"; 754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kOffersGroupCodeKey[] = "gbind_attribute"; 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char kRlzBrandCodeKey[] = "rlz_brand_code"; 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// OEM specific statistics. Must be prefixed with "oem_". 794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kOemCanExitEnterpriseEnrollmentKey[] = "oem_can_exit_enrollment"; 804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kOemDeviceRequisitionKey[] = "oem_device_requisition"; 814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kOemIsEnterpriseManagedKey[] = "oem_enterprise_managed"; 824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kOemKeyboardDrivenOobeKey[] = "oem_keyboard_driven_oobe"; 834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool HasOemPrefix(const std::string& name) { 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return name.substr(0, 4) == "oem_"; 86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// The StatisticsProvider implementation used in production. 894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class StatisticsProviderImpl : public StatisticsProvider { 904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public: 914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // StatisticsProvider implementation: 924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual void StartLoadingMachineStatistics( 934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const scoped_refptr<base::TaskRunner>& file_task_runner, 944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool load_oem_manifest) OVERRIDE; 954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual bool GetMachineStatistic(const std::string& name, 964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string* result) OVERRIDE; 974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual bool GetMachineFlag(const std::string& name, bool* result) OVERRIDE; 984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual void Shutdown() OVERRIDE; 994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static StatisticsProviderImpl* GetInstance(); 1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) protected: 1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) typedef std::map<std::string, bool> MachineFlags; 1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) friend struct DefaultSingletonTraits<StatisticsProviderImpl>; 1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StatisticsProviderImpl(); 1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual ~StatisticsProviderImpl(); 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Waits up to |kTimeoutSecs| for statistics to be loaded. Returns true if 1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // they were loaded successfully. 1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool WaitForStatisticsLoaded(); 1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Loads the machine statistics off of disk. Runs on the file thread. 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) void LoadMachineStatistics(bool load_oem_manifest); 1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Loads the OEM statistics off of disk. Runs on the file thread. 1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) void LoadOemManifestFromFile(const base::FilePath& file); 1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool load_statistics_started_; 1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NameValuePairsParser::NameValueMap machine_info_; 1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MachineFlags machine_flags_; 1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::CancellationFlag cancellation_flag_; 1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // |on_statistics_loaded_| protects |machine_info_| and |machine_flags_|. 1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::WaitableEvent on_statistics_loaded_; 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool oem_manifest_loaded_; 1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private: 1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(StatisticsProviderImpl); 1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}; 1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool StatisticsProviderImpl::WaitForStatisticsLoaded() { 1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CHECK(load_statistics_started_); 1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (on_statistics_loaded_.IsSignaled()) 1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Block if the statistics are not loaded yet. Normally this shouldn't 137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // happen except during OOBE. 1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Time start_time = base::Time::Now(); 1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::ThreadRestrictions::ScopedAllowWait allow_wait; 1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) on_statistics_loaded_.TimedWait(base::TimeDelta::FromSeconds(kTimeoutSecs)); 1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::TimeDelta dtime = base::Time::Now() - start_time; 1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (on_statistics_loaded_.IsSignaled()) { 1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG(ERROR) << "Statistics loaded after waiting " 1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << dtime.InMilliseconds() << "ms. "; 1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG(ERROR) << "Statistics not loaded after waiting " 1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << dtime.InMilliseconds() << "ms. "; 1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool StatisticsProviderImpl::GetMachineStatistic(const std::string& name, 1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string* result) { 1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) VLOG(1) << "Machine Statistic requested: " << name; 1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!WaitForStatisticsLoaded()) { 1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG(ERROR) << "GetMachineStatistic called before load started: " << name; 1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NameValuePairsParser::NameValueMap::iterator iter = machine_info_.find(name); 1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (iter == machine_info_.end()) { 164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (base::SysInfo::IsRunningOnChromeOS() && 165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) (oem_manifest_loaded_ || !HasOemPrefix(name))) { 1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG(WARNING) << "Requested statistic not found: " << name; 167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *result = iter->second; 1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool StatisticsProviderImpl::GetMachineFlag(const std::string& name, 1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool* result) { 1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) VLOG(1) << "Machine Flag requested: " << name; 1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!WaitForStatisticsLoaded()) { 1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG(ERROR) << "GetMachineFlag called before load started: " << name; 1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MachineFlags::const_iterator iter = machine_flags_.find(name); 1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (iter == machine_flags_.end()) { 184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (base::SysInfo::IsRunningOnChromeOS() && 185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) (oem_manifest_loaded_ || !HasOemPrefix(name))) { 1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG(WARNING) << "Requested machine flag not found: " << name; 187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *result = iter->second; 1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void StatisticsProviderImpl::Shutdown() { 1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) cancellation_flag_.Set(); // Cancel any pending loads 1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)StatisticsProviderImpl::StatisticsProviderImpl() 1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : load_statistics_started_(false), 2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) on_statistics_loaded_(true /* manual_reset */, 201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) false /* initially_signaled */), 202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) oem_manifest_loaded_(false) { 2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)StatisticsProviderImpl::~StatisticsProviderImpl() { 2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void StatisticsProviderImpl::StartLoadingMachineStatistics( 2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const scoped_refptr<base::TaskRunner>& file_task_runner, 2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool load_oem_manifest) { 2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CHECK(!load_statistics_started_); 2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) load_statistics_started_ = true; 2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) VLOG(1) << "Started loading statistics. Load OEM Manifest: " 2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << load_oem_manifest; 2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_task_runner->PostTask( 2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) FROM_HERE, 2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Bind(&StatisticsProviderImpl::LoadMachineStatistics, 2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Unretained(this), 2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) load_oem_manifest)); 2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void StatisticsProviderImpl::LoadMachineStatistics(bool load_oem_manifest) { 2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Run from the file task runner. StatisticsProviderImpl is a Singleton<> and 2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // will not be destroyed until after threads have been stopped, so this test 2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // is always safe. 2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (cancellation_flag_.IsSet()) 2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 231effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NameValuePairsParser parser(&machine_info_); 2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (base::SysInfo::IsRunningOnChromeOS()) { 2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Parse all of the key/value pairs from the crossystem tool. 2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!parser.ParseNameValuePairsFromTool(arraysize(kCrosSystemTool), 2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) kCrosSystemTool, 2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) kCrosSystemEq, 2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) kCrosSystemDelim, 2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) kCrosSystemCommentDelim)) { 2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG(ERROR) << "Errors parsing output from: " << kCrosSystemTool; 2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 243effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch parser.GetNameValuePairsFromFile(base::FilePath(kMachineHardwareInfoFile), 244effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kMachineHardwareInfoEq, 245effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kMachineHardwareInfoDelim); 246effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch parser.GetNameValuePairsFromFile(base::FilePath(kEchoCouponFile), 247effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kEchoCouponEq, 248effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kEchoCouponDelim); 249effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch parser.GetNameValuePairsFromFile(base::FilePath(kVpdFile), 250effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kVpdEq, 251effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kVpdDelim); 252effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Ensure that the hardware class key is present with the expected 2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // key name, and if it couldn't be retrieved, that the value is "unknown". 2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string hardware_class = machine_info_[kHardwareClassCrosSystemKey]; 2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (hardware_class.empty() || hardware_class == kCrosSystemUnknownValue) 2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) machine_info_[kHardwareClassKey] = kUnknownHardwareClass; 2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) else 2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) machine_info_[kHardwareClassKey] = hardware_class; 2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (load_oem_manifest) { 2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // If kAppOemManifestFile switch is specified, load OEM Manifest file. 2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CommandLine* command_line = CommandLine::ForCurrentProcess(); 2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (command_line->HasSwitch(switches::kAppOemManifestFile)) { 2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LoadOemManifestFromFile( 2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) command_line->GetSwitchValuePath(switches::kAppOemManifestFile)); 2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (base::SysInfo::IsRunningOnChromeOS()) { 2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LoadOemManifestFromFile(base::FilePath(kOemManifestFilePath)); 2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 272010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!base::SysInfo::IsRunningOnChromeOS() && 273010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) machine_info_.find(kSerialNumber) == machine_info_.end()) { 274010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Set stub value for testing. A time value is appended to avoid clashes of 275010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // the same serial for the same domain, which would invalidate earlier 276010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // enrollments. A fake /tmp/machine-info file should be used instead if 277010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // a stable serial is needed, e.g. to test re-enrollment. 278010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::TimeDelta time = base::Time::Now() - base::Time::UnixEpoch(); 279010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) machine_info_[kSerialNumber] = 280010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) "stub_serial_number_" + base::Int64ToString(time.InSeconds()); 281010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 282010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Finished loading the statistics. 2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) on_statistics_loaded_.Signal(); 2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) VLOG(1) << "Finished loading statistics."; 2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void StatisticsProviderImpl::LoadOemManifestFromFile( 2894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const base::FilePath& file) { 2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Called from LoadMachineStatistics. Check cancellation_flag_ again here. 2914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (cancellation_flag_.IsSet()) 2924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 2934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) KioskOemManifestParser::Manifest oem_manifest; 2954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!KioskOemManifestParser::Load(file, &oem_manifest)) { 2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG(WARNING) << "Unable to load OEM Manifest file: " << file.value(); 2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) machine_info_[kOemDeviceRequisitionKey] = 3004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) oem_manifest.device_requisition; 3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) machine_flags_[kOemIsEnterpriseManagedKey] = 3024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) oem_manifest.enterprise_managed; 3034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) machine_flags_[kOemCanExitEnterpriseEnrollmentKey] = 3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) oem_manifest.can_exit_enrollment; 3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) machine_flags_[kOemKeyboardDrivenOobeKey] = 3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) oem_manifest.keyboard_driven_oobe; 3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) oem_manifest_loaded_ = true; 3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) VLOG(1) << "Loaded OEM Manifest statistics from " << file.value(); 3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)StatisticsProviderImpl* StatisticsProviderImpl::GetInstance() { 3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return Singleton<StatisticsProviderImpl, 3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DefaultSingletonTraits<StatisticsProviderImpl> >::get(); 3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static StatisticsProvider* g_test_statistics_provider = NULL; 3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static 3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)StatisticsProvider* StatisticsProvider::GetInstance() { 3214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (g_test_statistics_provider) 3224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return g_test_statistics_provider; 3234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return StatisticsProviderImpl::GetInstance(); 3244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static 3274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void StatisticsProvider::SetTestProvider(StatisticsProvider* test_provider) { 3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) g_test_statistics_provider = test_provider; 3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace system 3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace chromeos 333