diff options
author | asvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-01 15:58:50 +0000 |
---|---|---|
committer | asvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-01 15:58:50 +0000 |
commit | b35b1dd3737b7d6bc9aeca0666772c9a9aded78a (patch) | |
tree | e70a28ade2edaaba53060a2f352a452466ca5f12 | |
parent | 6e1272138cd494e23c6e350fbd6041ead147bf5b (diff) | |
download | chromium_src-b35b1dd3737b7d6bc9aeca0666772c9a9aded78a.zip chromium_src-b35b1dd3737b7d6bc9aeca0666772c9a9aded78a.tar.gz chromium_src-b35b1dd3737b7d6bc9aeca0666772c9a9aded78a.tar.bz2 |
Implement CrashUploadListWin to enable chrome://crashes on Windows.
Added new class CrashUploadListWin, subclass of CrashUploadList which
has the Windows platform-specific logic to read crash logs from Windows
Event Log.
Added static CrashUploadList::Create() factory method which returns an
instance of CrashUploadListWin on Windows and an instance of
CrashUploadList on other platforms.
Also implemented the max_count parameter in
CrashUploadList::GetUploadedCrashes(), which was part of
the interface but was ignored by the code.
BUG=73468
TEST=Open chrome://crashes under Windows after one or more
crash reports were uploaded. See the crash reports listed.
Review URL: http://codereview.chromium.org/6771021
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@80165 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/crash_upload_list.cc | 63 | ||||
-rw-r--r-- | chrome/browser/crash_upload_list.h | 23 | ||||
-rw-r--r-- | chrome/browser/crash_upload_list_win.cc | 80 | ||||
-rw-r--r-- | chrome/browser/crash_upload_list_win.h | 32 | ||||
-rw-r--r-- | chrome/browser/ui/webui/crashes_ui.cc | 2 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 |
6 files changed, 181 insertions, 21 deletions
diff --git a/chrome/browser/crash_upload_list.cc b/chrome/browser/crash_upload_list.cc index d10980f..fa0e8ab 100644 --- a/chrome/browser/crash_upload_list.cc +++ b/chrome/browser/crash_upload_list.cc @@ -9,6 +9,9 @@ #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" @@ -17,20 +20,37 @@ CrashUploadList::CrashInfo::CrashInfo(const std::string& c, const base::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::LoadUploadLog)); + NewRunnableMethod(this, + &CrashUploadList::LoadCrashListAndInformDelegateOfCompletion)); } void CrashUploadList::ClearDelegate() { delegate_ = NULL; } -void CrashUploadList::LoadUploadLog() { + +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); @@ -38,22 +58,16 @@ void CrashUploadList::LoadUploadLog() { if (file_util::PathExists(upload_log_path)) { std::string contents; file_util::ReadFileToString(upload_log_path, &contents); - base::SplitStringAlongWhitespace(contents, &log_entries_); + std::vector<std::string> log_entries; + base::SplitStringAlongWhitespace(contents, &log_entries); + ParseLogEntries(log_entries); } - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - NewRunnableMethod(this, &CrashUploadList::InformDelegateOfCompletion)); -} - -void CrashUploadList::InformDelegateOfCompletion() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (delegate_) - delegate_->OnCrashListAvailable(); } -void CrashUploadList::GetUploadedCrashes(unsigned int max_count, - std::vector<CrashInfo>* crashes) { - std::vector<std::string>::reverse_iterator i; - for (i = log_entries_.rbegin(); i != log_entries_.rend(); ++i) { +void CrashUploadList::ParseLogEntries( + const std::vector<std::string>& log_entries) { + std::vector<std::string>::const_reverse_iterator i; + for (i = log_entries.rbegin(); i != log_entries.rend(); ++i) { std::vector<std::string> components; base::SplitString(*i, ',', &components); // Skip any blank (or corrupted) lines. @@ -63,6 +77,23 @@ void CrashUploadList::GetUploadedCrashes(unsigned int max_count, if (!base::StringToDouble(components[0], &seconds_since_epoch)) continue; CrashInfo info(components[1], base::Time::FromDoubleT(seconds_since_epoch)); - crashes->push_back(info); + 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<CrashInfo>* crashes) { + std::copy(crashes_.begin(), + crashes_.begin() + std::min<size_t>(crashes_.size(), max_count), + std::back_inserter(*crashes)); +} + +std::vector<CrashUploadList::CrashInfo>& CrashUploadList::crashes() { + return crashes_; +} diff --git a/chrome/browser/crash_upload_list.h b/chrome/browser/crash_upload_list.h index 9d5d243..c8b30d1 100644 --- a/chrome/browser/crash_upload_list.h +++ b/chrome/browser/crash_upload_list.h @@ -32,6 +32,10 @@ class CrashUploadList : public base::RefCountedThreadSafe<CrashUploadList> { virtual ~Delegate() {} }; + // Static factory method that creates the platform-specific implementation + // of the crash upload list with the given callback delegate. + static CrashUploadList* Create(Delegate* delegate); + // Creates a new crash upload list with the given callback delegate. explicit CrashUploadList(Delegate* delegate); @@ -49,17 +53,28 @@ class CrashUploadList : public base::RefCountedThreadSafe<CrashUploadList> { void GetUploadedCrashes(unsigned int max_count, std::vector<CrashInfo>* crashes); + protected: + virtual ~CrashUploadList(); + + // Reads the upload log and stores the entries in crashes_. + virtual void LoadCrashList(); + + // Returns a reference to the list of crashes. + std::vector<CrashInfo>& crashes(); + private: friend class base::RefCountedThreadSafe<CrashUploadList>; - virtual ~CrashUploadList(); - // Reads the upload log and stores the lines in log_entries_. - void LoadUploadLog(); + // Manages the background thread work for LoadCrashListAsynchronously(). + void LoadCrashListAndInformDelegateOfCompletion(); // Calls the delegate's callback method, if there is a delegate. void InformDelegateOfCompletion(); - std::vector<std::string> log_entries_; + // Parses crash log lines, converting them to CrashInfo entries. + void ParseLogEntries(const std::vector<std::string>& log_entries); + + std::vector<CrashInfo> crashes_; Delegate* delegate_; DISALLOW_COPY_AND_ASSIGN(CrashUploadList); diff --git a/chrome/browser/crash_upload_list_win.cc b/chrome/browser/crash_upload_list_win.cc new file mode 100644 index 0000000..7c4e948 --- /dev/null +++ b/chrome/browser/crash_upload_list_win.cc @@ -0,0 +1,80 @@ +// 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_win.h" + +#include "base/stringprintf.h" +#include "base/string_util.h" +#include "base/sys_string_conversions.h" + +CrashUploadListWin::CrashUploadListWin(Delegate* delegate) + : CrashUploadList(delegate) {} + +void CrashUploadListWin::LoadCrashList() { + std::vector<uint8> buffer(1024); + HANDLE event_log = OpenEventLog(NULL, L"Application"); + if (event_log) { + while (true) { + DWORD bytes_read; + DWORD bytes_needed; + BOOL success = + ReadEventLog(event_log, + EVENTLOG_SEQUENTIAL_READ | EVENTLOG_BACKWARDS_READ, + 0, + &buffer[0], + buffer.size(), + &bytes_read, + &bytes_needed); + if (success) { + DWORD record_offset = 0; + // The ReadEventLog() API docs imply, but do not explicitly state that + // partial records will not be returned. Use DCHECK() to affirm this. + while (record_offset < bytes_read) { + DCHECK(record_offset + sizeof(EVENTLOGRECORD) <= bytes_read); + EVENTLOGRECORD* record = (EVENTLOGRECORD*)&buffer[record_offset]; + DCHECK(record_offset + record->Length <= bytes_read); + if (IsPossibleCrashLogRecord(record)) + ProcessPossibleCrashLogRecord(record); + record_offset += record->Length; + } + } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + // Resize buffer to the required minimum size. + buffer.resize(bytes_needed); + } else { + // Stop on any other error, including the expected case + // of ERROR_HANDLE_EOF. + DCHECK(GetLastError() == ERROR_HANDLE_EOF); + break; + } + } + CloseEventLog(event_log); + } +} + +bool CrashUploadListWin::IsPossibleCrashLogRecord( + EVENTLOGRECORD* record) const { + LPWSTR provider_name = (LPWSTR)((uint8*)record + sizeof(EVENTLOGRECORD)); + return !wcscmp(L"Chrome", provider_name) && + record->EventType == EVENTLOG_INFORMATION_TYPE && + record->NumStrings >= 1; +} + +void CrashUploadListWin::ProcessPossibleCrashLogRecord(EVENTLOGRECORD* record) { + // Add the crash if the message matches the expected pattern. + const std::wstring pattern_prefix(L"Id="); + const std::wstring pattern_suffix(L"."); + std::wstring message((LPWSTR)((uint8*)record + record->StringOffset)); + size_t start_index = message.find(pattern_prefix); + if (start_index != std::wstring::npos) { + start_index += pattern_prefix.size(); + size_t end_index = message.find(pattern_suffix, start_index); + if (end_index != std::wstring::npos) { + std::wstring crash_id = + message.substr(start_index, end_index - start_index); + crashes().push_back( + CrashInfo(base::SysWideToUTF8(crash_id), + base::Time::FromDoubleT(record->TimeGenerated))); + } + } +} diff --git a/chrome/browser/crash_upload_list_win.h b/chrome/browser/crash_upload_list_win.h new file mode 100644 index 0000000..e395a27 --- /dev/null +++ b/chrome/browser/crash_upload_list_win.h @@ -0,0 +1,32 @@ +// 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. + +#ifndef CHROME_BROWSER_CRASH_UPLOAD_LIST_WIN_H_ +#define CHROME_BROWSER_CRASH_UPLOAD_LIST_WIN_H_ +#pragma once + +#include "chrome/browser/crash_upload_list.h" +#include "base/compiler_specific.h" + +// A CrashUploadList that retrieves the list of reported crashes +// from the Windows Event Log. +class CrashUploadListWin : public CrashUploadList { + public: + explicit CrashUploadListWin(Delegate* delegate); + + protected: + // Loads the list of crashes from the Windows Event Log. + virtual void LoadCrashList() OVERRIDE; + + private: + // Returns whether the event record is likely a Chrome crash log. + bool IsPossibleCrashLogRecord(EVENTLOGRECORD* record) const; + + // Parses the event record and adds it to the crash list. + void ProcessPossibleCrashLogRecord(EVENTLOGRECORD* record); + + DISALLOW_COPY_AND_ASSIGN(CrashUploadListWin); +}; + +#endif // CHROME_BROWSER_CRASH_UPLOAD_LIST_WIN_H_ diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/crashes_ui.cc index 0758652..6f2327a 100644 --- a/chrome/browser/ui/webui/crashes_ui.cc +++ b/chrome/browser/ui/webui/crashes_ui.cc @@ -127,7 +127,7 @@ class CrashesDOMHandler : public WebUIMessageHandler, CrashesDOMHandler::CrashesDOMHandler() : list_available_(false), js_request_pending_(false) { - upload_list_ = new CrashUploadList(this); + upload_list_ = CrashUploadList::Create(this); } CrashesDOMHandler::~CrashesDOMHandler() { diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 5889df3..c4bda76 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -746,6 +746,8 @@ 'browser/cookies_tree_model.h', 'browser/crash_upload_list.cc', 'browser/crash_upload_list.h', + 'browser/crash_upload_list_win.cc', + 'browser/crash_upload_list_win.h', 'browser/custom_home_pages_table_model.cc', 'browser/custom_home_pages_table_model.h', 'browser/custom_handlers/protocol_handler.cc', |