summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorasvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-01 15:58:50 +0000
committerasvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-01 15:58:50 +0000
commitb35b1dd3737b7d6bc9aeca0666772c9a9aded78a (patch)
treee70a28ade2edaaba53060a2f352a452466ca5f12
parent6e1272138cd494e23c6e350fbd6041ead147bf5b (diff)
downloadchromium_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.cc63
-rw-r--r--chrome/browser/crash_upload_list.h23
-rw-r--r--chrome/browser/crash_upload_list_win.cc80
-rw-r--r--chrome/browser/crash_upload_list_win.h32
-rw-r--r--chrome/browser/ui/webui/crashes_ui.cc2
-rw-r--r--chrome/chrome_browser.gypi2
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',