Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(532)

Unified Diff: chrome/browser/chromeos/system_access.cc

Issue 7324017: Split SystemAccess into TimezoneSettings, StatisticsProvider, and SyslogsProvider. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address comments Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/system_access.cc
diff --git a/chrome/browser/chromeos/system_access.cc b/chrome/browser/chromeos/system_access.cc
deleted file mode 100644
index 04cada67fb2ea7d38fb95b60c12060682d5d0737..0000000000000000000000000000000000000000
--- a/chrome/browser/chromeos/system_access.cc
+++ /dev/null
@@ -1,470 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/system_access.h"
-
-#include "base/command_line.h"
-#include "base/file_path.h"
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/observer_list.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/singleton.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/chromeos/name_value_pairs_parser.h"
-#include "chrome/common/chrome_switches.h"
-#include "content/browser/browser_thread.h"
-
-namespace chromeos { // NOLINT
-
-namespace { // NOLINT
-
-// The filepath to the timezone file that symlinks to the actual timezone file.
-const char kTimezoneSymlink[] = "/var/lib/timezone/localtime";
-const char kTimezoneSymlink2[] = "/var/lib/timezone/localtime2";
-
-// The directory that contains all the timezone files. So for timezone
-// "US/Pacific", the actual timezone file is: "/usr/share/zoneinfo/US/Pacific"
-const char kTimezoneFilesDir[] = "/usr/share/zoneinfo/";
-
-// The system command that returns the hardware class.
-const char kHardwareClassKey[] = "hardware_class";
-const char* kHardwareClassTool[] = { "crossystem", "hwid" };
-const char kUnknownHardwareClass[] = "unknown";
-
-// Command to get machine hardware info and key/value delimiters.
-// /tmp/machine-info is generated by platform/init/chromeos_startup.
-const char* kMachineHardwareInfoTool[] = { "cat", "/tmp/machine-info" };
-const char kMachineHardwareInfoEq[] = "=";
-const char kMachineHardwareInfoDelim[] = " \n";
-
-// Command to get machine OS info and key/value delimiters.
-const char* kMachineOSInfoTool[] = { "cat", "/etc/lsb-release" };
-const char kMachineOSInfoEq[] = "=";
-const char kMachineOSInfoDelim[] = "\n";
-
-// Command to get VPD info and key/value delimiters.
-const char* kVpdTool[] = { "cat", "/var/log/vpd_2.0.txt" };
-const char kVpdEq[] = "=";
-const char kVpdDelim[] = "\n";
-
-// Fallback time zone ID used in case of an unexpected error.
-const char kFallbackTimeZoneId[] = "America/Los_Angeles";
-
-const char kSysLogsScript[] =
- "/usr/share/userfeedback/scripts/sysinfo_script_runner";
-const char kBzip2Command[] =
- "/bin/bzip2";
-const char kMultilineQuote[] = "\"\"\"";
-const char kNewLineChars[] = "\r\n";
-const char kInvalidLogEntry[] = "<invalid characters in log entry>";
-const char kEmptyLogEntry[] = "<no value>";
-
-const char kContextFeedback[] = "feedback";
-const char kContextSysInfo[] = "sysinfo";
-const char kContextNetwork[] = "network";
-
-// Reads a key from the input string erasing the read values + delimiters read
-// from the initial string
-std::string ReadKey(std::string* data) {
- size_t equal_sign = data->find("=");
- if (equal_sign == std::string::npos)
- return std::string("");
- std::string key = data->substr(0, equal_sign);
- data->erase(0, equal_sign);
- if (data->size() > 0) {
- // erase the equal to sign also
- data->erase(0,1);
- return key;
- }
- return std::string();
-}
-
-// Reads a value from the input string; erasing the read values from
-// the initial string; detects if the value is multiline and reads
-// accordingly
-std::string ReadValue(std::string* data) {
- // Trim the leading spaces and tabs. In order to use a multi-line
- // value, you have to place the multi-line quote on the same line as
- // the equal sign.
- //
- // Why not use TrimWhitespace? Consider the following input:
- //
- // KEY1=
- // KEY2=VALUE
- //
- // If we use TrimWhitespace, we will incorrectly trim the new line
- // and assume that KEY1's value is "KEY2=VALUE" rather than empty.
- TrimString(*data, " \t", data);
-
- // If multiline value
- if (StartsWithASCII(*data, std::string(kMultilineQuote), false)) {
- data->erase(0, strlen(kMultilineQuote));
- size_t next_multi = data->find(kMultilineQuote);
- if (next_multi == std::string::npos) {
- // Error condition, clear data to stop further processing
- data->erase();
- return std::string();
- }
- std::string value = data->substr(0, next_multi);
- data->erase(0, next_multi + 3);
- return value;
- } else { // single line value
- size_t endl_pos = data->find_first_of(kNewLineChars);
- // if we don't find a new line, we just return the rest of the data
- std::string value = data->substr(0, endl_pos);
- data->erase(0, endl_pos);
- return value;
- }
-}
-
-// Returns a map of system log keys and values.
-//
-// Parameters:
-// temp_filename: This is an out parameter that holds the name of a file in
-// /tmp that contains the system logs in a KEY=VALUE format.
-// If this parameter is NULL, system logs are not retained on
-// the filesystem after this call completes.
-// context: This is an in parameter specifying what context should be
-// passed to the syslog collection script; currently valid
-// values are "sysinfo" or "feedback"; in case of an invalid
-// value, the script will currently default to "sysinfo"
-
-LogDictionaryType* GetSystemLogs(FilePath* zip_file_name,
- const std::string& context) {
- // Create the temp file, logs will go here
- FilePath temp_filename;
-
- if (!file_util::CreateTemporaryFile(&temp_filename))
- return NULL;
-
- std::string cmd = std::string(kSysLogsScript) + " " + context + " >> " +
- temp_filename.value();
-
- // Ignore the return value - if the script execution didn't work
- // stderr won't go into the output file anyway.
- if (system(cmd.c_str()) == -1)
- LOG(WARNING) << "Command " << cmd << " failed to run";
-
- // Compress the logs file if requested.
- if (zip_file_name) {
- cmd = std::string(kBzip2Command) + " -c " + temp_filename.value() + " > " +
- zip_file_name->value();
- if (system(cmd.c_str()) == -1)
- LOG(WARNING) << "Command " << cmd << " failed to run";
- }
- // Read logs from the temp file
- std::string data;
- bool read_success = file_util::ReadFileToString(temp_filename,
- &data);
- // if we were using an internal temp file, the user does not need the
- // logs to stay past the ReadFile call - delete the file
- file_util::Delete(temp_filename, false);
-
- if (!read_success)
- return NULL;
-
- // Parse the return data into a dictionary
- LogDictionaryType* logs = new LogDictionaryType();
- while (data.length() > 0) {
- std::string key = ReadKey(&data);
- TrimWhitespaceASCII(key, TRIM_ALL, &key);
- if (!key.empty()) {
- std::string value = ReadValue(&data);
- if (IsStringUTF8(value)) {
- TrimWhitespaceASCII(value, TRIM_ALL, &value);
- if (value.empty())
- (*logs)[key] = kEmptyLogEntry;
- else
- (*logs)[key] = value;
- } else {
- LOG(WARNING) << "Invalid characters in system log entry: " << key;
- (*logs)[key] = kInvalidLogEntry;
- }
- } else {
- // no more keys, we're done
- break;
- }
- }
-
- return logs;
-}
-
-class SystemAccessImpl : public SystemAccess {
- public:
- // SystemAccess.implementation:
- virtual const icu::TimeZone& GetTimezone();
- virtual void SetTimezone(const icu::TimeZone& timezone);
- virtual bool GetMachineStatistic(const std::string& name,
- std::string* result);
- virtual void AddObserver(Observer* observer);
- virtual void RemoveObserver(Observer* observer);
-
- virtual Handle RequestSyslogs(
- bool compress_logs,
- SyslogsContext context,
- CancelableRequestConsumerBase* consumer,
- ReadCompleteCallback* callback);
-
- // Reads system logs, compresses content if requested.
- // Called from FILE thread.
- void ReadSyslogs(
- scoped_refptr<CancelableRequest<ReadCompleteCallback> > request,
- bool compress_logs,
- SyslogsContext context);
-
- // Loads compressed logs and writes into |zip_content|.
- void LoadCompressedLogs(const FilePath& zip_file,
- std::string* zip_content);
-
- static SystemAccessImpl* GetInstance();
-
- private:
- friend struct DefaultSingletonTraits<SystemAccessImpl>;
-
- SystemAccessImpl();
-
- // Updates the machine statistcs by examining the system.
- void UpdateMachineStatistics();
-
- // Gets syslogs context string from the enum value.
- const char* GetSyslogsContextString(SyslogsContext context);
-
- scoped_ptr<icu::TimeZone> timezone_;
- ObserverList<Observer> observers_;
- NameValuePairsParser::NameValueMap machine_info_;
-
- DISALLOW_COPY_AND_ASSIGN(SystemAccessImpl);
-};
-
-std::string GetTimezoneIDAsString() {
- // Look at kTimezoneSymlink, see which timezone we are symlinked to.
- char buf[256];
- const ssize_t len = readlink(kTimezoneSymlink, buf,
- sizeof(buf)-1);
- if (len == -1) {
- LOG(ERROR) << "GetTimezoneID: Cannot read timezone symlink "
- << kTimezoneSymlink;
- return std::string();
- }
-
- std::string timezone(buf, len);
- // Remove kTimezoneFilesDir from the beginning.
- if (timezone.find(kTimezoneFilesDir) != 0) {
- LOG(ERROR) << "GetTimezoneID: Timezone symlink is wrong "
- << timezone;
- return std::string();
- }
-
- return timezone.substr(strlen(kTimezoneFilesDir));
-}
-
-void SetTimezoneIDFromString(const std::string& id) {
- // Change the kTimezoneSymlink symlink to the path for this timezone.
- // We want to do this in an atomic way. So we are going to create the symlink
- // at kTimezoneSymlink2 and then move it to kTimezoneSymlink
-
- FilePath timezone_symlink(kTimezoneSymlink);
- FilePath timezone_symlink2(kTimezoneSymlink2);
- FilePath timezone_file(kTimezoneFilesDir + id);
-
- // Make sure timezone_file exists.
- if (!file_util::PathExists(timezone_file)) {
- LOG(ERROR) << "SetTimezoneID: Cannot find timezone file "
- << timezone_file.value();
- return;
- }
-
- // Delete old symlink2 if it exists.
- file_util::Delete(timezone_symlink2, false);
-
- // Create new symlink2.
- if (symlink(timezone_file.value().c_str(),
- timezone_symlink2.value().c_str()) == -1) {
- LOG(ERROR) << "SetTimezoneID: Unable to create symlink "
- << timezone_symlink2.value() << " to " << timezone_file.value();
- return;
- }
-
- // Move symlink2 to symlink.
- if (!file_util::ReplaceFile(timezone_symlink2, timezone_symlink)) {
- LOG(ERROR) << "SetTimezoneID: Unable to move symlink "
- << timezone_symlink2.value() << " to "
- << timezone_symlink.value();
- }
-}
-
-const icu::TimeZone& SystemAccessImpl::GetTimezone() {
- return *timezone_.get();
-}
-
-void SystemAccessImpl::SetTimezone(const icu::TimeZone& timezone) {
- timezone_.reset(timezone.clone());
- icu::UnicodeString unicode;
- timezone.getID(unicode);
- std::string id;
- UTF16ToUTF8(unicode.getBuffer(), unicode.length(), &id);
- VLOG(1) << "Setting timezone to " << id;
- chromeos::SetTimezoneIDFromString(id);
- icu::TimeZone::setDefault(timezone);
- FOR_EACH_OBSERVER(Observer, observers_, TimezoneChanged(timezone));
-}
-
-bool SystemAccessImpl::GetMachineStatistic(
- const std::string& name, std::string* result) {
- NameValuePairsParser::NameValueMap::iterator iter = machine_info_.find(name);
- if (iter != machine_info_.end()) {
- *result = iter->second;
- return true;
- }
- return false;
-}
-
-void SystemAccessImpl::AddObserver(Observer* observer) {
- observers_.AddObserver(observer);
-}
-
-void SystemAccessImpl::RemoveObserver(Observer* observer) {
- observers_.RemoveObserver(observer);
-}
-
-SystemAccessImpl::SystemAccessImpl() {
- // Get Statistics
- UpdateMachineStatistics();
- // Get Timezone
- std::string id = GetTimezoneIDAsString();
- if (id.empty()) {
- id = kFallbackTimeZoneId;
- LOG(ERROR) << "Got an empty string for timezone, default to " << id;
- }
- icu::TimeZone* timezone =
- icu::TimeZone::createTimeZone(icu::UnicodeString::fromUTF8(id));
- timezone_.reset(timezone);
- icu::TimeZone::setDefault(*timezone);
- VLOG(1) << "Timezone is " << id;
-}
-
-void SystemAccessImpl::UpdateMachineStatistics() {
- NameValuePairsParser parser(&machine_info_);
- if (!parser.GetSingleValueFromTool(arraysize(kHardwareClassTool),
- kHardwareClassTool,
- kHardwareClassKey)) {
- // Use kUnknownHardwareClass if the hardware class command fails.
- parser.AddNameValuePair(kHardwareClassKey, kUnknownHardwareClass);
- }
- parser.ParseNameValuePairsFromTool(arraysize(kMachineHardwareInfoTool),
- kMachineHardwareInfoTool,
- kMachineHardwareInfoEq,
- kMachineHardwareInfoDelim);
- parser.ParseNameValuePairsFromTool(arraysize(kMachineOSInfoTool),
- kMachineOSInfoTool,
- kMachineOSInfoEq,
- kMachineOSInfoDelim);
- parser.ParseNameValuePairsFromTool(
- arraysize(kVpdTool), kVpdTool, kVpdEq, kVpdDelim);
-}
-
-CancelableRequestProvider::Handle SystemAccessImpl::RequestSyslogs(
- bool compress_logs,
- SyslogsContext context,
- CancelableRequestConsumerBase* consumer,
- ReadCompleteCallback* callback) {
- // Register the callback request.
- scoped_refptr<CancelableRequest<ReadCompleteCallback> > request(
- new CancelableRequest<ReadCompleteCallback>(callback));
- AddRequest(request, consumer);
-
- // Schedule a task on the FILE thread which will then trigger a request
- // callback on the calling thread (e.g. UI) when complete.
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- NewRunnableMethod(
- this, &SystemAccessImpl::ReadSyslogs, request,
- compress_logs, context));
-
- return request->handle();
-}
-
-// Called from FILE thread.
-void SystemAccessImpl::ReadSyslogs(
- scoped_refptr<CancelableRequest<ReadCompleteCallback> > request,
- bool compress_logs,
- SyslogsContext context) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
- if (request->canceled())
- return;
-
- if (compress_logs && !CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kCompressSystemFeedback))
- compress_logs = false;
-
- // Create temp file.
- FilePath zip_file;
- if (compress_logs && !file_util::CreateTemporaryFile(&zip_file)) {
- LOG(ERROR) << "Cannot create temp file";
- compress_logs = false;
- }
-
- LogDictionaryType* logs = NULL;
- logs = chromeos::GetSystemLogs(
- compress_logs ? &zip_file : NULL,
- GetSyslogsContextString(context));
-
- std::string* zip_content = NULL;
- if (compress_logs) {
- // Load compressed logs.
- zip_content = new std::string();
- LoadCompressedLogs(zip_file, zip_content);
- file_util::Delete(zip_file, false);
- }
-
- // Will call the callback on the calling thread.
- request->ForwardResult(Tuple2<LogDictionaryType*,
- std::string*>(logs, zip_content));
-}
-
-
-void SystemAccessImpl::LoadCompressedLogs(const FilePath& zip_file,
- std::string* zip_content) {
- DCHECK(zip_content);
- if (!file_util::ReadFileToString(zip_file, zip_content)) {
- LOG(ERROR) << "Cannot read compressed logs file from " <<
- zip_file.value().c_str();
- }
-}
-
-const char* SystemAccessImpl::GetSyslogsContextString(SyslogsContext context) {
- switch (context) {
- case(SYSLOGS_FEEDBACK):
- return kContextFeedback;
- case(SYSLOGS_SYSINFO):
- return kContextSysInfo;
- case(SYSLOGS_NETWORK):
- return kContextNetwork;
- case(SYSLOGS_DEFAULT):
- return kContextSysInfo;
- default:
- NOTREACHED();
- return "";
- }
-}
-
-SystemAccessImpl* SystemAccessImpl::GetInstance() {
- return Singleton<SystemAccessImpl,
- DefaultSingletonTraits<SystemAccessImpl> >::get();
-}
-
-} // namespace
-
-SystemAccess* SystemAccess::GetInstance() {
- return SystemAccessImpl::GetInstance();
-}
-
-} // namespace chromeos
-
-// Allows InvokeLater without adding refcounting. SystemAccessImpl is a
-// Singleton and won't be deleted until it's last InvokeLater is run.
-DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::SystemAccessImpl);
« no previous file with comments | « chrome/browser/chromeos/system_access.h ('k') | chrome/browser/extensions/extension_info_private_api_chromeos.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698