// 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/crash_upload_list.h" #include #include "base/path_service.h" #include "base/file_path.h" #include "base/file_util.h" #include "base/string_number_conversions.h" #include "base/string_split.h" #if defined(OS_WIN) #include "chrome/browser/crash_upload_list_win.h" #endif #include "chrome/common/chrome_paths.h" #include "content/browser/browser_thread.h" CrashUploadList::CrashInfo::CrashInfo(const std::string& c, const base::Time& t) : crash_id(c), crash_time(t) {} CrashUploadList::CrashInfo::~CrashInfo() {} // static CrashUploadList* CrashUploadList::Create(Delegate* delegate) { #if defined(OS_WIN) return new CrashUploadListWin(delegate); #else return new CrashUploadList(delegate); #endif } CrashUploadList::CrashUploadList(Delegate* delegate) : delegate_(delegate) {} CrashUploadList::~CrashUploadList() {} void CrashUploadList::LoadCrashListAsynchronously() { BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, NewRunnableMethod(this, &CrashUploadList::LoadCrashListAndInformDelegateOfCompletion)); } void CrashUploadList::ClearDelegate() { delegate_ = NULL; } void CrashUploadList::LoadCrashListAndInformDelegateOfCompletion() { LoadCrashList(); BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(this, &CrashUploadList::InformDelegateOfCompletion)); } void CrashUploadList::LoadCrashList() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); FilePath crash_dir_path; PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dir_path); FilePath upload_log_path = crash_dir_path.AppendASCII("uploads.log"); if (file_util::PathExists(upload_log_path)) { std::string contents; file_util::ReadFileToString(upload_log_path, &contents); std::vector log_entries; base::SplitStringAlongWhitespace(contents, &log_entries); ParseLogEntries(log_entries); } } void CrashUploadList::ParseLogEntries( const std::vector& log_entries) { std::vector::const_reverse_iterator i; for (i = log_entries.rbegin(); i != log_entries.rend(); ++i) { std::vector components; base::SplitString(*i, ',', &components); // Skip any blank (or corrupted) lines. if (components.size() != 2) continue; double seconds_since_epoch; if (!base::StringToDouble(components[0], &seconds_since_epoch)) continue; CrashInfo info(components[1], base::Time::FromDoubleT(seconds_since_epoch)); crashes_.push_back(info); } } void CrashUploadList::InformDelegateOfCompletion() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (delegate_) delegate_->OnCrashListAvailable(); } void CrashUploadList::GetUploadedCrashes(unsigned int max_count, std::vector* crashes) { std::copy(crashes_.begin(), crashes_.begin() + std::min(crashes_.size(), max_count), std::back_inserter(*crashes)); } std::vector& CrashUploadList::crashes() { return crashes_; }