15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/version_loader.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/location.h" 139ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h" 155e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 165e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h" 174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/sys_info.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/sequenced_worker_pool.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Beginning of line we look for that gives full version number. 294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Format: x.x.xx.x (Developer|Official build extra info) board info 304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kFullVersionKey[] = "CHROMEOS_RELEASE_DESCRIPTION"; 314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Same but for short version (x.x.xx.x). 334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kVersionKey[] = "CHROMEOS_RELEASE_VERSION"; 344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Beginning of line we look for that gives the firmware version. 364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kFirmwarePrefix[] = "version"; 374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// File to look for firmware number in. 394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kPathFirmware[] = "/var/log/bios_info.txt"; 404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Converts const string* to const string&. 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VersionLoaderCallbackHelper( 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Callback<void(const std::string&)> callback, 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string* version) { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback.Run(*version); 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VersionLoader::VersionLoader() : backend_(new Backend()) {} 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VersionLoader::~VersionLoader() {} 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::CancelableTaskTracker::TaskId VersionLoader::GetVersion( 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VersionFormat format, 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GetVersionCallback& callback, 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::CancelableTaskTracker* tracker) { 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string* version = new std::string(); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return tracker->PostTaskAndReply( 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::GetBlockingPool(), 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&Backend::GetVersion, backend_.get(), format, version), 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&VersionLoaderCallbackHelper, callback, base::Owned(version))); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::CancelableTaskTracker::TaskId VersionLoader::GetFirmware( 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GetFirmwareCallback& callback, 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::CancelableTaskTracker* tracker) { 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string* firmware = new std::string(); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return tracker->PostTaskAndReply( 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::GetBlockingPool(), 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&Backend::GetFirmware, backend_.get(), firmware), 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&VersionLoaderCallbackHelper, 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback, base::Owned(firmware))); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string VersionLoader::ParseFirmware(const std::string& contents) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The file contains lines such as: 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // vendor | ... 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // version | ... 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // release_date | ... 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't make any assumption that the spaces between "version" and "|" is 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fixed. So we just match kFirmwarePrefix at the start of the line and find 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the first character that is not "|" or space 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> lines; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitString(contents, '\n', &lines); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < lines.size(); ++i) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (StartsWithASCII(lines[i], kFirmwarePrefix, false)) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string str = lines[i].substr(std::string(kFirmwarePrefix).size()); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t found = str.find_first_not_of("| "); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found != std::string::npos) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return str.substr(found); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VersionLoader::Backend::GetVersion(VersionFormat format, 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string* version) { 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string key = (format == VERSION_FULL) ? kFullVersionKey : kVersionKey; 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!base::SysInfo::GetLsbReleaseValue(key, version)) { 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG_IF(ERROR, base::SysInfo::IsRunningOnChromeOS()) 1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << "No LSB version key: " << key; 1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *version = "0.0.0.0"; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (format == VERSION_SHORT_WITH_DATE) { 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Time::Exploded ctime; 1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::SysInfo::GetLsbReleaseTime().UTCExplode(&ctime); 1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *version += base::StringPrintf("-%02u.%02u.%02u", 1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ctime.year % 100, 1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ctime.month, 1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ctime.day_of_month); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VersionLoader::Backend::GetFirmware(std::string* firmware) { 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string contents; 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath file_path(kPathFirmware); 12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (base::ReadFileToString(file_path, &contents)) { 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *firmware = ParseFirmware(contents); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace chromeos 134