diff options
author | wolfbeast <mcwerewolf@wolfbeast.com> | 2019-04-01 13:05:24 +0200 |
---|---|---|
committer | wolfbeast <mcwerewolf@wolfbeast.com> | 2019-04-01 13:05:24 +0200 |
commit | ff2f287f82630ab3887d7d5c1e64e5b888ea0beb (patch) | |
tree | 4e96cb32aa2320a327024942d247c6b56ef8c199 /toolkit/crashreporter/google-breakpad/src/client/mac/sender/crash_report_sender.m | |
parent | bfc97728065cbbc7f6bbc281b654a2d1e079b48d (diff) | |
download | UXP-ff2f287f82630ab3887d7d5c1e64e5b888ea0beb.tar UXP-ff2f287f82630ab3887d7d5c1e64e5b888ea0beb.tar.gz UXP-ff2f287f82630ab3887d7d5c1e64e5b888ea0beb.tar.lz UXP-ff2f287f82630ab3887d7d5c1e64e5b888ea0beb.tar.xz UXP-ff2f287f82630ab3887d7d5c1e64e5b888ea0beb.zip |
Remove crashreporter toolkit files.
Resolves #20
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/client/mac/sender/crash_report_sender.m')
-rw-r--r-- | toolkit/crashreporter/google-breakpad/src/client/mac/sender/crash_report_sender.m | 755 |
1 files changed, 0 insertions, 755 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/sender/crash_report_sender.m b/toolkit/crashreporter/google-breakpad/src/client/mac/sender/crash_report_sender.m deleted file mode 100644 index 88d26fb03..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/mac/sender/crash_report_sender.m +++ /dev/null @@ -1,755 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#import "client/mac/sender/crash_report_sender.h" - -#import <Cocoa/Cocoa.h> -#import <pwd.h> -#import <sys/stat.h> -#import <SystemConfiguration/SystemConfiguration.h> -#import <unistd.h> - -#import "client/apple/Framework/BreakpadDefines.h" -#import "common/mac/GTMLogger.h" -#import "common/mac/HTTPMultipartUpload.h" - - -#define kLastSubmission @"LastSubmission" -const int kUserCommentsMaxLength = 1500; -const int kEmailMaxLength = 64; - -#define kApplePrefsSyncExcludeAllKey \ - @"com.apple.PreferenceSync.ExcludeAllSyncKeys" - -#pragma mark - - -@interface NSView (ResizabilityExtentions) -// Shifts the view vertically by the given amount. -- (void)breakpad_shiftVertically:(CGFloat)offset; - -// Shifts the view horizontally by the given amount. -- (void)breakpad_shiftHorizontally:(CGFloat)offset; -@end - -@implementation NSView (ResizabilityExtentions) -- (void)breakpad_shiftVertically:(CGFloat)offset { - NSPoint origin = [self frame].origin; - origin.y += offset; - [self setFrameOrigin:origin]; -} - -- (void)breakpad_shiftHorizontally:(CGFloat)offset { - NSPoint origin = [self frame].origin; - origin.x += offset; - [self setFrameOrigin:origin]; -} -@end - -@interface NSWindow (ResizabilityExtentions) -// Adjusts the window height by heightDelta relative to its current height, -// keeping all the content at the same size. -- (void)breakpad_adjustHeight:(CGFloat)heightDelta; -@end - -@implementation NSWindow (ResizabilityExtentions) -- (void)breakpad_adjustHeight:(CGFloat)heightDelta { - [[self contentView] setAutoresizesSubviews:NO]; - - NSRect windowFrame = [self frame]; - windowFrame.size.height += heightDelta; - [self setFrame:windowFrame display:YES]; - // For some reason the content view is resizing, but not adjusting its origin, - // so correct it manually. - [[self contentView] setFrameOrigin:NSMakePoint(0, 0)]; - - [[self contentView] setAutoresizesSubviews:YES]; -} -@end - -@interface NSTextField (ResizabilityExtentions) -// Grows or shrinks the height of the field to the minimum required to show the -// current text, preserving the existing width and origin. -// Returns the change in height. -- (CGFloat)breakpad_adjustHeightToFit; - -// Grows or shrinks the width of the field to the minimum required to show the -// current text, preserving the existing height and origin. -// Returns the change in width. -- (CGFloat)breakpad_adjustWidthToFit; -@end - -@implementation NSTextField (ResizabilityExtentions) -- (CGFloat)breakpad_adjustHeightToFit { - NSRect oldFrame = [self frame]; - // Starting with the 10.5 SDK, height won't grow, so make it huge to start. - NSRect presizeFrame = oldFrame; - presizeFrame.size.height = MAXFLOAT; - // sizeToFit will blow out the width rather than making the field taller, so - // we do it manually. - NSSize newSize = [[self cell] cellSizeForBounds:presizeFrame]; - NSRect newFrame = NSMakeRect(oldFrame.origin.x, oldFrame.origin.y, - NSWidth(oldFrame), newSize.height); - [self setFrame:newFrame]; - - return newSize.height - NSHeight(oldFrame); -} - -- (CGFloat)breakpad_adjustWidthToFit { - NSRect oldFrame = [self frame]; - [self sizeToFit]; - return NSWidth([self frame]) - NSWidth(oldFrame); -} -@end - -@interface NSButton (ResizabilityExtentions) -// Resizes to fit the label using IB-style size-to-fit metrics and enforcing a -// minimum width of 70, while preserving the right edge location. -// Returns the change in width. -- (CGFloat)breakpad_smartSizeToFit; -@end - -@implementation NSButton (ResizabilityExtentions) -- (CGFloat)breakpad_smartSizeToFit { - NSRect oldFrame = [self frame]; - [self sizeToFit]; - NSRect newFrame = [self frame]; - // sizeToFit gives much worse results that IB's Size to Fit option. This is - // the amount of padding IB adds over a sizeToFit, empirically determined. - const float kExtraPaddingAmount = 12; - const float kMinButtonWidth = 70; // The default button size in IB. - newFrame.size.width = NSWidth(newFrame) + kExtraPaddingAmount; - if (NSWidth(newFrame) < kMinButtonWidth) - newFrame.size.width = kMinButtonWidth; - // Preserve the right edge location. - newFrame.origin.x = NSMaxX(oldFrame) - NSWidth(newFrame); - [self setFrame:newFrame]; - return NSWidth(newFrame) - NSWidth(oldFrame); -} -@end - -#pragma mark - - -@interface Reporter(PrivateMethods) -- (id)initWithConfigFile:(const char *)configFile; - -// Returns YES if it has been long enough since the last report that we should -// submit a report for this crash. -- (BOOL)reportIntervalElapsed; - -// Returns YES if we should send the report without asking the user first. -- (BOOL)shouldSubmitSilently; - -// Returns YES if the minidump was generated on demand. -- (BOOL)isOnDemand; - -// Returns YES if we should ask the user to provide comments. -- (BOOL)shouldRequestComments; - -// Returns YES if we should ask the user to provide an email address. -- (BOOL)shouldRequestEmail; - -// Shows UI to the user to ask for permission to send and any extra information -// we've been instructed to request. Returns YES if the user allows the report -// to be sent. -- (BOOL)askUserPermissionToSend; - -// Returns the short description of the crash, suitable for use as a dialog -// title (e.g., "The application Foo has quit unexpectedly"). -- (NSString*)shortDialogMessage; - -// Return explanatory text about the crash and the reporter, suitable for the -// body text of a dialog. -- (NSString*)explanatoryDialogText; - -// Returns the amount of time the UI should be shown before timing out. -- (NSTimeInterval)messageTimeout; - -// Preps the comment-prompting alert window for display: -// * localizes all the elements -// * resizes and adjusts layout as necessary for localization -// * removes the email section if includeEmail is NO -- (void)configureAlertWindowIncludingEmail:(BOOL)includeEmail; - -// Rmevoes the email section of the dialog, adjusting the rest of the window -// as necessary. -- (void)removeEmailPrompt; - -// Run an alert window with the given timeout. Returns -// NSRunStoppedResponse if the timeout is exceeded. A timeout of 0 -// queues the message immediately in the modal run loop. -- (NSInteger)runModalWindow:(NSWindow*)window - withTimeout:(NSTimeInterval)timeout; - -// This method is used to periodically update the UI with how many -// seconds are left in the dialog display. -- (void)updateSecondsLeftInDialogDisplay:(NSTimer*)theTimer; - -// When we receive this notification, it means that the user has -// begun editing the email address or comments field, and we disable -// the timers so that the user has as long as they want to type -// in their comments/email. -- (void)controlTextDidBeginEditing:(NSNotification *)aNotification; - -- (void)report; - -@end - -@implementation Reporter -//============================================================================= -- (id)initWithConfigFile:(const char *)configFile { - if ((self = [super init])) { - remainingDialogTime_ = 0; - uploader_ = [[Uploader alloc] initWithConfigFile:configFile]; - if (!uploader_) { - [self release]; - return nil; - } - } - return self; -} - -//============================================================================= -- (BOOL)askUserPermissionToSend { - // Initialize Cocoa, needed to display the alert - NSApplicationLoad(); - - // Get the timeout value for the notification. - NSTimeInterval timeout = [self messageTimeout]; - - NSInteger buttonPressed = NSAlertAlternateReturn; - // Determine whether we should create a text box for user feedback. - if ([self shouldRequestComments]) { - BOOL didLoadNib = [NSBundle loadNibNamed:@"Breakpad" owner:self]; - if (!didLoadNib) { - return NO; - } - - [self configureAlertWindowIncludingEmail:[self shouldRequestEmail]]; - - buttonPressed = [self runModalWindow:alertWindow_ withTimeout:timeout]; - - // Extract info from the user into the uploader_. - if ([self commentsValue]) { - [[uploader_ parameters] setObject:[self commentsValue] - forKey:@BREAKPAD_COMMENTS]; - } - if ([self emailValue]) { - [[uploader_ parameters] setObject:[self emailValue] - forKey:@BREAKPAD_EMAIL]; - } - } else { - // Create an alert panel to tell the user something happened - NSPanel* alert = - NSGetAlertPanel([self shortDialogMessage], - @"%@", - NSLocalizedString(@"sendReportButton", @""), - NSLocalizedString(@"cancelButton", @""), - nil, - [self explanatoryDialogText]); - - // Pop the alert with an automatic timeout, and wait for the response - buttonPressed = [self runModalWindow:alert withTimeout:timeout]; - - // Release the panel memory - NSReleaseAlertPanel(alert); - } - return buttonPressed == NSAlertDefaultReturn; -} - -- (void)configureAlertWindowIncludingEmail:(BOOL)includeEmail { - // Swap in localized values, making size adjustments to impacted elements as - // we go. Remember that the origin is in the bottom left, so elements above - // "fall" as text areas are shrunk from their overly-large IB sizes. - - // Localize the header. No resizing needed, as it has plenty of room. - [dialogTitle_ setStringValue:[self shortDialogMessage]]; - - // Localize the explanatory text field. - [commentMessage_ setStringValue:[NSString stringWithFormat:@"%@\n\n%@", - [self explanatoryDialogText], - NSLocalizedString(@"commentsMsg", @"")]]; - CGFloat commentHeightDelta = [commentMessage_ breakpad_adjustHeightToFit]; - [headerBox_ breakpad_shiftVertically:commentHeightDelta]; - [alertWindow_ breakpad_adjustHeight:commentHeightDelta]; - - // Either localize the email explanation field or remove the whole email - // section depending on whether or not we are asking for email. - if (includeEmail) { - [emailMessage_ setStringValue:NSLocalizedString(@"emailMsg", @"")]; - CGFloat emailHeightDelta = [emailMessage_ breakpad_adjustHeightToFit]; - [preEmailBox_ breakpad_shiftVertically:emailHeightDelta]; - [alertWindow_ breakpad_adjustHeight:emailHeightDelta]; - } else { - [self removeEmailPrompt]; // Handles necessary resizing. - } - - // Localize the email label, and shift the associated text field. - [emailLabel_ setStringValue:NSLocalizedString(@"emailLabel", @"")]; - CGFloat emailLabelWidthDelta = [emailLabel_ breakpad_adjustWidthToFit]; - [emailEntryField_ breakpad_shiftHorizontally:emailLabelWidthDelta]; - - // Localize the privacy policy label, and keep it right-aligned to the arrow. - [privacyLinkLabel_ setStringValue:NSLocalizedString(@"privacyLabel", @"")]; - CGFloat privacyLabelWidthDelta = - [privacyLinkLabel_ breakpad_adjustWidthToFit]; - [privacyLinkLabel_ breakpad_shiftHorizontally:(-privacyLabelWidthDelta)]; - - // Ensure that the email field and the privacy policy link don't overlap. - CGFloat kMinControlPadding = 8; - CGFloat maxEmailFieldWidth = NSMinX([privacyLinkLabel_ frame]) - - NSMinX([emailEntryField_ frame]) - - kMinControlPadding; - if (NSWidth([emailEntryField_ bounds]) > maxEmailFieldWidth && - maxEmailFieldWidth > 0) { - NSSize emailSize = [emailEntryField_ frame].size; - emailSize.width = maxEmailFieldWidth; - [emailEntryField_ setFrameSize:emailSize]; - } - - // Localize the placeholder text. - [[commentsEntryField_ cell] - setPlaceholderString:NSLocalizedString(@"commentsPlaceholder", @"")]; - [[emailEntryField_ cell] - setPlaceholderString:NSLocalizedString(@"emailPlaceholder", @"")]; - - // Localize the buttons, and keep the cancel button at the right distance. - [sendButton_ setTitle:NSLocalizedString(@"sendReportButton", @"")]; - CGFloat sendButtonWidthDelta = [sendButton_ breakpad_smartSizeToFit]; - [cancelButton_ breakpad_shiftHorizontally:(-sendButtonWidthDelta)]; - [cancelButton_ setTitle:NSLocalizedString(@"cancelButton", @"")]; - [cancelButton_ breakpad_smartSizeToFit]; -} - -- (void)removeEmailPrompt { - [emailSectionBox_ setHidden:YES]; - CGFloat emailSectionHeight = NSHeight([emailSectionBox_ frame]); - [preEmailBox_ breakpad_shiftVertically:(-emailSectionHeight)]; - [alertWindow_ breakpad_adjustHeight:(-emailSectionHeight)]; -} - -- (NSInteger)runModalWindow:(NSWindow*)window - withTimeout:(NSTimeInterval)timeout { - // Queue a |stopModal| message to be performed in |timeout| seconds. - if (timeout > 0.001) { - remainingDialogTime_ = timeout; - SEL updateSelector = @selector(updateSecondsLeftInDialogDisplay:); - messageTimer_ = [NSTimer scheduledTimerWithTimeInterval:1.0 - target:self - selector:updateSelector - userInfo:nil - repeats:YES]; - } - - // Run the window modally and wait for either a |stopModal| message or a - // button click. - [NSApp activateIgnoringOtherApps:YES]; - NSInteger returnMethod = [NSApp runModalForWindow:window]; - - return returnMethod; -} - -- (IBAction)sendReport:(id)sender { - // Force the text fields to end editing so text for the currently focused - // field will be commited. - [alertWindow_ makeFirstResponder:alertWindow_]; - - [alertWindow_ orderOut:self]; - // Use NSAlertDefaultReturn so that the return value of |runModalWithWindow| - // matches the AppKit function NSRunAlertPanel() - [NSApp stopModalWithCode:NSAlertDefaultReturn]; -} - -// UI Button Actions -//============================================================================= -- (IBAction)cancel:(id)sender { - [alertWindow_ orderOut:self]; - // Use NSAlertDefaultReturn so that the return value of |runModalWithWindow| - // matches the AppKit function NSRunAlertPanel() - [NSApp stopModalWithCode:NSAlertAlternateReturn]; -} - -- (IBAction)showPrivacyPolicy:(id)sender { - // Get the localized privacy policy URL and open it in the default browser. - NSURL* privacyPolicyURL = - [NSURL URLWithString:NSLocalizedString(@"privacyPolicyURL", @"")]; - [[NSWorkspace sharedWorkspace] openURL:privacyPolicyURL]; -} - -// Text Field Delegate Methods -//============================================================================= -- (BOOL) control:(NSControl*)control - textView:(NSTextView*)textView -doCommandBySelector:(SEL)commandSelector { - BOOL result = NO; - // If the user has entered text on the comment field, don't end - // editing on "return". - if (control == commentsEntryField_ && - commandSelector == @selector(insertNewline:) - && [[textView string] length] > 0) { - [textView insertNewlineIgnoringFieldEditor:self]; - result = YES; - } - return result; -} - -- (void)controlTextDidBeginEditing:(NSNotification *)aNotification { - [messageTimer_ invalidate]; - [self setCountdownMessage:@""]; -} - -- (void)updateSecondsLeftInDialogDisplay:(NSTimer*)theTimer { - remainingDialogTime_ -= 1; - - NSString *countdownMessage; - NSString *formatString; - - int displayedTimeLeft; // This can be either minutes or seconds. - - if (remainingDialogTime_ > 59) { - // calculate minutes remaining for UI purposes - displayedTimeLeft = (int)(remainingDialogTime_ / 60); - - if (displayedTimeLeft == 1) { - formatString = NSLocalizedString(@"countdownMsgMinuteSingular", @""); - } else { - formatString = NSLocalizedString(@"countdownMsgMinutesPlural", @""); - } - } else { - displayedTimeLeft = (int)remainingDialogTime_; - if (displayedTimeLeft == 1) { - formatString = NSLocalizedString(@"countdownMsgSecondSingular", @""); - } else { - formatString = NSLocalizedString(@"countdownMsgSecondsPlural", @""); - } - } - countdownMessage = [NSString stringWithFormat:formatString, - displayedTimeLeft]; - if (remainingDialogTime_ <= 30) { - [countdownLabel_ setTextColor:[NSColor redColor]]; - } - [self setCountdownMessage:countdownMessage]; - if (remainingDialogTime_ <= 0) { - [messageTimer_ invalidate]; - [NSApp stopModal]; - } -} - - - -#pragma mark Accessors -#pragma mark - -//============================================================================= - -- (NSString *)commentsValue { - return [[commentsValue_ retain] autorelease]; -} - -- (void)setCommentsValue:(NSString *)value { - if (commentsValue_ != value) { - [commentsValue_ release]; - commentsValue_ = [value copy]; - } -} - -- (NSString *)emailValue { - return [[emailValue_ retain] autorelease]; -} - -- (void)setEmailValue:(NSString *)value { - if (emailValue_ != value) { - [emailValue_ release]; - emailValue_ = [value copy]; - } -} - -- (NSString *)countdownMessage { - return [[countdownMessage_ retain] autorelease]; -} - -- (void)setCountdownMessage:(NSString *)value { - if (countdownMessage_ != value) { - [countdownMessage_ release]; - countdownMessage_ = [value copy]; - } -} - -#pragma mark - -//============================================================================= -- (BOOL)reportIntervalElapsed { - float interval = [[[uploader_ parameters] - objectForKey:@BREAKPAD_REPORT_INTERVAL] floatValue]; - NSString *program = [[uploader_ parameters] objectForKey:@BREAKPAD_PRODUCT]; - NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; - NSMutableDictionary *programDict = - [NSMutableDictionary dictionaryWithDictionary:[ud dictionaryForKey:program]]; - NSNumber *lastTimeNum = [programDict objectForKey:kLastSubmission]; - NSTimeInterval lastTime = lastTimeNum ? [lastTimeNum floatValue] : 0; - NSTimeInterval now = CFAbsoluteTimeGetCurrent(); - NSTimeInterval spanSeconds = (now - lastTime); - - [programDict setObject:[NSNumber numberWithDouble:now] - forKey:kLastSubmission]; - [ud setObject:programDict forKey:program]; - [ud synchronize]; - - // If we've specified an interval and we're within that time, don't ask the - // user if we should report - GTMLoggerDebug(@"Reporter Interval: %f", interval); - if (interval > spanSeconds) { - GTMLoggerDebug(@"Within throttling interval, not sending report"); - return NO; - } - return YES; -} - -- (BOOL)isOnDemand { - return [[[uploader_ parameters] objectForKey:@BREAKPAD_ON_DEMAND] - isEqualToString:@"YES"]; -} - -- (BOOL)shouldSubmitSilently { - return [[[uploader_ parameters] objectForKey:@BREAKPAD_SKIP_CONFIRM] - isEqualToString:@"YES"]; -} - -- (BOOL)shouldRequestComments { - return [[[uploader_ parameters] objectForKey:@BREAKPAD_REQUEST_COMMENTS] - isEqualToString:@"YES"]; -} - -- (BOOL)shouldRequestEmail { - return [[[uploader_ parameters] objectForKey:@BREAKPAD_REQUEST_EMAIL] - isEqualToString:@"YES"]; -} - -- (NSString*)shortDialogMessage { - NSString *displayName = - [[uploader_ parameters] objectForKey:@BREAKPAD_PRODUCT_DISPLAY]; - if (![displayName length]) - displayName = [[uploader_ parameters] objectForKey:@BREAKPAD_PRODUCT]; - - if ([self isOnDemand]) { - // Local variable to pacify clang's -Wformat-extra-args. - NSString* format = NSLocalizedString(@"noCrashDialogHeader", @""); - return [NSString stringWithFormat:format, displayName]; - } else { - // Local variable to pacify clang's -Wformat-extra-args. - NSString* format = NSLocalizedString(@"crashDialogHeader", @""); - return [NSString stringWithFormat:format, displayName]; - } -} - -- (NSString*)explanatoryDialogText { - NSString *displayName = - [[uploader_ parameters] objectForKey:@BREAKPAD_PRODUCT_DISPLAY]; - if (![displayName length]) - displayName = [[uploader_ parameters] objectForKey:@BREAKPAD_PRODUCT]; - - NSString *vendor = [[uploader_ parameters] objectForKey:@BREAKPAD_VENDOR]; - if (![vendor length]) - vendor = @"unknown vendor"; - - if ([self isOnDemand]) { - // Local variable to pacify clang's -Wformat-extra-args. - NSString* format = NSLocalizedString(@"noCrashDialogMsg", @""); - return [NSString stringWithFormat:format, vendor, displayName]; - } else { - // Local variable to pacify clang's -Wformat-extra-args. - NSString* format = NSLocalizedString(@"crashDialogMsg", @""); - return [NSString stringWithFormat:format, vendor]; - } -} - -- (NSTimeInterval)messageTimeout { - // Get the timeout value for the notification. - NSTimeInterval timeout = [[[uploader_ parameters] - objectForKey:@BREAKPAD_CONFIRM_TIMEOUT] floatValue]; - // Require a timeout of at least a minute (except 0, which means no timeout). - if (timeout > 0.001 && timeout < 60.0) { - timeout = 60.0; - } - return timeout; -} - -- (void)report { - [uploader_ report]; -} - -//============================================================================= -- (void)dealloc { - [uploader_ release]; - [super dealloc]; -} - -- (void)awakeFromNib { - [emailEntryField_ setMaximumLength:kEmailMaxLength]; - [commentsEntryField_ setMaximumLength:kUserCommentsMaxLength]; -} - -@end - -//============================================================================= -@implementation LengthLimitingTextField - -- (void)setMaximumLength:(NSUInteger)maxLength { - maximumLength_ = maxLength; -} - -// This is the method we're overriding in NSTextField, which lets us -// limit the user's input if it makes the string too long. -- (BOOL) textView:(NSTextView *)textView -shouldChangeTextInRange:(NSRange)affectedCharRange - replacementString:(NSString *)replacementString { - - // Sometimes the range comes in invalid, so reject if we can't - // figure out if the replacement text is too long. - if (affectedCharRange.location == NSNotFound) { - return NO; - } - // Figure out what the new string length would be, taking into - // account user selections. - NSUInteger newStringLength = - [[textView string] length] - affectedCharRange.length + - [replacementString length]; - if (newStringLength > maximumLength_) { - return NO; - } else { - return YES; - } -} - -// Cut, copy, and paste have to be caught specifically since there is no menu. -- (BOOL)performKeyEquivalent:(NSEvent*)event { - // Only handle the key equivalent if |self| is the text field with focus. - NSText* fieldEditor = [self currentEditor]; - if (fieldEditor != nil) { - // Check for a single "Command" modifier - NSUInteger modifiers = [event modifierFlags]; - modifiers &= NSDeviceIndependentModifierFlagsMask; - if (modifiers == NSCommandKeyMask) { - // Now, check for Select All, Cut, Copy, or Paste key equivalents. - NSString* characters = [event characters]; - // Select All is Command-A. - if ([characters isEqualToString:@"a"]) { - [fieldEditor selectAll:self]; - return YES; - // Cut is Command-X. - } else if ([characters isEqualToString:@"x"]) { - [fieldEditor cut:self]; - return YES; - // Copy is Command-C. - } else if ([characters isEqualToString:@"c"]) { - [fieldEditor copy:self]; - return YES; - // Paste is Command-V. - } else if ([characters isEqualToString:@"v"]) { - [fieldEditor paste:self]; - return YES; - } - } - } - // Let the super class handle the rest (e.g. Command-Period will cancel). - return [super performKeyEquivalent:event]; -} - -@end - -//============================================================================= -int main(int argc, const char *argv[]) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; -#if DEBUG - // Log to stderr in debug builds. - [GTMLogger setSharedLogger:[GTMLogger standardLoggerWithStderr]]; -#endif - GTMLoggerDebug(@"Reporter Launched, argc=%d", argc); - // The expectation is that there will be one argument which is the path - // to the configuration file - if (argc != 2) { - exit(1); - } - - Reporter *reporter = [[Reporter alloc] initWithConfigFile:argv[1]]; - if (!reporter) { - GTMLoggerDebug(@"reporter initialization failed"); - exit(1); - } - - // only submit a report if we have not recently crashed in the past - BOOL shouldSubmitReport = [reporter reportIntervalElapsed]; - BOOL okayToSend = NO; - - // ask user if we should send - if (shouldSubmitReport) { - if ([reporter shouldSubmitSilently]) { - GTMLoggerDebug(@"Skipping confirmation and sending report"); - okayToSend = YES; - } else { - okayToSend = [reporter askUserPermissionToSend]; - } - } - - // If we're running as root, switch over to nobody - if (getuid() == 0 || geteuid() == 0) { - struct passwd *pw = getpwnam("nobody"); - - // If we can't get a non-root uid, don't send the report - if (!pw) { - GTMLoggerDebug(@"!pw - %s", strerror(errno)); - exit(0); - } - - if (setgid(pw->pw_gid) == -1) { - GTMLoggerDebug(@"setgid(pw->pw_gid) == -1 - %s", strerror(errno)); - exit(0); - } - - if (setuid(pw->pw_uid) == -1) { - GTMLoggerDebug(@"setuid(pw->pw_uid) == -1 - %s", strerror(errno)); - exit(0); - } - } - else { - GTMLoggerDebug(@"getuid() !=0 || geteuid() != 0"); - } - - if (okayToSend && shouldSubmitReport) { - GTMLoggerDebug(@"Sending Report"); - [reporter report]; - GTMLoggerDebug(@"Report Sent!"); - } else { - GTMLoggerDebug(@"Not sending crash report okayToSend=%d, "\ - "shouldSubmitReport=%d", okayToSend, shouldSubmitReport); - } - - GTMLoggerDebug(@"Exiting with no errors"); - // Cleanup - [reporter release]; - [pool release]; - return 0; -} |