Index: chrome_frame/chrome_frame_reporting.cc |
diff --git a/chrome_frame/chrome_frame_reporting.cc b/chrome_frame/chrome_frame_reporting.cc |
index f9fa490d7427dbaf47e6f54caf834bf24866f400..b77d3be9e74a368462e1579ad355cb6a42044900 100644 |
--- a/chrome_frame/chrome_frame_reporting.cc |
+++ b/chrome_frame/chrome_frame_reporting.cc |
@@ -4,15 +4,26 @@ |
// Implementation of wrapper around common crash reporting. |
+#include "chrome_frame/chrome_frame_reporting.h" |
+ |
+#include "base/basictypes.h" |
#include "base/file_util.h" |
#include "base/file_version_info.h" |
+#include "base/lazy_instance.h" |
#include "base/win/win_util.h" |
#include "chrome/installer/util/google_update_settings.h" |
#include "chrome/installer/util/install_util.h" |
-#include "chrome_frame/chrome_frame_reporting.h" |
+#include "chrome_frame/crash_reporting/crash_report.h" |
#include "chrome_frame/exception_barrier.h" |
#include "chrome_frame/utils.h" |
+extern "C" IMAGE_DOS_HEADER __ImageBase; |
+ |
+namespace { |
+ |
+base::LazyInstance<CrashReportingManager>::Leaky g_crash_reporting_manager = |
+ LAZY_INSTANCE_INITIALIZER; |
+ |
// Well known SID for the system principal. |
const wchar_t kSystemPrincipalSid[] = L"S-1-5-18"; |
const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices"; |
@@ -45,15 +56,13 @@ google_breakpad::CustomClientInfo* GetCustomInfo(const wchar_t* dll_path) { |
return &custom_info; |
} |
-extern "C" IMAGE_DOS_HEADER __ImageBase; |
- |
bool InitializeCrashReporting() { |
// In headless mode we want crashes to be reported back. |
bool always_take_dump = IsHeadlessMode(); |
// We want to use the Google Update crash reporting. We need to check if the |
// user allows it first. |
if (!always_take_dump && !GoogleUpdateSettings::GetCollectStatsConsent()) |
- return true; |
+ return true; |
// If we got here, we want to report crashes, so make sure all |
// ExceptionBarrierBase instances do so. |
@@ -61,17 +70,16 @@ bool InitializeCrashReporting() { |
// Get the alternate dump directory. We use the temp path. |
base::FilePath temp_directory; |
- if (!file_util::GetTempDir(&temp_directory) || temp_directory.empty()) { |
+ if (!file_util::GetTempDir(&temp_directory) || temp_directory.empty()) |
return false; |
- } |
wchar_t dll_path[MAX_PATH * 2] = {0}; |
GetModuleFileName(reinterpret_cast<HMODULE>(&__ImageBase), dll_path, |
arraysize(dll_path)); |
if (always_take_dump) { |
- return InitializeVectoredCrashReportingWithPipeName(true, kChromePipeName, |
- temp_directory.value(), GetCustomInfo(dll_path)); |
+ return InitializeVectoredCrashReportingWithPipeName( |
+ true, kChromePipeName, temp_directory.value(), GetCustomInfo(dll_path)); |
} |
// Build the pipe name. It can be either: |
@@ -79,18 +87,77 @@ bool InitializeCrashReporting() { |
// Per-user install: "NamedPipe\GoogleCrashServices\<user SID>" |
std::wstring user_sid; |
if (InstallUtil::IsPerUserInstall(dll_path)) { |
- if (!base::win::GetUserSidString(&user_sid)) { |
+ if (!base::win::GetUserSidString(&user_sid)) |
return false; |
- } |
} else { |
user_sid = kSystemPrincipalSid; |
} |
- return InitializeVectoredCrashReporting(false, user_sid.c_str(), |
- temp_directory.value(), GetCustomInfo(dll_path)); |
+ return InitializeVectoredCrashReporting( |
+ false, user_sid.c_str(), temp_directory.value(), GetCustomInfo(dll_path)); |
} |
bool ShutdownCrashReporting() { |
ExceptionBarrierConfig::set_enabled(false); |
return ShutdownVectoredCrashReporting(); |
} |
+ |
+} // namespace |
+ |
+// static |
+void CrashReportingManager::Decommit() { |
+ CrashReportingManager& instance = Get(); |
+ base::AutoLock auto_lock(instance.lock_); |
+ instance.committed_ = false; |
+ instance.ShutdownIfNotCommittedAndUnreferenced(); |
+} |
+ |
+CrashReportingManager::CrashReportingManager() |
+ : ref_count_(0), |
+ initialized_(false), |
+ committed_(false) {} |
+ |
+CrashReportingManager::~CrashReportingManager() { |
+ // The one and only instance of this class is leaked. |
+ NOTREACHED(); |
+} |
+ |
+// static |
+CrashReportingManager& CrashReportingManager::Get() { |
+ return g_crash_reporting_manager.Get(); |
+} |
+ |
+void CrashReportingManager::AddRef() { |
+ base::AutoLock auto_lock(lock_); |
+ DCHECK_LT(ref_count_, kuint32max); |
+ ++ref_count_; |
+ |
+ if (!initialized_) { |
+ initialized_ = true; |
+ InitializeCrashReporting(); |
+ } |
+} |
+ |
+void CrashReportingManager::Release() { |
+ base::AutoLock auto_lock(lock_); |
+ |
+ DCHECK_GT(ref_count_, 0U); |
+ if (--ref_count_ == 0) |
+ ShutdownIfNotCommittedAndUnreferenced(); |
+} |
+ |
+void CrashReportingManager::Commit() { |
+ base::AutoLock auto_lock(lock_); |
+ DCHECK_NE(ref_count_, 0U); |
+ committed_ = true; |
+} |
+ |
+// Shuts down crash reporting if no scoper has committed to keeping reporting |
+// alive and no scopers are currently active. |
+void CrashReportingManager::ShutdownIfNotCommittedAndUnreferenced() { |
+ lock_.AssertAcquired(); |
+ if (initialized_ && !committed_ && ref_count_ == 0) { |
+ initialized_ = false; |
+ ShutdownCrashReporting(); |
+ } |
+} |