| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/chromeos/system_access.h" | 5 #include "chrome/browser/chromeos/system_access.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | |
| 8 #include "base/command_line.h" | |
| 9 #include "base/file_path.h" | 7 #include "base/file_path.h" |
| 10 #include "base/file_util.h" | 8 #include "base/file_util.h" |
| 11 #include "base/logging.h" | 9 #include "base/logging.h" |
| 12 #include "base/process_util.h" | 10 #include "base/observer_list.h" |
| 13 #include "base/string_tokenizer.h" | 11 #include "base/memory/scoped_ptr.h" |
| 14 #include "base/string_util.h" | 12 #include "base/memory/singleton.h" |
| 15 #include "base/threading/thread_restrictions.h" | |
| 16 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
| 14 #include "chrome/browser/chromeos/name_value_pairs_parser.h" |
| 17 | 15 |
| 18 namespace chromeos { // NOLINT | 16 namespace chromeos { // NOLINT |
| 19 | 17 |
| 20 namespace { // NOLINT | 18 namespace { // NOLINT |
| 21 | 19 |
| 22 // The filepath to the timezone file that symlinks to the actual timezone file. | 20 // The filepath to the timezone file that symlinks to the actual timezone file. |
| 23 static const char kTimezoneSymlink[] = "/var/lib/timezone/localtime"; | 21 const char kTimezoneSymlink[] = "/var/lib/timezone/localtime"; |
| 24 static const char kTimezoneSymlink2[] = "/var/lib/timezone/localtime2"; | 22 const char kTimezoneSymlink2[] = "/var/lib/timezone/localtime2"; |
| 25 | 23 |
| 26 // The directory that contains all the timezone files. So for timezone | 24 // The directory that contains all the timezone files. So for timezone |
| 27 // "US/Pacific", the actual timezone file is: "/usr/share/zoneinfo/US/Pacific" | 25 // "US/Pacific", the actual timezone file is: "/usr/share/zoneinfo/US/Pacific" |
| 28 static const char kTimezoneFilesDir[] = "/usr/share/zoneinfo/"; | 26 const char kTimezoneFilesDir[] = "/usr/share/zoneinfo/"; |
| 29 | 27 |
| 30 // The system command that returns the hardware class. | 28 // The system command that returns the hardware class. |
| 31 static const char kHardwareClassKey[] = "hardware_class"; | 29 const char kHardwareClassKey[] = "hardware_class"; |
| 32 static const char* kHardwareClassTool[] = { "/usr/bin/hardware_class" }; | 30 const char* kHardwareClassTool[] = { "/usr/bin/hardware_class" }; |
| 33 static const char kUnknownHardwareClass[] = "unknown"; | 31 const char kUnknownHardwareClass[] = "unknown"; |
| 34 | 32 |
| 35 // Command to get machine hardware info and key/value delimiters. | 33 // Command to get machine hardware info and key/value delimiters. |
| 36 // /tmp/machine-info is generated by platform/init/chromeos_startup. | 34 // /tmp/machine-info is generated by platform/init/chromeos_startup. |
| 37 static const char* kMachineHardwareInfoTool[] = { "cat", "/tmp/machine-info" }; | 35 const char* kMachineHardwareInfoTool[] = { "cat", "/tmp/machine-info" }; |
| 38 static const char kMachineHardwareInfoEq[] = "="; | 36 const char kMachineHardwareInfoEq[] = "="; |
| 39 static const char kMachineHardwareInfoDelim[] = " \n"; | 37 const char kMachineHardwareInfoDelim[] = " \n"; |
| 40 | 38 |
| 41 // Command to get machine OS info and key/value delimiters. | 39 // Command to get machine OS info and key/value delimiters. |
| 42 static const char* kMachineOSInfoTool[] = { "cat", "/etc/lsb-release" }; | 40 const char* kMachineOSInfoTool[] = { "cat", "/etc/lsb-release" }; |
| 43 static const char kMachineOSInfoEq[] = "="; | 41 const char kMachineOSInfoEq[] = "="; |
| 44 static const char kMachineOSInfoDelim[] = "\n"; | 42 const char kMachineOSInfoDelim[] = "\n"; |
| 43 |
| 44 // Command to get HWID and key. |
| 45 const char kHwidKey[] = "hwid"; |
| 46 const char* kHwidTool[] = { "cat", "/sys/devices/platform/chromeos_acpi/HWID" }; |
| 47 |
| 48 // Command to get VPD info and key/value delimiters. |
| 49 const char* kVpdTool[] = { "cat", "/var/log/vpd_2.0.txt" }; |
| 50 const char kVpdEq[] = "="; |
| 51 const char kVpdDelim[] = "\n"; |
| 45 | 52 |
| 46 // Fallback time zone ID used in case of an unexpected error. | 53 // Fallback time zone ID used in case of an unexpected error. |
| 47 static const char kFallbackTimeZoneId[] = "America/Los_Angeles"; | 54 const char kFallbackTimeZoneId[] = "America/Los_Angeles"; |
| 55 |
| 56 class SystemAccessImpl : public SystemAccess { |
| 57 public: |
| 58 // SystemAccess.implementation: |
| 59 virtual const icu::TimeZone& GetTimezone(); |
| 60 virtual void SetTimezone(const icu::TimeZone& timezone); |
| 61 virtual bool GetMachineStatistic(const std::string& name, |
| 62 std::string* result); |
| 63 virtual void AddObserver(Observer* observer); |
| 64 virtual void RemoveObserver(Observer* observer); |
| 65 |
| 66 static SystemAccessImpl* GetInstance(); |
| 67 |
| 68 private: |
| 69 friend struct DefaultSingletonTraits<SystemAccessImpl>; |
| 70 |
| 71 SystemAccessImpl(); |
| 72 |
| 73 // Updates the machine statistcs by examining the system. |
| 74 void UpdateMachineStatistics(); |
| 75 |
| 76 scoped_ptr<icu::TimeZone> timezone_; |
| 77 ObserverList<Observer> observers_; |
| 78 NameValuePairsParser::NameValueMap machine_info_; |
| 79 |
| 80 DISALLOW_COPY_AND_ASSIGN(SystemAccessImpl); |
| 81 }; |
| 48 | 82 |
| 49 std::string GetTimezoneIDAsString() { | 83 std::string GetTimezoneIDAsString() { |
| 50 // Look at kTimezoneSymlink, see which timezone we are symlinked to. | 84 // Look at kTimezoneSymlink, see which timezone we are symlinked to. |
| 51 char buf[256]; | 85 char buf[256]; |
| 52 const ssize_t len = readlink(kTimezoneSymlink, buf, | 86 const ssize_t len = readlink(kTimezoneSymlink, buf, |
| 53 sizeof(buf)-1); | 87 sizeof(buf)-1); |
| 54 if (len == -1) { | 88 if (len == -1) { |
| 55 LOG(ERROR) << "GetTimezoneID: Cannot read timezone symlink " | 89 LOG(ERROR) << "GetTimezoneID: Cannot read timezone symlink " |
| 56 << kTimezoneSymlink; | 90 << kTimezoneSymlink; |
| 57 return std::string(); | 91 return std::string(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 } | 130 } |
| 97 | 131 |
| 98 // Move symlink2 to symlink. | 132 // Move symlink2 to symlink. |
| 99 if (!file_util::ReplaceFile(timezone_symlink2, timezone_symlink)) { | 133 if (!file_util::ReplaceFile(timezone_symlink2, timezone_symlink)) { |
| 100 LOG(ERROR) << "SetTimezoneID: Unable to move symlink " | 134 LOG(ERROR) << "SetTimezoneID: Unable to move symlink " |
| 101 << timezone_symlink2.value() << " to " | 135 << timezone_symlink2.value() << " to " |
| 102 << timezone_symlink.value(); | 136 << timezone_symlink.value(); |
| 103 } | 137 } |
| 104 } | 138 } |
| 105 | 139 |
| 106 } // namespace | 140 const icu::TimeZone& SystemAccessImpl::GetTimezone() { |
| 107 | |
| 108 SystemAccess* SystemAccess::GetInstance() { | |
| 109 return Singleton<SystemAccess, DefaultSingletonTraits<SystemAccess> >::get(); | |
| 110 } | |
| 111 | |
| 112 const icu::TimeZone& SystemAccess::GetTimezone() { | |
| 113 return *timezone_.get(); | 141 return *timezone_.get(); |
| 114 } | 142 } |
| 115 | 143 |
| 116 void SystemAccess::SetTimezone(const icu::TimeZone& timezone) { | 144 void SystemAccessImpl::SetTimezone(const icu::TimeZone& timezone) { |
| 117 timezone_.reset(timezone.clone()); | 145 timezone_.reset(timezone.clone()); |
| 118 icu::UnicodeString unicode; | 146 icu::UnicodeString unicode; |
| 119 timezone.getID(unicode); | 147 timezone.getID(unicode); |
| 120 std::string id; | 148 std::string id; |
| 121 UTF16ToUTF8(unicode.getBuffer(), unicode.length(), &id); | 149 UTF16ToUTF8(unicode.getBuffer(), unicode.length(), &id); |
| 122 VLOG(1) << "Setting timezone to " << id; | 150 VLOG(1) << "Setting timezone to " << id; |
| 123 chromeos::SetTimezoneIDFromString(id); | 151 chromeos::SetTimezoneIDFromString(id); |
| 124 icu::TimeZone::setDefault(timezone); | 152 icu::TimeZone::setDefault(timezone); |
| 125 FOR_EACH_OBSERVER(Observer, observers_, TimezoneChanged(timezone)); | 153 FOR_EACH_OBSERVER(Observer, observers_, TimezoneChanged(timezone)); |
| 126 } | 154 } |
| 127 | 155 |
| 128 bool SystemAccess::GetMachineStatistic( | 156 bool SystemAccessImpl::GetMachineStatistic( |
| 129 const std::string& name, std::string* result) { | 157 const std::string& name, std::string* result) { |
| 130 MachineInfo::iterator iter = machine_info_.find(name); | 158 NameValuePairsParser::NameValueMap::iterator iter = machine_info_.find(name); |
| 131 if (iter != machine_info_.end()) { | 159 if (iter != machine_info_.end()) { |
| 132 *result = iter->second; | 160 *result = iter->second; |
| 133 return true; | 161 return true; |
| 134 } | 162 } |
| 135 return false; | 163 return false; |
| 136 } | 164 } |
| 137 | 165 |
| 138 void SystemAccess::AddObserver(Observer* observer) { | 166 void SystemAccessImpl::AddObserver(Observer* observer) { |
| 139 observers_.AddObserver(observer); | 167 observers_.AddObserver(observer); |
| 140 } | 168 } |
| 141 | 169 |
| 142 void SystemAccess::RemoveObserver(Observer* observer) { | 170 void SystemAccessImpl::RemoveObserver(Observer* observer) { |
| 143 observers_.RemoveObserver(observer); | 171 observers_.RemoveObserver(observer); |
| 144 } | 172 } |
| 145 | 173 |
| 146 SystemAccess::SystemAccess() { | 174 SystemAccessImpl::SystemAccessImpl() { |
| 147 // Get Statistics | 175 // Get Statistics |
| 148 UpdateMachineStatistics(); | 176 UpdateMachineStatistics(); |
| 149 // Get Timezone | 177 // Get Timezone |
| 150 std::string id = GetTimezoneIDAsString(); | 178 std::string id = GetTimezoneIDAsString(); |
| 151 if (id.empty()) { | 179 if (id.empty()) { |
| 152 id = kFallbackTimeZoneId; | 180 id = kFallbackTimeZoneId; |
| 153 LOG(ERROR) << "Got an empty string for timezone, default to " << id; | 181 LOG(ERROR) << "Got an empty string for timezone, default to " << id; |
| 154 } | 182 } |
| 155 icu::TimeZone* timezone = | 183 icu::TimeZone* timezone = |
| 156 icu::TimeZone::createTimeZone(icu::UnicodeString::fromUTF8(id)); | 184 icu::TimeZone::createTimeZone(icu::UnicodeString::fromUTF8(id)); |
| 157 timezone_.reset(timezone); | 185 timezone_.reset(timezone); |
| 158 icu::TimeZone::setDefault(*timezone); | 186 icu::TimeZone::setDefault(*timezone); |
| 159 VLOG(1) << "Timezone is " << id; | 187 VLOG(1) << "Timezone is " << id; |
| 160 } | 188 } |
| 161 | 189 |
| 162 void SystemAccess::UpdateMachineStatistics() { | 190 void SystemAccessImpl::UpdateMachineStatistics() { |
| 163 NameValuePairsParser parser(&machine_info_); | 191 NameValuePairsParser parser(&machine_info_); |
| 164 if (!parser.GetSingleValueFromTool(arraysize(kHardwareClassTool), | 192 if (!parser.GetSingleValueFromTool(arraysize(kHardwareClassTool), |
| 165 kHardwareClassTool, | 193 kHardwareClassTool, |
| 166 kHardwareClassKey)) { | 194 kHardwareClassKey)) { |
| 167 // Use kUnknownHardwareClass if the hardware class command fails. | 195 // Use kUnknownHardwareClass if the hardware class command fails. |
| 168 parser.AddNameValuePair(kHardwareClassKey, kUnknownHardwareClass); | 196 parser.AddNameValuePair(kHardwareClassKey, kUnknownHardwareClass); |
| 169 } | 197 } |
| 170 parser.ParseNameValuePairsFromTool(arraysize(kMachineHardwareInfoTool), | 198 parser.ParseNameValuePairsFromTool(arraysize(kMachineHardwareInfoTool), |
| 171 kMachineHardwareInfoTool, | 199 kMachineHardwareInfoTool, |
| 172 kMachineHardwareInfoEq, | 200 kMachineHardwareInfoEq, |
| 173 kMachineHardwareInfoDelim); | 201 kMachineHardwareInfoDelim); |
| 174 parser.ParseNameValuePairsFromTool(arraysize(kMachineOSInfoTool), | 202 parser.ParseNameValuePairsFromTool(arraysize(kMachineOSInfoTool), |
| 175 kMachineOSInfoTool, | 203 kMachineOSInfoTool, |
| 176 kMachineOSInfoEq, | 204 kMachineOSInfoEq, |
| 177 kMachineOSInfoDelim); | 205 kMachineOSInfoDelim); |
| 206 parser.GetSingleValueFromTool(arraysize(kHwidTool), kHwidTool, kHwidKey); |
| 207 parser.ParseNameValuePairsFromTool( |
| 208 arraysize(kVpdTool), kVpdTool, kVpdEq, kVpdDelim); |
| 178 } | 209 } |
| 179 | 210 |
| 180 NameValuePairsParser::NameValuePairsParser(MachineInfo* machine_info) | 211 SystemAccessImpl* SystemAccessImpl::GetInstance() { |
| 181 : machine_info_(machine_info) { | 212 return Singleton<SystemAccessImpl, |
| 213 DefaultSingletonTraits<SystemAccessImpl> >::get(); |
| 182 } | 214 } |
| 183 | 215 |
| 184 void NameValuePairsParser::AddNameValuePair(const std::string& key, | 216 } // namespace |
| 185 const std::string& value) { | |
| 186 (*machine_info_)[key] = value; | |
| 187 VLOG(1) << "name: " << key << ", value: " << value; | |
| 188 } | |
| 189 | 217 |
| 190 bool NameValuePairsParser::ParseNameValuePairs(const std::string& in_string, | 218 SystemAccess* SystemAccess::GetInstance() { |
| 191 const std::string& eq, | 219 return SystemAccessImpl::GetInstance(); |
| 192 const std::string& delim) { | |
| 193 // Set up the pair tokenizer. | |
| 194 StringTokenizer pair_toks(in_string, delim); | |
| 195 pair_toks.set_quote_chars("\""); | |
| 196 // Process token pairs. | |
| 197 while (pair_toks.GetNext()) { | |
| 198 std::string pair(pair_toks.token()); | |
| 199 if (pair.find(eq) == 0) { | |
| 200 LOG(WARNING) << "Empty key: '" << pair << "'. Aborting."; | |
| 201 return false; | |
| 202 } | |
| 203 StringTokenizer keyvalue(pair, eq); | |
| 204 std::string key,value; | |
| 205 if (keyvalue.GetNext()) { | |
| 206 key = keyvalue.token(); | |
| 207 if (keyvalue.GetNext()) { | |
| 208 value = keyvalue.token(); | |
| 209 if (keyvalue.GetNext()) { | |
| 210 LOG(WARNING) << "Multiple key tokens: '" << pair << "'. Aborting."; | |
| 211 return false; | |
| 212 } | |
| 213 } | |
| 214 } | |
| 215 if (key.empty()) { | |
| 216 LOG(WARNING) << "Invalid token pair: '" << pair << "'. Aborting."; | |
| 217 return false; | |
| 218 } | |
| 219 AddNameValuePair(key, value); | |
| 220 } | |
| 221 return true; | |
| 222 } | |
| 223 | |
| 224 bool NameValuePairsParser::GetSingleValueFromTool(int argc, | |
| 225 const char* argv[], | |
| 226 const std::string& key) { | |
| 227 CommandLine command_line(argc, argv); | |
| 228 std::string output_string; | |
| 229 // TODO(stevenjb,satorux): Make this non blocking: crosbug.com/5603. | |
| 230 base::ThreadRestrictions::ScopedAllowIO allow_io_for_thread_join; | |
| 231 if (argc < 1 || !base::GetAppOutput(command_line, &output_string)) { | |
| 232 LOG(WARNING) << "Error excuting: " << command_line.command_line_string(); | |
| 233 return false; | |
| 234 } | |
| 235 TrimWhitespaceASCII(output_string, TRIM_ALL, &output_string); | |
| 236 AddNameValuePair(key, output_string); | |
| 237 return true; | |
| 238 } | |
| 239 | |
| 240 bool NameValuePairsParser::ParseNameValuePairsFromTool( | |
| 241 int argc, | |
| 242 const char* argv[], | |
| 243 const std::string& eq, | |
| 244 const std::string& delim) { | |
| 245 CommandLine command_line(argc, argv); | |
| 246 std::string output_string; | |
| 247 // TODO(stevenjb,satorux): Make this non blocking: crosbug.com/5603. | |
| 248 base::ThreadRestrictions::ScopedAllowIO allow_io_for_thread_join; | |
| 249 if (argc < 1 || !base::GetAppOutput(command_line, &output_string)) { | |
| 250 LOG(WARNING) << "Error excuting: " << command_line.command_line_string(); | |
| 251 return false; | |
| 252 } | |
| 253 if (!ParseNameValuePairs(output_string, eq, delim)) { | |
| 254 LOG(WARNING) << "Error parsing values while excuting: " | |
| 255 << command_line.command_line_string(); | |
| 256 return false; | |
| 257 } | |
| 258 return true; | |
| 259 } | 220 } |
| 260 | 221 |
| 261 } // namespace chromeos | 222 } // namespace chromeos |
| OLD | NEW |