blob: 9d7505e25682f8c33b1f82fb4f8c7cbd06e03c66 [file] [log] [blame]
khorimoto@chromium.orgc7e4e002012-04-25 10:59:44 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
evan@chromium.org54b72102009-07-22 09:35:18 +09002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/sys_info.h"
6
7#include "base/basictypes.h"
stevenjb@chromium.org2f4de042013-09-27 06:51:23 +09008#include "base/environment.h"
evan@chromium.org54b72102009-07-22 09:35:18 +09009#include "base/file_util.h"
brettw@chromium.org59eef1f2013-02-24 14:40:52 +090010#include "base/files/file_path.h"
dgozman@chromium.org4fadf422011-04-05 20:31:42 +090011#include "base/lazy_instance.h"
brettw@chromium.orgabcde5c2013-02-07 11:57:22 +090012#include "base/strings/string_number_conversions.h"
tfarina@chromium.orgb6d49112013-03-30 23:29:00 +090013#include "base/strings/string_piece.h"
stevenjb@chromium.org2f4de042013-09-27 06:51:23 +090014#include "base/strings/string_split.h"
brettw@chromium.org2cbc2872013-02-02 09:21:39 +090015#include "base/strings/string_tokenizer.h"
stevenjb@chromium.org2f4de042013-09-27 06:51:23 +090016#include "base/strings/string_util.h"
brettw@chromium.org5b5f5e02011-01-01 10:01:06 +090017#include "base/threading/thread_restrictions.h"
evan@chromium.org54b72102009-07-22 09:35:18 +090018
19namespace base {
20
stevenjb@chromium.org2f4de042013-09-27 06:51:23 +090021namespace {
22
23const char* kLinuxStandardBaseVersionKeys[] = {
dgozman@chromium.org4fadf422011-04-05 20:31:42 +090024 "CHROMEOS_RELEASE_VERSION",
25 "GOOGLE_RELEASE",
26 "DISTRIB_RELEASE",
dgozman@chromium.org4fadf422011-04-05 20:31:42 +090027};
stevenjb@chromium.org2f4de042013-09-27 06:51:23 +090028const size_t kLinuxStandardBaseVersionKeysLength =
29 arraysize(kLinuxStandardBaseVersionKeys);
evan@chromium.org54b72102009-07-22 09:35:18 +090030
31const char kLinuxStandardBaseReleaseFile[] = "/etc/lsb-release";
32
stevenjb@chromium.org2f4de042013-09-27 06:51:23 +090033const char kLsbReleaseKey[] = "LSB_RELEASE";
34const char kLsbReleaseTimeKey[] = "LSB_RELEASE_TIME"; // Seconds since epoch
35
36const char kLsbReleaseSourceKey[] = "lsb-release";
37const char kLsbReleaseSourceEnv[] = "env";
38const char kLsbReleaseSourceFile[] = "file";
39
40class ChromeOSVersionInfo {
41 public:
42 ChromeOSVersionInfo() {
43 Parse();
dgozman@chromium.org4fadf422011-04-05 20:31:42 +090044 }
45
stevenjb@chromium.org2f4de042013-09-27 06:51:23 +090046 void Parse() {
47 lsb_release_map_.clear();
48 major_version_ = 0;
49 minor_version_ = 0;
50 bugfix_version_ = 0;
51
52 std::string lsb_release, lsb_release_time_str;
53 scoped_ptr<base::Environment> env(base::Environment::Create());
54 bool parsed_from_env =
55 env->GetVar(kLsbReleaseKey, &lsb_release) &&
56 env->GetVar(kLsbReleaseTimeKey, &lsb_release_time_str);
57 if (parsed_from_env) {
58 double us = 0;
59 if (StringToDouble(lsb_release_time_str, &us))
60 lsb_release_time_ = base::Time::FromDoubleT(us);
61 } else {
62 // If the LSB_RELEASE and LSB_RELEASE_TIME environment variables are not
63 // set, fall back to a blocking read of the lsb_release file. This should
64 // only happen in non Chrome OS environments.
65 ThreadRestrictions::ScopedAllowIO allow_io;
66 FilePath path(kLinuxStandardBaseReleaseFile);
67 ReadFileToString(path, &lsb_release);
68 base::PlatformFileInfo fileinfo;
69 if (file_util::GetFileInfo(path, &fileinfo))
70 lsb_release_time_ = fileinfo.creation_time;
71 }
72 ParseLsbRelease(lsb_release);
73 // For debugging:
74 lsb_release_map_[kLsbReleaseSourceKey] =
75 parsed_from_env ? kLsbReleaseSourceEnv : kLsbReleaseSourceFile;
76 }
77
78 bool GetLsbReleaseValue(const std::string& key, std::string* value) {
79 SysInfo::LsbReleaseMap::const_iterator iter = lsb_release_map_.find(key);
80 if (iter == lsb_release_map_.end())
81 return false;
82 *value = iter->second;
83 return true;
84 }
85
86 void GetVersionNumbers(int32* major_version,
87 int32* minor_version,
88 int32* bugfix_version) {
89 *major_version = major_version_;
90 *minor_version = minor_version_;
91 *bugfix_version = bugfix_version_;
92 }
93
94 const base::Time& lsb_release_time() const { return lsb_release_time_; }
95 const SysInfo::LsbReleaseMap& lsb_release_map() const {
96 return lsb_release_map_;
97 }
98
99 private:
100 void ParseLsbRelease(const std::string& lsb_release) {
101 // Parse and cache lsb_release key pairs. There should only be a handful
102 // of entries so the overhead for this will be small, and it can be
103 // useful for debugging.
104 std::vector<std::pair<std::string, std::string> > pairs;
105 base::SplitStringIntoKeyValuePairs(lsb_release, '=', '\n', &pairs);
106 for (size_t i = 0; i < pairs.size(); ++i) {
107 std::string key, value;
108 TrimWhitespaceASCII(pairs[i].first, TRIM_ALL, &key);
109 TrimWhitespaceASCII(pairs[i].second, TRIM_ALL, &value);
110 if (key.empty())
111 continue;
112 lsb_release_map_[key] = value;
113 }
114 // Parse the version from the first matching recognized version key.
115 std::string version;
116 for (size_t i = 0; i < kLinuxStandardBaseVersionKeysLength; ++i) {
117 std::string key = kLinuxStandardBaseVersionKeys[i];
118 if (GetLsbReleaseValue(key, &version) && !version.empty())
119 break;
120 }
121 StringTokenizer tokenizer(version, ".");
122 if (tokenizer.GetNext()) {
123 StringToInt(StringPiece(tokenizer.token_begin(), tokenizer.token_end()),
124 &major_version_);
125 }
126 if (tokenizer.GetNext()) {
127 StringToInt(StringPiece(tokenizer.token_begin(), tokenizer.token_end()),
128 &minor_version_);
129 }
130 if (tokenizer.GetNext()) {
131 StringToInt(StringPiece(tokenizer.token_begin(), tokenizer.token_end()),
132 &bugfix_version_);
133 }
134 }
135
136 base::Time lsb_release_time_;
137 SysInfo::LsbReleaseMap lsb_release_map_;
138 int32 major_version_;
139 int32 minor_version_;
140 int32 bugfix_version_;
dgozman@chromium.org4fadf422011-04-05 20:31:42 +0900141};
142
stevenjb@chromium.org2f4de042013-09-27 06:51:23 +0900143static LazyInstance<ChromeOSVersionInfo>
144 g_chrome_os_version_info = LAZY_INSTANCE_INITIALIZER;
145
146ChromeOSVersionInfo& GetChromeOSVersionInfo() {
147 return g_chrome_os_version_info.Get();
148}
149
150} // namespace
dgozman@chromium.org4fadf422011-04-05 20:31:42 +0900151
evan@chromium.org54b72102009-07-22 09:35:18 +0900152// static
pkasting@chromium.org271d9db2011-04-08 07:15:34 +0900153void SysInfo::OperatingSystemVersionNumbers(int32* major_version,
154 int32* minor_version,
155 int32* bugfix_version) {
stevenjb@chromium.org2f4de042013-09-27 06:51:23 +0900156 return GetChromeOSVersionInfo().GetVersionNumbers(
157 major_version, minor_version, bugfix_version);
evan@chromium.org54b72102009-07-22 09:35:18 +0900158}
159
160// static
stevenjb@chromium.org2f4de042013-09-27 06:51:23 +0900161const SysInfo::LsbReleaseMap& SysInfo::GetLsbReleaseMap() {
162 return GetChromeOSVersionInfo().lsb_release_map();
evan@chromium.org54b72102009-07-22 09:35:18 +0900163}
164
165// static
stevenjb@chromium.org2f4de042013-09-27 06:51:23 +0900166bool SysInfo::GetLsbReleaseValue(const std::string& key, std::string* value) {
167 return GetChromeOSVersionInfo().GetLsbReleaseValue(key, value);
evan@chromium.org54b72102009-07-22 09:35:18 +0900168}
169
khorimoto@chromium.orgc7e4e002012-04-25 10:59:44 +0900170// static
stevenjb@chromium.org2f4de042013-09-27 06:51:23 +0900171std::string SysInfo::GetLsbReleaseBoard() {
172 const char kMachineInfoBoard[] = "CHROMEOS_RELEASE_BOARD";
173 std::string board;
174 if (!GetLsbReleaseValue(kMachineInfoBoard, &board))
175 board = "unknown";
176 return board;
177}
178
179// static
180base::Time SysInfo::GetLsbReleaseTime() {
181 return GetChromeOSVersionInfo().lsb_release_time();
182}
183
184// static
185void SysInfo::SetChromeOSVersionInfoForTest(const std::string& lsb_release,
186 const Time& lsb_release_time) {
187 scoped_ptr<base::Environment> env(base::Environment::Create());
188 env->SetVar(kLsbReleaseKey, lsb_release);
189 env->SetVar(kLsbReleaseTimeKey,
190 base::DoubleToString(lsb_release_time.ToDoubleT()));
191 g_chrome_os_version_info.Get().Parse();
khorimoto@chromium.orgc7e4e002012-04-25 10:59:44 +0900192}
193
evan@chromium.org54b72102009-07-22 09:35:18 +0900194} // namespace base