Merge pull request #7500 from electron/store-crashes-in-configured-temp-dir
Store crash reports in configured temp dir
This commit is contained in:
commit
91591f37e6
16 changed files with 151 additions and 88 deletions
|
@ -607,7 +607,7 @@ base::FilePath App::GetPath(mate::Arguments* args, const std::string& name) {
|
||||||
if (key >= 0)
|
if (key >= 0)
|
||||||
succeed = PathService::Get(key, &path);
|
succeed = PathService::Get(key, &path);
|
||||||
if (!succeed)
|
if (!succeed)
|
||||||
args->ThrowError("Failed to get path");
|
args->ThrowError("Failed to get '" + name + "' path");
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,7 +615,7 @@ void App::SetPath(mate::Arguments* args,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const base::FilePath& path) {
|
const base::FilePath& path) {
|
||||||
if (!path.IsAbsolute()) {
|
if (!path.IsAbsolute()) {
|
||||||
args->ThrowError("path must be absolute");
|
args->ThrowError("Path must be absolute");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "atom/common/crash_reporter/crash_reporter.h"
|
#include "atom/common/crash_reporter/crash_reporter.h"
|
||||||
|
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||||
#include "base/bind.h"
|
#include "base/bind.h"
|
||||||
#include "native_mate/dictionary.h"
|
#include "native_mate/dictionary.h"
|
||||||
|
|
||||||
|
|
|
@ -25,13 +25,14 @@ CrashReporter::~CrashReporter() {
|
||||||
void CrashReporter::Start(const std::string& product_name,
|
void CrashReporter::Start(const std::string& product_name,
|
||||||
const std::string& company_name,
|
const std::string& company_name,
|
||||||
const std::string& submit_url,
|
const std::string& submit_url,
|
||||||
|
const base::FilePath& crashes_dir,
|
||||||
bool auto_submit,
|
bool auto_submit,
|
||||||
bool skip_system_crash_handler,
|
bool skip_system_crash_handler,
|
||||||
const StringMap& extra_parameters) {
|
const StringMap& extra_parameters) {
|
||||||
SetUploadParameters(extra_parameters);
|
SetUploadParameters(extra_parameters);
|
||||||
|
|
||||||
InitBreakpad(product_name, ATOM_VERSION_STRING, company_name, submit_url,
|
InitBreakpad(product_name, ATOM_VERSION_STRING, company_name, submit_url,
|
||||||
auto_submit, skip_system_crash_handler);
|
crashes_dir, auto_submit, skip_system_crash_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrashReporter::SetUploadParameters(const StringMap& parameters) {
|
void CrashReporter::SetUploadParameters(const StringMap& parameters) {
|
||||||
|
@ -43,11 +44,12 @@ void CrashReporter::SetUploadParameters(const StringMap& parameters) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CrashReporter::UploadReportResult>
|
std::vector<CrashReporter::UploadReportResult>
|
||||||
CrashReporter::GetUploadedReports(const std::string& path) {
|
CrashReporter::GetUploadedReports(const base::FilePath& crashes_dir) {
|
||||||
std::string file_content;
|
std::string file_content;
|
||||||
std::vector<CrashReporter::UploadReportResult> result;
|
std::vector<CrashReporter::UploadReportResult> result;
|
||||||
if (base::ReadFileToString(base::FilePath::FromUTF8Unsafe(path),
|
base::FilePath uploads_path =
|
||||||
&file_content)) {
|
crashes_dir.Append(FILE_PATH_LITERAL("uploads.log"));
|
||||||
|
if (base::ReadFileToString(uploads_path, &file_content)) {
|
||||||
std::vector<std::string> reports = base::SplitString(
|
std::vector<std::string> reports = base::SplitString(
|
||||||
file_content, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
file_content, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||||
for (const std::string& report : reports) {
|
for (const std::string& report : reports) {
|
||||||
|
@ -68,6 +70,7 @@ void CrashReporter::InitBreakpad(const std::string& product_name,
|
||||||
const std::string& version,
|
const std::string& version,
|
||||||
const std::string& company_name,
|
const std::string& company_name,
|
||||||
const std::string& submit_url,
|
const std::string& submit_url,
|
||||||
|
const base::FilePath& crashes_dir,
|
||||||
bool auto_submit,
|
bool auto_submit,
|
||||||
bool skip_system_crash_handler) {
|
bool skip_system_crash_handler) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "base/files/file_path.h"
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
|
|
||||||
namespace crash_reporter {
|
namespace crash_reporter {
|
||||||
|
@ -24,12 +25,13 @@ class CrashReporter {
|
||||||
void Start(const std::string& product_name,
|
void Start(const std::string& product_name,
|
||||||
const std::string& company_name,
|
const std::string& company_name,
|
||||||
const std::string& submit_url,
|
const std::string& submit_url,
|
||||||
|
const base::FilePath& crashes_dir,
|
||||||
bool auto_submit,
|
bool auto_submit,
|
||||||
bool skip_system_crash_handler,
|
bool skip_system_crash_handler,
|
||||||
const StringMap& extra_parameters);
|
const StringMap& extra_parameters);
|
||||||
|
|
||||||
virtual std::vector<CrashReporter::UploadReportResult> GetUploadedReports(
|
virtual std::vector<CrashReporter::UploadReportResult> GetUploadedReports(
|
||||||
const std::string& path);
|
const base::FilePath& crashes_dir);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CrashReporter();
|
CrashReporter();
|
||||||
|
@ -39,6 +41,7 @@ class CrashReporter {
|
||||||
const std::string& version,
|
const std::string& version,
|
||||||
const std::string& company_name,
|
const std::string& company_name,
|
||||||
const std::string& submit_url,
|
const std::string& submit_url,
|
||||||
|
const base::FilePath& crashes_dir,
|
||||||
bool auto_submit,
|
bool auto_submit,
|
||||||
bool skip_system_crash_handler);
|
bool skip_system_crash_handler);
|
||||||
virtual void SetUploadParameters();
|
virtual void SetUploadParameters();
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "base/memory/singleton.h"
|
#include "base/memory/singleton.h"
|
||||||
#include "base/process/memory.h"
|
#include "base/process/memory.h"
|
||||||
#include "base/strings/stringprintf.h"
|
|
||||||
#include "vendor/breakpad/src/client/linux/handler/exception_handler.h"
|
#include "vendor/breakpad/src/client/linux/handler/exception_handler.h"
|
||||||
#include "vendor/breakpad/src/common/linux/linux_libc_support.h"
|
#include "vendor/breakpad/src/common/linux/linux_libc_support.h"
|
||||||
|
|
||||||
|
@ -60,9 +59,10 @@ void CrashReporterLinux::InitBreakpad(const std::string& product_name,
|
||||||
const std::string& version,
|
const std::string& version,
|
||||||
const std::string& company_name,
|
const std::string& company_name,
|
||||||
const std::string& submit_url,
|
const std::string& submit_url,
|
||||||
|
const base::FilePath& crashes_dir,
|
||||||
bool auto_submit,
|
bool auto_submit,
|
||||||
bool skip_system_crash_handler) {
|
bool skip_system_crash_handler) {
|
||||||
EnableCrashDumping(product_name);
|
EnableCrashDumping(crashes_dir);
|
||||||
|
|
||||||
crash_keys_.SetKeyValue("prod", ATOM_PRODUCT_NAME);
|
crash_keys_.SetKeyValue("prod", ATOM_PRODUCT_NAME);
|
||||||
crash_keys_.SetKeyValue("ver", version.c_str());
|
crash_keys_.SetKeyValue("ver", version.c_str());
|
||||||
|
@ -77,16 +77,13 @@ void CrashReporterLinux::SetUploadParameters() {
|
||||||
upload_parameters_["platform"] = "linux";
|
upload_parameters_["platform"] = "linux";
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrashReporterLinux::EnableCrashDumping(const std::string& product_name) {
|
void CrashReporterLinux::EnableCrashDumping(const base::FilePath& crashes_dir) {
|
||||||
std::string dump_dir = "/tmp/" + product_name + " Crashes";
|
base::CreateDirectory(crashes_dir);
|
||||||
base::FilePath dumps_path(dump_dir);
|
|
||||||
base::CreateDirectory(dumps_path);
|
|
||||||
|
|
||||||
std::string log_file = base::StringPrintf(
|
std::string log_file = crashes_dir.Append("uploads.log").value();
|
||||||
"%s/%s", dump_dir.c_str(), "uploads.log");
|
|
||||||
strncpy(g_crash_log_path, log_file.c_str(), sizeof(g_crash_log_path));
|
strncpy(g_crash_log_path, log_file.c_str(), sizeof(g_crash_log_path));
|
||||||
|
|
||||||
MinidumpDescriptor minidump_descriptor(dumps_path.value());
|
MinidumpDescriptor minidump_descriptor(crashes_dir.value());
|
||||||
minidump_descriptor.set_size_limit(kMaxMinidumpFileSize);
|
minidump_descriptor.set_size_limit(kMaxMinidumpFileSize);
|
||||||
|
|
||||||
breakpad_.reset(new ExceptionHandler(
|
breakpad_.reset(new ExceptionHandler(
|
||||||
|
|
|
@ -31,6 +31,7 @@ class CrashReporterLinux : public CrashReporter {
|
||||||
const std::string& version,
|
const std::string& version,
|
||||||
const std::string& company_name,
|
const std::string& company_name,
|
||||||
const std::string& submit_url,
|
const std::string& submit_url,
|
||||||
|
const base::FilePath& crashes_dir,
|
||||||
bool auto_submit,
|
bool auto_submit,
|
||||||
bool skip_system_crash_handler) override;
|
bool skip_system_crash_handler) override;
|
||||||
void SetUploadParameters() override;
|
void SetUploadParameters() override;
|
||||||
|
@ -41,7 +42,7 @@ class CrashReporterLinux : public CrashReporter {
|
||||||
CrashReporterLinux();
|
CrashReporterLinux();
|
||||||
virtual ~CrashReporterLinux();
|
virtual ~CrashReporterLinux();
|
||||||
|
|
||||||
void EnableCrashDumping(const std::string& product_name);
|
void EnableCrashDumping(const base::FilePath& crashes_dir);
|
||||||
|
|
||||||
static bool CrashDone(const google_breakpad::MinidumpDescriptor& minidump,
|
static bool CrashDone(const google_breakpad::MinidumpDescriptor& minidump,
|
||||||
void* context,
|
void* context,
|
||||||
|
|
|
@ -27,6 +27,7 @@ class CrashReporterMac : public CrashReporter {
|
||||||
const std::string& version,
|
const std::string& version,
|
||||||
const std::string& company_name,
|
const std::string& company_name,
|
||||||
const std::string& submit_url,
|
const std::string& submit_url,
|
||||||
|
const base::FilePath& crashes_dir,
|
||||||
bool auto_submit,
|
bool auto_submit,
|
||||||
bool skip_system_crash_handler) override;
|
bool skip_system_crash_handler) override;
|
||||||
void SetUploadParameters() override;
|
void SetUploadParameters() override;
|
||||||
|
@ -42,7 +43,7 @@ class CrashReporterMac : public CrashReporter {
|
||||||
const base::StringPiece& value);
|
const base::StringPiece& value);
|
||||||
|
|
||||||
std::vector<UploadReportResult> GetUploadedReports(
|
std::vector<UploadReportResult> GetUploadedReports(
|
||||||
const std::string& path) override;
|
const base::FilePath& crashes_dir) override;
|
||||||
|
|
||||||
std::unique_ptr<crashpad::SimpleStringDictionary> simple_string_dictionary_;
|
std::unique_ptr<crashpad::SimpleStringDictionary> simple_string_dictionary_;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "base/files/file_path.h"
|
|
||||||
#include "base/files/file_util.h"
|
#include "base/files/file_util.h"
|
||||||
#include "base/mac/bundle_locations.h"
|
#include "base/mac/bundle_locations.h"
|
||||||
#include "base/mac/mac_util.h"
|
#include "base/mac/mac_util.h"
|
||||||
|
@ -31,15 +30,14 @@ void CrashReporterMac::InitBreakpad(const std::string& product_name,
|
||||||
const std::string& version,
|
const std::string& version,
|
||||||
const std::string& company_name,
|
const std::string& company_name,
|
||||||
const std::string& submit_url,
|
const std::string& submit_url,
|
||||||
|
const base::FilePath& crashes_dir,
|
||||||
bool auto_submit,
|
bool auto_submit,
|
||||||
bool skip_system_crash_handler) {
|
bool skip_system_crash_handler) {
|
||||||
// check whether crashpad has been initilized.
|
// check whether crashpad has been initialized.
|
||||||
// Only need to initilize once.
|
// Only need to initialize once.
|
||||||
if (simple_string_dictionary_)
|
if (simple_string_dictionary_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string dump_dir = "/tmp/" + product_name + " Crashes";
|
|
||||||
base::FilePath database_path(dump_dir);
|
|
||||||
if (is_browser_) {
|
if (is_browser_) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
base::FilePath framework_bundle_path = base::mac::FrameworkBundlePath();
|
base::FilePath framework_bundle_path = base::mac::FrameworkBundlePath();
|
||||||
|
@ -47,7 +45,7 @@ void CrashReporterMac::InitBreakpad(const std::string& product_name,
|
||||||
framework_bundle_path.Append("Resources").Append("crashpad_handler");
|
framework_bundle_path.Append("Resources").Append("crashpad_handler");
|
||||||
|
|
||||||
crashpad::CrashpadClient crashpad_client;
|
crashpad::CrashpadClient crashpad_client;
|
||||||
if (crashpad_client.StartHandler(handler_path, database_path,
|
if (crashpad_client.StartHandler(handler_path, crashes_dir,
|
||||||
submit_url,
|
submit_url,
|
||||||
StringMap(),
|
StringMap(),
|
||||||
std::vector<std::string>(),
|
std::vector<std::string>(),
|
||||||
|
@ -76,7 +74,7 @@ void CrashReporterMac::InitBreakpad(const std::string& product_name,
|
||||||
}
|
}
|
||||||
if (is_browser_) {
|
if (is_browser_) {
|
||||||
std::unique_ptr<crashpad::CrashReportDatabase> database =
|
std::unique_ptr<crashpad::CrashReportDatabase> database =
|
||||||
crashpad::CrashReportDatabase::Initialize(database_path);
|
crashpad::CrashReportDatabase::Initialize(crashes_dir);
|
||||||
if (database) {
|
if (database) {
|
||||||
database->GetSettings()->SetUploadsEnabled(auto_submit);
|
database->GetSettings()->SetUploadsEnabled(auto_submit);
|
||||||
}
|
}
|
||||||
|
@ -93,16 +91,15 @@ void CrashReporterMac::SetCrashKeyValue(const base::StringPiece& key,
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CrashReporter::UploadReportResult>
|
std::vector<CrashReporter::UploadReportResult>
|
||||||
CrashReporterMac::GetUploadedReports(const std::string& path) {
|
CrashReporterMac::GetUploadedReports(const base::FilePath& crashes_dir) {
|
||||||
std::vector<CrashReporter::UploadReportResult> uploaded_reports;
|
std::vector<CrashReporter::UploadReportResult> uploaded_reports;
|
||||||
|
|
||||||
base::FilePath file_path(path);
|
if (!base::PathExists(crashes_dir)) {
|
||||||
if (!base::PathExists(file_path)) {
|
|
||||||
return uploaded_reports;
|
return uploaded_reports;
|
||||||
}
|
}
|
||||||
// Load crashpad database.
|
// Load crashpad database.
|
||||||
std::unique_ptr<crashpad::CrashReportDatabase> database =
|
std::unique_ptr<crashpad::CrashReportDatabase> database =
|
||||||
crashpad::CrashReportDatabase::Initialize(file_path);
|
crashpad::CrashReportDatabase::Initialize(crashes_dir);
|
||||||
DCHECK(database);
|
DCHECK(database);
|
||||||
|
|
||||||
std::vector<crashpad::CrashReportDatabase::Report> completed_reports;
|
std::vector<crashpad::CrashReportDatabase::Report> completed_reports;
|
||||||
|
|
|
@ -149,16 +149,11 @@ void CrashReporterWin::InitBreakpad(const std::string& product_name,
|
||||||
const std::string& version,
|
const std::string& version,
|
||||||
const std::string& company_name,
|
const std::string& company_name,
|
||||||
const std::string& submit_url,
|
const std::string& submit_url,
|
||||||
|
const base::FilePath& crashes_dir,
|
||||||
bool auto_submit,
|
bool auto_submit,
|
||||||
bool skip_system_crash_handler) {
|
bool skip_system_crash_handler) {
|
||||||
skip_system_crash_handler_ = skip_system_crash_handler;
|
skip_system_crash_handler_ = skip_system_crash_handler;
|
||||||
|
|
||||||
base::FilePath temp_dir;
|
|
||||||
if (!base::GetTempDir(&temp_dir)) {
|
|
||||||
LOG(ERROR) << "Cannot get temp directory";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
base::string16 pipe_name = base::ReplaceStringPlaceholders(
|
base::string16 pipe_name = base::ReplaceStringPlaceholders(
|
||||||
kPipeNameFormat, base::UTF8ToUTF16(product_name), NULL);
|
kPipeNameFormat, base::UTF8ToUTF16(product_name), NULL);
|
||||||
base::string16 wait_name = base::ReplaceStringPlaceholders(
|
base::string16 wait_name = base::ReplaceStringPlaceholders(
|
||||||
|
@ -177,7 +172,7 @@ void CrashReporterWin::InitBreakpad(const std::string& product_name,
|
||||||
breakpad_.reset();
|
breakpad_.reset();
|
||||||
|
|
||||||
breakpad_.reset(new google_breakpad::ExceptionHandler(
|
breakpad_.reset(new google_breakpad::ExceptionHandler(
|
||||||
temp_dir.value(),
|
crashes_dir.DirName().value(),
|
||||||
FilterCallback,
|
FilterCallback,
|
||||||
MinidumpCallback,
|
MinidumpCallback,
|
||||||
this,
|
this,
|
||||||
|
|
|
@ -27,6 +27,7 @@ class CrashReporterWin : public CrashReporter {
|
||||||
const std::string& version,
|
const std::string& version,
|
||||||
const std::string& company_name,
|
const std::string& company_name,
|
||||||
const std::string& submit_url,
|
const std::string& submit_url,
|
||||||
|
const base::FilePath& crashes_dir,
|
||||||
bool auto_submit,
|
bool auto_submit,
|
||||||
bool skip_system_crash_handler) override;
|
bool skip_system_crash_handler) override;
|
||||||
void SetUploadParameters() override;
|
void SetUploadParameters() override;
|
||||||
|
|
|
@ -16,6 +16,7 @@ namespace crash_service {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const char kApplicationName[] = "application-name";
|
const char kApplicationName[] = "application-name";
|
||||||
|
const char kCrashesDirectory[] = "crashes-directory";
|
||||||
|
|
||||||
const wchar_t kPipeNameFormat[] = L"\\\\.\\pipe\\$1 Crash Service";
|
const wchar_t kPipeNameFormat[] = L"\\\\.\\pipe\\$1 Crash Service";
|
||||||
const wchar_t kStandardLogFile[] = L"operation_log.txt";
|
const wchar_t kStandardLogFile[] = L"operation_log.txt";
|
||||||
|
@ -25,17 +26,11 @@ void InvalidParameterHandler(const wchar_t*, const wchar_t*, const wchar_t*,
|
||||||
// noop.
|
// noop.
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetCrashServiceDirectory(const std::wstring& application_name,
|
bool CreateCrashServiceDirectory(const base::FilePath& temp_dir) {
|
||||||
base::FilePath* dir) {
|
|
||||||
base::FilePath temp_dir;
|
|
||||||
if (!base::GetTempDir(&temp_dir))
|
|
||||||
return false;
|
|
||||||
temp_dir = temp_dir.Append(application_name + L" Crashes");
|
|
||||||
if (!base::PathExists(temp_dir)) {
|
if (!base::PathExists(temp_dir)) {
|
||||||
if (!base::CreateDirectory(temp_dir))
|
if (!base::CreateDirectory(temp_dir))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*dir = temp_dir;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,9 +54,16 @@ int Main(const wchar_t* cmd) {
|
||||||
std::wstring application_name = cmd_line.GetSwitchValueNative(
|
std::wstring application_name = cmd_line.GetSwitchValueNative(
|
||||||
kApplicationName);
|
kApplicationName);
|
||||||
|
|
||||||
|
if (!cmd_line.HasSwitch(kCrashesDirectory)) {
|
||||||
|
LOG(ERROR) << "Crashes directory path must be specified with --"
|
||||||
|
<< kCrashesDirectory;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// We use/create a directory under the user's temp folder, for logging.
|
// We use/create a directory under the user's temp folder, for logging.
|
||||||
base::FilePath operating_dir;
|
base::FilePath operating_dir(
|
||||||
GetCrashServiceDirectory(application_name, &operating_dir);
|
cmd_line.GetSwitchValueNative(kCrashesDirectory));
|
||||||
|
CreateCrashServiceDirectory(operating_dir);
|
||||||
base::FilePath log_file = operating_dir.Append(kStandardLogFile);
|
base::FilePath log_file = operating_dir.Append(kStandardLogFile);
|
||||||
|
|
||||||
// Logging to stderr (to help with debugging failures on the
|
// Logging to stderr (to help with debugging failures on the
|
||||||
|
|
|
@ -22,6 +22,12 @@ following projects:
|
||||||
* [socorro](https://github.com/mozilla/socorro)
|
* [socorro](https://github.com/mozilla/socorro)
|
||||||
* [mini-breakpad-server](https://github.com/electron/mini-breakpad-server)
|
* [mini-breakpad-server](https://github.com/electron/mini-breakpad-server)
|
||||||
|
|
||||||
|
Crash reports are saved locally in an application-specific temp directory folder.
|
||||||
|
For a `productName` of `YourName`, crash reports will be stored in a folder
|
||||||
|
named `YourName Crashes` inside the temp directory. You can customize this temp
|
||||||
|
directory location for your app by calling the `app.setPath('temp', '/my/custom/temp')`
|
||||||
|
API before starting the crash reporter.
|
||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
|
|
||||||
The `crash-reporter` module has the following methods:
|
The `crash-reporter` module has the following methods:
|
||||||
|
|
|
@ -1,30 +1,20 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
|
const {spawn} = require('child_process')
|
||||||
const os = require('os')
|
const os = require('os')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const spawn = require('child_process').spawn
|
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
|
const {app} = process.type === 'browser' ? electron : electron.remote
|
||||||
const binding = process.atomBinding('crash_reporter')
|
const binding = process.atomBinding('crash_reporter')
|
||||||
|
|
||||||
var CrashReporter = (function () {
|
class CrashReporter {
|
||||||
function CrashReporter () {}
|
start (options) {
|
||||||
|
|
||||||
CrashReporter.prototype.start = function (options) {
|
|
||||||
var app, args, autoSubmit, companyName, env, extra, ignoreSystemCrashHandler, start, submitURL
|
|
||||||
if (options == null) {
|
if (options == null) {
|
||||||
options = {}
|
options = {}
|
||||||
}
|
}
|
||||||
this.productName = options.productName
|
this.productName = options.productName != null ? options.productName : app.getName()
|
||||||
companyName = options.companyName
|
let {autoSubmit, companyName, extra, ignoreSystemCrashHandler, submitURL} = options
|
||||||
submitURL = options.submitURL
|
|
||||||
autoSubmit = options.autoSubmit
|
|
||||||
ignoreSystemCrashHandler = options.ignoreSystemCrashHandler
|
|
||||||
extra = options.extra
|
|
||||||
|
|
||||||
app = (process.type === 'browser' ? electron : electron.remote).app
|
|
||||||
if (this.productName == null) {
|
|
||||||
this.productName = app.getName()
|
|
||||||
}
|
|
||||||
if (autoSubmit == null) {
|
if (autoSubmit == null) {
|
||||||
autoSubmit = true
|
autoSubmit = true
|
||||||
}
|
}
|
||||||
|
@ -35,7 +25,7 @@ var CrashReporter = (function () {
|
||||||
extra = {}
|
extra = {}
|
||||||
}
|
}
|
||||||
if (extra._productName == null) {
|
if (extra._productName == null) {
|
||||||
extra._productName = this.productName
|
extra._productName = this.getProductName()
|
||||||
}
|
}
|
||||||
if (extra._companyName == null) {
|
if (extra._companyName == null) {
|
||||||
extra._companyName = companyName
|
extra._companyName = companyName
|
||||||
|
@ -49,12 +39,15 @@ var CrashReporter = (function () {
|
||||||
if (submitURL == null) {
|
if (submitURL == null) {
|
||||||
throw new Error('submitURL is a required option to crashReporter.start')
|
throw new Error('submitURL is a required option to crashReporter.start')
|
||||||
}
|
}
|
||||||
start = () => {
|
|
||||||
binding.start(this.productName, companyName, submitURL, autoSubmit, ignoreSystemCrashHandler, extra)
|
|
||||||
}
|
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
args = ['--reporter-url=' + submitURL, '--application-name=' + this.productName, '--v=1']
|
const args = [
|
||||||
env = {
|
'--reporter-url=' + submitURL,
|
||||||
|
'--application-name=' + this.getProductName(),
|
||||||
|
'--crashes-directory=' + this.getCrashesDirectory(),
|
||||||
|
'--v=1'
|
||||||
|
]
|
||||||
|
const env = {
|
||||||
ELECTRON_INTERNAL_CRASH_SERVICE: 1
|
ELECTRON_INTERNAL_CRASH_SERVICE: 1
|
||||||
}
|
}
|
||||||
spawn(process.execPath, args, {
|
spawn(process.execPath, args, {
|
||||||
|
@ -62,12 +55,12 @@ var CrashReporter = (function () {
|
||||||
detached: true
|
detached: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return start()
|
|
||||||
|
binding.start(this.getProductName(), companyName, submitURL, this.getCrashesDirectory(), autoSubmit, ignoreSystemCrashHandler, extra)
|
||||||
}
|
}
|
||||||
|
|
||||||
CrashReporter.prototype.getLastCrashReport = function () {
|
getLastCrashReport () {
|
||||||
var reports
|
const reports = this.getUploadedReports()
|
||||||
reports = this.getUploadedReports()
|
|
||||||
if (reports.length > 0) {
|
if (reports.length > 0) {
|
||||||
return reports[0]
|
return reports[0]
|
||||||
} else {
|
} else {
|
||||||
|
@ -75,14 +68,33 @@ var CrashReporter = (function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CrashReporter.prototype.getUploadedReports = function () {
|
getUploadedReports () {
|
||||||
var log, tmpdir
|
return binding._getUploadedReports(this.getCrashesDirectory())
|
||||||
tmpdir = process.platform === 'win32' ? os.tmpdir() : '/tmp'
|
|
||||||
log = process.platform === 'darwin' ? path.join(tmpdir, this.productName + ' Crashes') : path.join(tmpdir, this.productName + ' Crashes', 'uploads.log')
|
|
||||||
return binding._getUploadedReports(log)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return CrashReporter
|
getCrashesDirectory () {
|
||||||
})()
|
const crashesDir = this.getProductName() + ' Crashes'
|
||||||
|
return path.join(this.getTempDirectory(), crashesDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
getProductName () {
|
||||||
|
if (this.productName == null) {
|
||||||
|
this.productName = app.getName()
|
||||||
|
}
|
||||||
|
return this.productName
|
||||||
|
}
|
||||||
|
|
||||||
|
getTempDirectory () {
|
||||||
|
if (this.tempDirectory == null) {
|
||||||
|
try {
|
||||||
|
this.tempDirectory = app.getPath('temp')
|
||||||
|
} catch (error) {
|
||||||
|
// app.getPath may throw so fallback to OS temp directory
|
||||||
|
this.tempDirectory = os.tmpdir()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.tempDirectory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = new CrashReporter()
|
module.exports = new CrashReporter()
|
||||||
|
|
|
@ -334,4 +334,23 @@ describe('app module', function () {
|
||||||
assert.equal(typeof app.isAccessibilitySupportEnabled(), 'boolean')
|
assert.equal(typeof app.isAccessibilitySupportEnabled(), 'boolean')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('getPath(name)', function () {
|
||||||
|
it('returns paths that exist', function () {
|
||||||
|
assert.equal(fs.existsSync(app.getPath('exe')), true)
|
||||||
|
assert.equal(fs.existsSync(app.getPath('home')), true)
|
||||||
|
assert.equal(fs.existsSync(app.getPath('temp')), true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws an error when the name is invalid', function () {
|
||||||
|
assert.throws(function () {
|
||||||
|
app.getPath('does-not-exist')
|
||||||
|
}, /Failed to get 'does-not-exist' path/)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns the overridden path', function () {
|
||||||
|
app.setPath('music', __dirname)
|
||||||
|
assert.equal(app.getPath('music'), __dirname)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,25 +2,30 @@ const assert = require('assert')
|
||||||
const http = require('http')
|
const http = require('http')
|
||||||
const multiparty = require('multiparty')
|
const multiparty = require('multiparty')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
const temp = require('temp').track()
|
||||||
const url = require('url')
|
const url = require('url')
|
||||||
const {closeWindow} = require('./window-helpers')
|
const {closeWindow} = require('./window-helpers')
|
||||||
|
|
||||||
const remote = require('electron').remote
|
const {remote} = require('electron')
|
||||||
const app = remote.require('electron').app
|
const {app, BrowserWindow, crashReporter} = remote.require('electron')
|
||||||
const crashReporter = remote.require('electron').crashReporter
|
|
||||||
const BrowserWindow = remote.require('electron').BrowserWindow
|
|
||||||
|
|
||||||
describe('crashReporter module', function () {
|
describe('crashReporter module', function () {
|
||||||
var fixtures = path.resolve(__dirname, 'fixtures')
|
var fixtures = path.resolve(__dirname, 'fixtures')
|
||||||
var w = null
|
var w = null
|
||||||
|
var originalTempDirectory = null
|
||||||
|
var tempDirectory = null
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
w = new BrowserWindow({
|
w = new BrowserWindow({
|
||||||
show: false
|
show: false
|
||||||
})
|
})
|
||||||
|
tempDirectory = temp.mkdirSync('electronCrashReporterSpec-')
|
||||||
|
originalTempDirectory = app.getPath('temp')
|
||||||
|
app.setPath('temp', tempDirectory)
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
|
app.setPath('temp', originalTempDirectory)
|
||||||
return closeWindow(w).then(function () { w = null })
|
return closeWindow(w).then(function () { w = null })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -54,11 +59,14 @@ describe('crashReporter module', function () {
|
||||||
assert.equal(fields['_companyName'], 'Umbrella Corporation')
|
assert.equal(fields['_companyName'], 'Umbrella Corporation')
|
||||||
assert.equal(fields['_version'], app.getVersion())
|
assert.equal(fields['_version'], app.getVersion())
|
||||||
|
|
||||||
res.end('abc-123-def', () => {
|
const reportId = 'abc-123-def-456-abc-789-abc-123-abcd'
|
||||||
assert.equal(crashReporter.getLastCrashReport().id, 'abc-123-def')
|
res.end(reportId, () => {
|
||||||
assert.notEqual(crashReporter.getUploadedReports().length, 0)
|
waitForCrashReport().then(() => {
|
||||||
assert.equal(crashReporter.getUploadedReports()[0].id, 'abc-123-def')
|
assert.equal(crashReporter.getLastCrashReport().id, reportId)
|
||||||
done()
|
assert.notEqual(crashReporter.getUploadedReports().length, 0)
|
||||||
|
assert.equal(crashReporter.getUploadedReports()[0].id, reportId)
|
||||||
|
done()
|
||||||
|
}, done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -110,3 +118,20 @@ describe('crashReporter module', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const waitForCrashReport = () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let times = 0
|
||||||
|
const checkForReport = () => {
|
||||||
|
if (crashReporter.getLastCrashReport() != null) {
|
||||||
|
resolve()
|
||||||
|
} else if (times >= 10) {
|
||||||
|
reject(new Error('No crash report available'))
|
||||||
|
} else {
|
||||||
|
times++
|
||||||
|
setTimeout(checkForReport, 100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkForReport()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ ipcMain.on('message', function (event, ...args) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Set productName so getUploadedReports() uses the right directory in specs
|
// Set productName so getUploadedReports() uses the right directory in specs
|
||||||
if (process.platform === 'win32') {
|
if (process.platform !== 'darwin') {
|
||||||
crashReporter.productName = 'Zombies'
|
crashReporter.productName = 'Zombies'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue