diff options
Diffstat (limited to 'src/client/mac/Framework')
-rw-r--r-- | src/client/mac/Framework/Breakpad.h | 110 | ||||
-rw-r--r-- | src/client/mac/Framework/Breakpad.mm | 106 |
2 files changed, 160 insertions, 56 deletions
diff --git a/src/client/mac/Framework/Breakpad.h b/src/client/mac/Framework/Breakpad.h index 88be8162..ab4d6220 100644 --- a/src/client/mac/Framework/Breakpad.h +++ b/src/client/mac/Framework/Breakpad.h @@ -81,15 +81,15 @@ extern "C" { #define BREAKPAD_REQUEST_EMAIL "BreakpadRequestEmail" #define BREAKPAD_EMAIL "BreakpadEmail" #define BREAKPAD_SERVER_TYPE "BreakpadServerType" -// TODO(nealsid) find a better way to support server-specific -// parameters without having to rebuild Breakpad -#define BREAKPAD_BUILD_ID "BreakpadBuildID" +#define BREAKPAD_SERVER_PARAMETER_DICT "BreakpadServerParameters" // The keys below are NOT user supplied, and are used internally. -#define BREAKPAD_PROCESS_START_TIME "BreakpadProcStartTime" -#define BREAKPAD_PROCESS_UP_TIME "BreakpadProcessUpTime" -#define BREAKPAD_PROCESS_CRASH_TIME "BreakpadProcessCrashTime" -#define BREAKPAD_LOGFILE_KEY_PREFIX "BreakpadAppLogFile" +#define BREAKPAD_PROCESS_START_TIME "BreakpadProcStartTime" +#define BREAKPAD_PROCESS_UP_TIME "BreakpadProcessUpTime" +#define BREAKPAD_PROCESS_CRASH_TIME "BreakpadProcessCrashTime" +#define BREAKPAD_LOGFILE_KEY_PREFIX "BreakpadAppLogFile" +#define BREAKPAD_SERVER_PARAMETER_PREFIX "BreakpadServerParameterPrefix_" + // Optional user-defined function to dec to decide if we should handle // this crash or forward it along. // Return true if you want Breakpad to handle it. @@ -98,7 +98,8 @@ extern "C" { // (which means the next exception handler will take the exception) typedef bool (*BreakpadFilterCallback)(int exception_type, int exception_code, - mach_port_t crashing_thread); + mach_port_t crashing_thread, + void *context); // Create a new BreakpadRef object and install it as an exception // handler. The |parameters| will typically be the contents of your @@ -179,8 +180,15 @@ typedef bool (*BreakpadFilterCallback)(int exception_type, // other types, see the function in // crash_report_sender.m that maps parameters to // URL parameters. Defaults to 'google'. -// BREAKPAD_BUILD_ID A string parameter indicating build id. -// Optional. +// +// BREAKPAD_SERVER_PARAMETER_DICT A plist dictionary of static +// parameters that are uploaded to the +// server. The parameters are sent as +// is to the crash server. Their +// content isn't added to the minidump +// but pass as URL parameters when +// uploading theminidump to the crash +// server. //============================================================================= // The BREAKPAD_PRODUCT, BREAKPAD_VERSION and BREAKPAD_URL are // required to have non-NULL values. By default, the BREAKPAD_PRODUCT @@ -209,17 +217,31 @@ typedef bool (*BreakpadFilterCallback)(int exception_type, // completeness. They are calculated by Breakpad during initialization & // crash-dump generation. // -// BREAKPAD_PROCESS_START_TIME The time the process started. +// BREAKPAD_PROCESS_START_TIME The time the process started. +// +// BREAKPAD_PROCESS_CRASH_TIME The time the process crashed. +// +// BREAKPAD_PROCESS_UP_TIME The total time the process has been +// running. This parameter is not set +// until the crash-dump-generation phase. // -// BREAKPAD_PROCESS_CRASH_TIME The time the process crashed. +// BREAKPAD_LOGFILE_KEY_PREFIX Used to find out which parameters in the +// parameter dictionary correspond to log +// file paths. // -// BREAKPAD_PROCESS_UP_TIME The total time the process has been running. -// This parameter is not set until the -// crash-dump-generation phase. +// BREAKPAD_SERVER_PARAMETER_PREFIX This prefix is used by Breakpad +// internally, because Breakpad uses +// the same dictionary internally to +// track both its internal +// configuration parameters and +// parameters meant to be uploaded +// to the server. This string is +// used internally by Breakpad to +// prefix user-supplied parameter +// names so those can be sent to the +// server without leaking Breakpad's +// internal values. // -// BREAKPAD_LOGFILE_KEY_PREFIX Used to find out which parameters in the -// parameter dictionary correspond to log file -// paths. // Returns a new BreakpadRef object on success, NULL otherwise. BreakpadRef BreakpadCreate(NSDictionary *parameters); @@ -227,27 +249,49 @@ BreakpadRef BreakpadCreate(NSDictionary *parameters); // Uninstall and release the data associated with |ref|. void BreakpadRelease(BreakpadRef ref); -// Clients may set an optional callback which gets called when a crash occurs. -// The callback function should return |true| if we should handle the crash, -// generate a crash report, etc. or |false| if we should ignore it and forward -// the crash (normally to CrashReporter) +// Clients may set an optional callback which gets called when a crash +// occurs. The callback function should return |true| if we should +// handle the crash, generate a crash report, etc. or |false| if we +// should ignore it and forward the crash (normally to CrashReporter). +// Context is a pointer to arbitrary data to make the callback with. void BreakpadSetFilterCallback(BreakpadRef ref, - BreakpadFilterCallback callback); + BreakpadFilterCallback callback, + void *context); -// User defined key and value string storage -// All set keys will be uploaded with the minidump if a crash occurs -// Keys and Values are limited to 255 bytes (256 - 1 for terminator). -// NB this is BYTES not GLYPHS. -// Anything longer than 255 bytes will be truncated. Note that the string is -// converted to UTF8 before truncation, so any multibyte character that -// straddles the 255 byte limit will be mangled. -// -// A maximum number of 64 key/value pairs are supported. An assert() will fire -// if more than this number are set. +// User defined key and value string storage. Generally this is used +// to configure Breakpad's internal operation, such as whether the +// crash_sender should prompt the user, or the filesystem location for +// the minidump file. See Breakpad.h for some parameters that can be +// set. Anything longer than 255 bytes will be truncated. Note that +// the string is converted to UTF8 before truncation, so any multibyte +// character that straddles the 255(256 - 1 for terminator) byte limit +// will be mangled. +// +// A maximum number of 64 key/value pairs are supported. An assert() +// will fire if more than this number are set. Unfortunately, right +// now, the same dictionary is used for both Breakpad's parameters AND +// the Upload parameters. +// +// TODO (nealsid): Investigate how necessary this is if we don't +// automatically upload parameters to the server anymore. +// TODO (nealsid): separate server parameter dictionary from the +// dictionary used to configure Breakpad, and document limits for each +// independently. void BreakpadSetKeyValue(BreakpadRef ref, NSString *key, NSString *value); NSString *BreakpadKeyValue(BreakpadRef ref, NSString *key); void BreakpadRemoveKeyValue(BreakpadRef ref, NSString *key); +// You can use this method to specify parameters that will be uploaded +// to the crash server. They will be automatically encoded as +// necessary. Note that as mentioned above there are limits on both +// the number of keys and their length. +void BreakpadAddUploadParameter(BreakpadRef ref, NSString *key, + NSString *value); + +// This method will remove a previously-added parameter from the +// upload parameter set. +void BreakpadRemoveUploadParameter(BreakpadRef ref, NSString *key); + // Add a log file for Breakpad to read and send upon crash dump void BreakpadAddLogFile(BreakpadRef ref, NSString *logPathname); diff --git a/src/client/mac/Framework/Breakpad.mm b/src/client/mac/Framework/Breakpad.mm index ad4a1cda..e2b87141 100644 --- a/src/client/mac/Framework/Breakpad.mm +++ b/src/client/mac/Framework/Breakpad.mm @@ -154,8 +154,9 @@ class Breakpad { void GenerateAndSendReport(); - void SetFilterCallback(BreakpadFilterCallback callback) { + void SetFilterCallback(BreakpadFilterCallback callback, void *context) { filter_callback_ = callback; + filter_callback_context_ = context; } private: @@ -163,7 +164,8 @@ class Breakpad { : handler_(NULL), config_params_(NULL), send_and_exit_(true), - filter_callback_(NULL) { + filter_callback_(NULL), + filter_callback_context_(NULL) { inspector_path_[0] = 0; } @@ -194,8 +196,7 @@ class Breakpad { bool send_and_exit_; // Exit after sending, if true BreakpadFilterCallback filter_callback_; - - unsigned int logFileCounter; + void *filter_callback_context_; }; #pragma mark - @@ -412,8 +413,10 @@ bool Breakpad::ExtractParameters(NSDictionary *parameters) { [parameters objectForKey:@BREAKPAD_VENDOR]; NSString *dumpSubdirectory = [parameters objectForKey:@BREAKPAD_DUMP_DIRECTORY]; - NSString *buildId = - [parameters objectForKey:@BREAKPAD_BUILD_ID]; + + NSDictionary *serverParameters = + [parameters objectForKey:@BREAKPAD_SERVER_PARAMETER_DICT]; + // These may have been set above as user prefs, which take priority. if (!skipConfirm) { skipConfirm = [parameters objectForKey:@BREAKPAD_SKIP_CONFIRM]; @@ -521,10 +524,19 @@ bool Breakpad::ExtractParameters(NSDictionary *parameters) { dumpSubdirectory = @""; } - // The product and version are required values. - if (![product length] || ![version length]) { - DEBUGLOG(stderr, - "Missing required product or version subdirectory keys\n"); + // The product, version, and URL are required values. + if (![product length]) { + DEBUGLOG(stderr, "Missing required product key.\n"); + return false; + } + + if (![version length]) { + DEBUGLOG(stderr, "Missing required version key.\n"); + return false; + } + + if (![urlStr length]) { + DEBUGLOG(stderr, "Missing required URL key.\n"); return false; } @@ -555,8 +567,6 @@ bool Breakpad::ExtractParameters(NSDictionary *parameters) { dictionary.SetKeyValue(BREAKPAD_DUMP_DIRECTORY, [dumpSubdirectory UTF8String]); - dictionary.SetKeyValue(BREAKPAD_BUILD_ID, - [buildId UTF8String]); struct timeval tv; gettimeofday(&tv, NULL); char timeStartedString[32]; @@ -579,6 +589,15 @@ bool Breakpad::ExtractParameters(NSDictionary *parameters) { [reportEmail UTF8String]); } + if (serverParameters) { + // For each key-value pair, call BreakpadAddUploadParameter() + NSEnumerator *keyEnumerator = [serverParameters keyEnumerator]; + NSString *aParameter; + while (aParameter = [keyEnumerator nextObject]) { + BreakpadAddUploadParameter(this, aParameter, + [serverParameters objectForKey:aParameter]); + } + } return true; } @@ -622,7 +641,8 @@ bool Breakpad::HandleException(int exception_type, if (filter_callback_) { bool should_handle = filter_callback_(exception_type, exception_code, - crashing_thread); + crashing_thread, + filter_callback_context_); if (!should_handle) return false; } @@ -769,7 +789,7 @@ BreakpadRef BreakpadCreate(NSDictionary *parameters) { [pool release]; return (BreakpadRef)breakpad; - } catch(...) { // don't let exception leave this C API + } catch(...) { // don't let exceptions leave this C API if (gKeyValueAllocator) { gKeyValueAllocator->~ProtectedMemoryAllocator(); gKeyValueAllocator = NULL; @@ -817,7 +837,7 @@ void BreakpadRelease(BreakpadRef ref) { pthread_mutex_destroy(&gDictionaryMutex); } - } catch(...) { // don't let exception leave this C API + } catch(...) { // don't let exceptions leave this C API fprintf(stderr, "BreakpadRelease() : error\n"); } } @@ -833,11 +853,51 @@ void BreakpadSetKeyValue(BreakpadRef ref, NSString *key, NSString *value) { breakpad->SetKeyValue(key, value); } - } catch(...) { // don't let exception leave this C API + } catch(...) { // don't let exceptions leave this C API + fprintf(stderr, "BreakpadSetKeyValue() : error\n"); + } +} + +void BreakpadAddUploadParameter(BreakpadRef ref, + NSString *key, + NSString *value) { + // The only difference, internally, between an upload parameter and + // a key value one that is set with BreakpadSetKeyValue is that we + // prepend the keyname with a special prefix. This informs the + // crash sender that the parameter should be sent along with the + // POST of the crash dump upload. + try { + Breakpad *breakpad = (Breakpad *)ref; + + if (breakpad && key && gKeyValueAllocator) { + ProtectedMemoryLocker locker(&gDictionaryMutex, gKeyValueAllocator); + + NSString *prefixedKey = [@BREAKPAD_SERVER_PARAMETER_PREFIX + stringByAppendingString:key]; + breakpad->SetKeyValue(prefixedKey, value); + } + } catch(...) { // don't let exceptions leave this C API fprintf(stderr, "BreakpadSetKeyValue() : error\n"); } } +void BreakpadRemoveUploadParameter(BreakpadRef ref, + NSString *key) { + try { + // Not called at exception time + Breakpad *breakpad = (Breakpad *)ref; + + if (breakpad && key && gKeyValueAllocator) { + ProtectedMemoryLocker locker(&gDictionaryMutex, gKeyValueAllocator); + + NSString *prefixedKey = [NSString stringWithFormat:@"%@%@", + @BREAKPAD_SERVER_PARAMETER_PREFIX, key]; + breakpad->RemoveKeyValue(prefixedKey); + } + } catch(...) { // don't let exceptions leave this C API + fprintf(stderr, "BreakpadRemoveKeyValue() : error\n"); + } +} //============================================================================= NSString *BreakpadKeyValue(BreakpadRef ref, NSString *key) { NSString *value = nil; @@ -852,7 +912,7 @@ NSString *BreakpadKeyValue(BreakpadRef ref, NSString *key) { ProtectedMemoryLocker locker(&gDictionaryMutex, gKeyValueAllocator); value = breakpad->KeyValue(key); - } catch(...) { // don't let exception leave this C API + } catch(...) { // don't let exceptions leave this C API fprintf(stderr, "BreakpadKeyValue() : error\n"); } @@ -870,7 +930,7 @@ void BreakpadRemoveKeyValue(BreakpadRef ref, NSString *key) { breakpad->RemoveKeyValue(key); } - } catch(...) { // don't let exception leave this C API + } catch(...) { // don't let exceptions leave this C API fprintf(stderr, "BreakpadRemoveKeyValue() : error\n"); } } @@ -887,14 +947,15 @@ void BreakpadGenerateAndSendReport(BreakpadRef ref) { breakpad->GenerateAndSendReport(); gBreakpadAllocator->Protect(); } - } catch(...) { // don't let exception leave this C API + } catch(...) { // don't let exceptions leave this C API fprintf(stderr, "BreakpadGenerateAndSendReport() : error\n"); } } //============================================================================= void BreakpadSetFilterCallback(BreakpadRef ref, - BreakpadFilterCallback callback) { + BreakpadFilterCallback callback, + void *context) { try { Breakpad *breakpad = (Breakpad *)ref; @@ -903,9 +964,9 @@ void BreakpadSetFilterCallback(BreakpadRef ref, // share the dictionary mutex here (we really don't need a mutex) ProtectedMemoryLocker locker(&gDictionaryMutex, gBreakpadAllocator); - breakpad->SetFilterCallback(callback); + breakpad->SetFilterCallback(callback, context); } - } catch(...) { // don't let exception leave this C API + } catch(...) { // don't let exceptions leave this C API fprintf(stderr, "BreakpadSetFilterCallback() : error\n"); } } @@ -933,5 +994,4 @@ void BreakpadAddLogFile(BreakpadRef ref, NSString *logPathname) { } BreakpadSetKeyValue(ref, logFileKey, logPathname); - } |