OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "base/sys_info.h" | 5 #include "base/sys_info.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/environment.h" | |
8 #include "base/file_util.h" | 9 #include "base/file_util.h" |
9 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
10 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
11 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
12 #include "base/strings/string_piece.h" | 13 #include "base/strings/string_piece.h" |
14 #include "base/strings/string_split.h" | |
13 #include "base/strings/string_tokenizer.h" | 15 #include "base/strings/string_tokenizer.h" |
16 #include "base/strings/string_util.h" | |
14 #include "base/threading/thread_restrictions.h" | 17 #include "base/threading/thread_restrictions.h" |
15 | 18 |
16 namespace base { | 19 namespace base { |
17 | 20 |
18 static const char* kLinuxStandardBaseVersionKeys[] = { | 21 namespace { |
22 | |
23 const char* kLinuxStandardBaseVersionKeys[] = { | |
19 "CHROMEOS_RELEASE_VERSION", | 24 "CHROMEOS_RELEASE_VERSION", |
20 "GOOGLE_RELEASE", | 25 "GOOGLE_RELEASE", |
21 "DISTRIB_RELEASE", | 26 "DISTRIB_RELEASE", |
22 NULL | |
23 }; | 27 }; |
28 const size_t kLinuxStandardBaseVersionKeysLength = | |
29 arraysize(kLinuxStandardBaseVersionKeys); | |
24 | 30 |
25 const char kLinuxStandardBaseReleaseFile[] = "/etc/lsb-release"; | 31 const char kLinuxStandardBaseReleaseFile[] = "/etc/lsb-release"; |
26 | 32 |
27 struct ChromeOSVersionNumbers { | 33 class ChromeOSVersionInfo { |
28 ChromeOSVersionNumbers() | 34 public: |
29 : major_version(0), | 35 ChromeOSVersionInfo() { |
30 minor_version(0), | 36 Parse(); |
31 bugfix_version(0), | |
32 parsed(false) { | |
33 } | 37 } |
34 | 38 |
35 int32 major_version; | 39 void Parse() { |
36 int32 minor_version; | 40 lsb_release_map_.clear(); |
37 int32 bugfix_version; | 41 major_version_ = 0; |
38 bool parsed; | 42 minor_version_ = 0; |
43 bugfix_version_ = 0; | |
44 | |
45 std::string lsb_release, lsb_release_time_str; | |
46 scoped_ptr<base::Environment> env(base::Environment::Create()); | |
47 bool parsed_from_env = | |
48 env->GetVar("LSB_RELEASE", &lsb_release) && | |
49 env->GetVar("LSB_RELEASE_TIME", &lsb_release_time_str); | |
Daniel Erat
2013/09/24 15:37:53
nit: move both of these to constants so you can sh
stevenjb
2013/09/24 17:18:34
Done.
| |
50 if (parsed_from_env) { | |
51 double us = 0; | |
52 StringToDouble(lsb_release_time_str, &us); | |
Daniel Erat
2013/09/24 15:37:53
check the return value and maybe log an error
stevenjb
2013/09/24 17:18:34
Added a test, but this occurs before logging is in
| |
53 lsb_release_time_ = base::Time::FromDoubleT(us); | |
54 } else { | |
55 // If the LSB_RELEASE and LSB_RELEASE_TIME environment variables are not | |
56 // set, fall back to a blocking read of the lsb_release file. This should | |
57 // only happen in non-chromeos environments. | |
Daniel Erat
2013/09/24 15:37:53
nit: s/chromeos/Chrome OS/
also, worthwhile calli
stevenjb
2013/09/24 17:18:34
Again, logging won't help, but we do set lsb-sourc
| |
58 ThreadRestrictions::ScopedAllowIO allow_io; | |
59 FilePath path(kLinuxStandardBaseReleaseFile); | |
60 ReadFileToString(path, &lsb_release); | |
61 base::PlatformFileInfo fileinfo; | |
62 if (file_util::GetFileInfo(path, &fileinfo)) | |
63 lsb_release_time_ = fileinfo.creation_time; | |
64 } | |
65 ParseLsbRelease(lsb_release); | |
66 // For debugging: | |
67 lsb_release_map_["lsb-source"] = parsed_from_env ? "env" : "file"; | |
Daniel Erat
2013/09/24 15:37:53
nit: move these strings to constants (assuming tha
stevenjb
2013/09/24 17:18:34
Made them constants, but we only display these in
| |
68 } | |
69 | |
70 bool GetLsbReleaseValue(const std::string& key, std::string* value) { | |
71 SysInfo::LsbReleaseMap::const_iterator iter = lsb_release_map_.find(key); | |
72 if (iter == lsb_release_map_.end()) | |
73 return false; | |
74 *value = iter->second; | |
75 return true; | |
76 } | |
77 | |
78 void GetVersionNumbers(int32* major_version, | |
79 int32* minor_version, | |
80 int32* bugfix_version) { | |
81 *major_version = major_version_; | |
82 *minor_version = minor_version_; | |
83 *bugfix_version = bugfix_version_; | |
84 } | |
85 | |
86 const base::Time& lsb_release_time() const { return lsb_release_time_; } | |
87 const SysInfo::LsbReleaseMap& lsb_release_map() const { | |
88 return lsb_release_map_; | |
89 } | |
90 | |
91 private: | |
92 void ParseLsbRelease(const std::string& lsb_release) { | |
93 // Parse lsb_release key pairs. | |
94 std::vector<std::pair<std::string, std::string> > pairs; | |
95 base::SplitStringIntoKeyValuePairs(lsb_release, '=', '\n', &pairs); | |
96 for (size_t i = 0; i < pairs.size(); ++i) { | |
Daniel Erat
2013/09/24 15:37:53
nit: remove extra space before '<'
stevenjb
2013/09/24 17:18:34
Done.
| |
97 std::string key, value; | |
98 TrimWhitespaceASCII(pairs[i].first, TRIM_ALL, &key); | |
99 TrimWhitespaceASCII(pairs[i].second, TRIM_ALL, &value); | |
100 if (key.empty()) | |
101 continue; | |
102 lsb_release_map_[key] = value; | |
103 } | |
104 // Parse the version from the first matching recognized version key. | |
105 std::string version; | |
106 for (size_t i = 0; i < kLinuxStandardBaseVersionKeysLength; ++i) { | |
107 std::string key = kLinuxStandardBaseVersionKeys[i]; | |
108 if (GetLsbReleaseValue(key, &version) && !version.empty()) | |
109 break; | |
110 } | |
111 StringTokenizer tokenizer(version, "."); | |
112 if (tokenizer.GetNext()) { | |
113 StringToInt(StringPiece(tokenizer.token_begin(), tokenizer.token_end()), | |
114 &major_version_); | |
115 } | |
116 if (tokenizer.GetNext()) { | |
117 StringToInt(StringPiece(tokenizer.token_begin(), tokenizer.token_end()), | |
118 &minor_version_); | |
119 } | |
120 if (tokenizer.GetNext()) { | |
121 StringToInt(StringPiece(tokenizer.token_begin(), tokenizer.token_end()), | |
122 &bugfix_version_); | |
123 } | |
124 } | |
125 | |
126 base::Time lsb_release_time_; | |
127 SysInfo::LsbReleaseMap lsb_release_map_; | |
pneubeck (no reviews)
2013/09/24 07:44:51
FWIW, before this change only a fixed amount of me
Daniel Erat
2013/09/24 15:37:53
fwiw, i don't think there's any harm in keeping al
stevenjb
2013/09/24 17:18:34
This is tiny, all things considered, but I added a
| |
128 int32 major_version_; | |
129 int32 minor_version_; | |
130 int32 bugfix_version_; | |
39 }; | 131 }; |
40 | 132 |
41 static LazyInstance<ChromeOSVersionNumbers> | 133 static LazyInstance<ChromeOSVersionInfo> |
42 g_chrome_os_version_numbers = LAZY_INSTANCE_INITIALIZER; | 134 g_chrome_os_version_info = LAZY_INSTANCE_INITIALIZER; |
135 | |
136 ChromeOSVersionInfo& GetChromeOSVersionInfo() { | |
137 return g_chrome_os_version_info.Get(); | |
138 } | |
139 | |
140 } // namespace | |
43 | 141 |
44 // static | 142 // static |
45 void SysInfo::OperatingSystemVersionNumbers(int32* major_version, | 143 void SysInfo::OperatingSystemVersionNumbers(int32* major_version, |
46 int32* minor_version, | 144 int32* minor_version, |
47 int32* bugfix_version) { | 145 int32* bugfix_version) { |
48 if (!g_chrome_os_version_numbers.Get().parsed) { | 146 return GetChromeOSVersionInfo().GetVersionNumbers( |
49 // The other implementations of SysInfo don't block on the disk. | 147 major_version, minor_version, bugfix_version); |
50 // See http://code.google.com/p/chromium/issues/detail?id=60394 | |
51 // Perhaps the caller ought to cache this? | |
52 // Temporary allowing while we work the bug out. | |
53 ThreadRestrictions::ScopedAllowIO allow_io; | |
54 | |
55 FilePath path(kLinuxStandardBaseReleaseFile); | |
56 std::string contents; | |
57 if (ReadFileToString(path, &contents)) { | |
58 g_chrome_os_version_numbers.Get().parsed = true; | |
59 ParseLsbRelease(contents, | |
60 &(g_chrome_os_version_numbers.Get().major_version), | |
61 &(g_chrome_os_version_numbers.Get().minor_version), | |
62 &(g_chrome_os_version_numbers.Get().bugfix_version)); | |
63 } | |
64 } | |
65 *major_version = g_chrome_os_version_numbers.Get().major_version; | |
66 *minor_version = g_chrome_os_version_numbers.Get().minor_version; | |
67 *bugfix_version = g_chrome_os_version_numbers.Get().bugfix_version; | |
68 } | 148 } |
69 | 149 |
70 // static | 150 // static |
71 std::string SysInfo::GetLinuxStandardBaseVersionKey() { | 151 const SysInfo::LsbReleaseMap& SysInfo::GetLsbReleaseMap() { |
72 return std::string(kLinuxStandardBaseVersionKeys[0]); | 152 return GetChromeOSVersionInfo().lsb_release_map(); |
73 } | 153 } |
74 | 154 |
75 // static | 155 // static |
76 void SysInfo::ParseLsbRelease(const std::string& lsb_release, | 156 bool SysInfo::GetLsbReleaseValue(const std::string& key, std::string* value) { |
77 int32* major_version, | 157 return GetChromeOSVersionInfo().GetLsbReleaseValue(key, value); |
78 int32* minor_version, | |
79 int32* bugfix_version) { | |
80 size_t version_key_index = std::string::npos; | |
81 for (int i = 0; kLinuxStandardBaseVersionKeys[i] != NULL; ++i) { | |
82 version_key_index = lsb_release.find(kLinuxStandardBaseVersionKeys[i]); | |
83 if (std::string::npos != version_key_index) { | |
84 break; | |
85 } | |
86 } | |
87 if (std::string::npos == version_key_index) { | |
88 return; | |
89 } | |
90 | |
91 size_t start_index = lsb_release.find_first_of('=', version_key_index); | |
92 start_index++; // Move past '='. | |
93 size_t length = lsb_release.find_first_of('\n', start_index) - start_index; | |
94 std::string version = lsb_release.substr(start_index, length); | |
95 StringTokenizer tokenizer(version, "."); | |
96 for (int i = 0; i < 3 && tokenizer.GetNext(); ++i) { | |
97 if (0 == i) { | |
98 StringToInt(StringPiece(tokenizer.token_begin(), | |
99 tokenizer.token_end()), | |
100 major_version); | |
101 *minor_version = *bugfix_version = 0; | |
102 } else if (1 == i) { | |
103 StringToInt(StringPiece(tokenizer.token_begin(), | |
104 tokenizer.token_end()), | |
105 minor_version); | |
106 } else { // 2 == i | |
107 StringToInt(StringPiece(tokenizer.token_begin(), | |
108 tokenizer.token_end()), | |
109 bugfix_version); | |
110 } | |
111 } | |
112 } | 158 } |
113 | 159 |
114 // static | 160 // static |
115 FilePath SysInfo::GetLsbReleaseFilePath() { | 161 std::string SysInfo::GetLsbReleaseBoard() { |
116 return FilePath(kLinuxStandardBaseReleaseFile); | 162 const char kMachineInfoBoard[] = "CHROMEOS_RELEASE_BOARD"; |
163 std::string board; | |
164 if (!GetLsbReleaseValue(kMachineInfoBoard, &board)) | |
165 board = "unknown"; | |
166 return board; | |
167 } | |
168 | |
169 // static | |
170 base::Time SysInfo::GetLsbReleaseTime() { | |
171 return GetChromeOSVersionInfo().lsb_release_time(); | |
172 } | |
173 | |
174 // static | |
175 void SysInfo::SetChromeOSVersionInfoForTest(const std::string& lsb_release, | |
176 double lsb_release_time) { | |
177 scoped_ptr<base::Environment> env(base::Environment::Create()); | |
178 env->SetVar("LSB_RELEASE", lsb_release); | |
179 // LSB_RELEASE_TIME must be set to read LSB_RELEASE from the env. | |
180 env->SetVar("LSB_RELEASE_TIME", base::DoubleToString(lsb_release_time)); | |
181 g_chrome_os_version_info.Get().Parse(); | |
117 } | 182 } |
118 | 183 |
119 } // namespace base | 184 } // namespace base |
OLD | NEW |