version_loader.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 3// found in the LICENSE file. 4 5#include "chrome/browser/chromeos/version_loader.h" 6 7#include <vector> 8 9#include "base/bind.h" 10#include "base/file_path.h" 11#include "base/file_util.h" 12#include "base/message_loop.h" 13#include "base/string_split.h" 14#include "base/string_util.h" 15#include "base/stringprintf.h" 16#include "base/threading/thread.h" 17#include "base/time.h" 18#include "chrome/browser/browser_process.h" 19#include "content/public/browser/browser_thread.h" 20 21using content::BrowserThread; 22 23namespace chromeos { 24 25// File to look for version number in. 26static const char kPathVersion[] = "/etc/lsb-release"; 27 28// File to look for firmware number in. 29static const char kPathFirmware[] = "/var/log/bios_info.txt"; 30 31VersionLoader::VersionLoader() : backend_(new Backend()) {} 32 33VersionLoader::~VersionLoader() {} 34 35// Beginning of line we look for that gives full version number. 36// Format: x.x.xx.x (Developer|Official build extra info) board info 37// static 38const char VersionLoader::kFullVersionPrefix[] = 39 "CHROMEOS_RELEASE_DESCRIPTION="; 40 41// Same but for short version (x.x.xx.x). 42// static 43const char VersionLoader::kVersionPrefix[] = "CHROMEOS_RELEASE_VERSION="; 44 45// Beginning of line we look for that gives the firmware version. 46const char VersionLoader::kFirmwarePrefix[] = "version"; 47 48VersionLoader::Handle VersionLoader::GetVersion( 49 CancelableRequestConsumerBase* consumer, 50 const VersionLoader::GetVersionCallback& callback, 51 VersionFormat format) { 52 if (!BrowserThread::IsMessageLoopValid(BrowserThread::FILE)) { 53 // This should only happen if Chrome is shutting down, so we don't do 54 // anything. 55 return 0; 56 } 57 58 scoped_refptr<GetVersionRequest> request(new GetVersionRequest(callback)); 59 AddRequest(request, consumer); 60 61 BrowserThread::PostTask( 62 BrowserThread::FILE, FROM_HERE, 63 base::Bind(&Backend::GetVersion, backend_.get(), request, format)); 64 return request->handle(); 65} 66 67VersionLoader::Handle VersionLoader::GetFirmware( 68 CancelableRequestConsumerBase* consumer, 69 const VersionLoader::GetFirmwareCallback& callback) { 70 if (!BrowserThread::IsMessageLoopValid(BrowserThread::FILE)) { 71 // This should only happen if Chrome is shutting down, so we don't do 72 // anything. 73 return 0; 74 } 75 76 scoped_refptr<GetFirmwareRequest> request(new GetFirmwareRequest(callback)); 77 AddRequest(request, consumer); 78 79 BrowserThread::PostTask( 80 BrowserThread::FILE, FROM_HERE, 81 base::Bind(&Backend::GetFirmware, backend_.get(), request)); 82 return request->handle(); 83} 84 85// static 86std::string VersionLoader::ParseVersion(const std::string& contents, 87 const std::string& prefix) { 88 // The file contains lines such as: 89 // XXX=YYY 90 // AAA=ZZZ 91 // Split the lines and look for the one that starts with prefix. The version 92 // file is small, which is why we don't try and be tricky. 93 std::vector<std::string> lines; 94 base::SplitString(contents, '\n', &lines); 95 for (size_t i = 0; i < lines.size(); ++i) { 96 if (StartsWithASCII(lines[i], prefix, false)) { 97 std::string version = lines[i].substr(std::string(prefix).size()); 98 if (version.size() > 1 && version[0] == '"' && 99 version[version.size() - 1] == '"') { 100 // Trim trailing and leading quotes. 101 version = version.substr(1, version.size() - 2); 102 } 103 return version; 104 } 105 } 106 return std::string(); 107} 108 109// static 110std::string VersionLoader::ParseFirmware(const std::string& contents) { 111 // The file contains lines such as: 112 // vendor | ... 113 // version | ... 114 // release_date | ... 115 // We don't make any assumption that the spaces between "version" and "|" is 116 // fixed. So we just match kFirmwarePrefix at the start of the line and find 117 // the first character that is not "|" or space 118 119 std::vector<std::string> lines; 120 base::SplitString(contents, '\n', &lines); 121 for (size_t i = 0; i < lines.size(); ++i) { 122 if (StartsWithASCII(lines[i], kFirmwarePrefix, false)) { 123 std::string str = lines[i].substr(std::string(kFirmwarePrefix).size()); 124 size_t found = str.find_first_not_of("| "); 125 if (found != std::string::npos) 126 return str.substr(found); 127 } 128 } 129 return std::string(); 130} 131 132void VersionLoader::Backend::GetVersion( 133 scoped_refptr<GetVersionRequest> request, 134 VersionFormat format) { 135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 136 if (request->canceled()) 137 return; 138 139 std::string version; 140 std::string contents; 141 const FilePath file_path(kPathVersion); 142 if (file_util::ReadFileToString(file_path, &contents)) { 143 version = ParseVersion( 144 contents, 145 (format == VERSION_FULL) ? kFullVersionPrefix : kVersionPrefix); 146 } 147 148 if (format == VERSION_SHORT_WITH_DATE) { 149 base::PlatformFileInfo fileinfo; 150 if (file_util::GetFileInfo(file_path, &fileinfo)) { 151 base::Time::Exploded ctime; 152 fileinfo.creation_time.UTCExplode(&ctime); 153 version += base::StringPrintf("-%02u.%02u.%02u", 154 ctime.year % 100, 155 ctime.month, 156 ctime.day_of_month); 157 } 158 } 159 160 request->ForwardResult(request->handle(), version); 161} 162 163void VersionLoader::Backend::GetFirmware( 164 scoped_refptr<GetFirmwareRequest> request) { 165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 166 if (request->canceled()) 167 return; 168 169 std::string firmware; 170 std::string contents; 171 const FilePath file_path(kPathFirmware); 172 if (file_util::ReadFileToString(file_path, &contents)) { 173 firmware = ParseFirmware(contents); 174 } 175 176 request->ForwardResult(request->handle(), firmware); 177} 178 179} // namespace chromeos 180