diff options
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/client/ios/BreakpadController.mm')
-rw-r--r-- | toolkit/crashreporter/google-breakpad/src/client/ios/BreakpadController.mm | 354 |
1 files changed, 0 insertions, 354 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/client/ios/BreakpadController.mm b/toolkit/crashreporter/google-breakpad/src/client/ios/BreakpadController.mm deleted file mode 100644 index dd71cff68..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/ios/BreakpadController.mm +++ /dev/null @@ -1,354 +0,0 @@ -// Copyright (c) 2012, 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 "BreakpadController.h" - -#import <UIKit/UIKit.h> -#include <asl.h> -#include <execinfo.h> -#include <signal.h> -#include <unistd.h> -#include <sys/sysctl.h> - -#include <common/scoped_ptr.h> - -#pragma mark - -#pragma mark Private Methods - -@interface BreakpadController () - -// Init the singleton instance. -- (id)initSingleton; - -// Load a crash report and send it to the server. -- (void)sendStoredCrashReports; - -// Returns when a report can be sent. |-1| means never, |0| means that a report -// can be sent immediately, a positive number is the number of seconds to wait -// before being allowed to upload a report. -- (int)sendDelay; - -// Notifies that a report will be sent, and update the last sending time -// accordingly. -- (void)reportWillBeSent; - -@end - -#pragma mark - -#pragma mark Anonymous namespace - -namespace { - -// The name of the user defaults key for the last submission to the crash -// server. -NSString* const kLastSubmission = @"com.google.Breakpad.LastSubmission"; - -// Returns a NSString describing the current platform. -NSString* GetPlatform() { - // Name of the system call for getting the platform. - static const char kHwMachineSysctlName[] = "hw.machine"; - - NSString* result = nil; - - size_t size = 0; - if (sysctlbyname(kHwMachineSysctlName, NULL, &size, NULL, 0) || size == 0) - return nil; - google_breakpad::scoped_array<char> machine(new char[size]); - if (sysctlbyname(kHwMachineSysctlName, machine.get(), &size, NULL, 0) == 0) - result = [NSString stringWithUTF8String:machine.get()]; - return result; -} - -} // namespace - -#pragma mark - -#pragma mark BreakpadController Implementation - -@implementation BreakpadController - -+ (BreakpadController*)sharedInstance { - @synchronized(self) { - static BreakpadController* sharedInstance_ = - [[BreakpadController alloc] initSingleton]; - return sharedInstance_; - } -} - -- (id)init { - return nil; -} - -- (id)initSingleton { - self = [super init]; - if (self) { - queue_ = dispatch_queue_create("com.google.BreakpadQueue", NULL); - enableUploads_ = NO; - started_ = NO; - [self resetConfiguration]; - } - return self; -} - -// Since this class is a singleton, this method is not expected to be called. -- (void)dealloc { - assert(!breakpadRef_); - dispatch_release(queue_); - [configuration_ release]; - [uploadTimeParameters_ release]; - [super dealloc]; -} - -#pragma mark - - -- (void)start:(BOOL)onCurrentThread { - if (started_) - return; - started_ = YES; - void(^startBlock)() = ^{ - assert(!breakpadRef_); - breakpadRef_ = BreakpadCreate(configuration_); - if (breakpadRef_) { - BreakpadAddUploadParameter(breakpadRef_, @"platform", GetPlatform()); - } - }; - if (onCurrentThread) - startBlock(); - else - dispatch_async(queue_, startBlock); -} - -- (void)stop { - if (!started_) - return; - started_ = NO; - dispatch_sync(queue_, ^{ - if (breakpadRef_) { - BreakpadRelease(breakpadRef_); - breakpadRef_ = NULL; - } - }); -} - -// This method must be called from the breakpad queue. -- (void)threadUnsafeSendReportWithConfiguration:(NSDictionary*)configuration - withBreakpadRef:(BreakpadRef)ref { - NSAssert(started_, @"The controller must be started before " - "threadUnsafeSendReportWithConfiguration is called"); - if (breakpadRef_) { - BreakpadUploadReportWithParametersAndConfiguration(breakpadRef_, - uploadTimeParameters_, - configuration); - } -} - -- (void)setUploadingEnabled:(BOOL)enabled { - NSAssert(started_, - @"The controller must be started before setUploadingEnabled is called"); - dispatch_async(queue_, ^{ - if (enabled == enableUploads_) - return; - if (enabled) { - // Set this before calling doSendStoredCrashReport, because that - // calls sendDelay, which in turn checks this flag. - enableUploads_ = YES; - [self sendStoredCrashReports]; - } else { - enableUploads_ = NO; - [NSObject cancelPreviousPerformRequestsWithTarget:self - selector:@selector(sendStoredCrashReports) - object:nil]; - } - }); -} - -- (void)updateConfiguration:(NSDictionary*)configuration { - NSAssert(!started_, - @"The controller must not be started when updateConfiguration is called"); - [configuration_ addEntriesFromDictionary:configuration]; - NSString* uploadInterval = - [configuration_ valueForKey:@BREAKPAD_REPORT_INTERVAL]; - if (uploadInterval) - [self setUploadInterval:[uploadInterval intValue]]; -} - -- (void)resetConfiguration { - NSAssert(!started_, - @"The controller must not be started when resetConfiguration is called"); - [configuration_ autorelease]; - configuration_ = [[[NSBundle mainBundle] infoDictionary] mutableCopy]; - NSString* uploadInterval = - [configuration_ valueForKey:@BREAKPAD_REPORT_INTERVAL]; - [self setUploadInterval:[uploadInterval intValue]]; - [self setParametersToAddAtUploadTime:nil]; -} - -- (void)setUploadingURL:(NSString*)url { - NSAssert(!started_, - @"The controller must not be started when setUploadingURL is called"); - [configuration_ setValue:url forKey:@BREAKPAD_URL]; -} - -- (void)setUploadInterval:(int)intervalInSeconds { - NSAssert(!started_, - @"The controller must not be started when setUploadInterval is called"); - [configuration_ removeObjectForKey:@BREAKPAD_REPORT_INTERVAL]; - uploadIntervalInSeconds_ = intervalInSeconds; - if (uploadIntervalInSeconds_ < 0) - uploadIntervalInSeconds_ = 0; -} - -- (void)setParametersToAddAtUploadTime:(NSDictionary*)uploadTimeParameters { - NSAssert(!started_, @"The controller must not be started when " - "setParametersToAddAtUploadTime is called"); - [uploadTimeParameters_ autorelease]; - uploadTimeParameters_ = [uploadTimeParameters copy]; -} - -- (void)addUploadParameter:(NSString*)value forKey:(NSString*)key { - NSAssert(started_, - @"The controller must be started before addUploadParameter is called"); - dispatch_async(queue_, ^{ - if (breakpadRef_) - BreakpadAddUploadParameter(breakpadRef_, key, value); - }); -} - -- (void)removeUploadParameterForKey:(NSString*)key { - NSAssert(started_, @"The controller must be started before " - "removeUploadParameterForKey is called"); - dispatch_async(queue_, ^{ - if (breakpadRef_) - BreakpadRemoveUploadParameter(breakpadRef_, key); - }); -} - -- (void)withBreakpadRef:(void(^)(BreakpadRef))callback { - NSAssert(started_, - @"The controller must be started before withBreakpadRef is called"); - dispatch_async(queue_, ^{ - callback(breakpadRef_); - }); -} - -- (void)hasReportToUpload:(void(^)(BOOL))callback { - NSAssert(started_, @"The controller must be started before " - "hasReportToUpload is called"); - dispatch_async(queue_, ^{ - callback(breakpadRef_ && (BreakpadGetCrashReportCount(breakpadRef_) > 0)); - }); -} - -- (void)getCrashReportCount:(void(^)(int))callback { - NSAssert(started_, @"The controller must be started before " - "getCrashReportCount is called"); - dispatch_async(queue_, ^{ - callback(breakpadRef_ ? BreakpadGetCrashReportCount(breakpadRef_) : 0); - }); -} - -- (void)getNextReportConfigurationOrSendDelay: - (void(^)(NSDictionary*, int))callback { - NSAssert(started_, @"The controller must be started before " - "getNextReportConfigurationOrSendDelay is called"); - dispatch_async(queue_, ^{ - if (!breakpadRef_) { - callback(nil, -1); - return; - } - int delay = [self sendDelay]; - if (delay != 0) { - callback(nil, delay); - return; - } - [self reportWillBeSent]; - callback(BreakpadGetNextReportConfiguration(breakpadRef_), 0); - }); -} - -#pragma mark - - -- (int)sendDelay { - if (!breakpadRef_ || uploadIntervalInSeconds_ <= 0 || !enableUploads_) - return -1; - - // To prevent overloading the crash server, crashes are not sent than one - // report every |uploadIntervalInSeconds_|. A value in the user defaults is - // used to keep the time of the last upload. - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - NSNumber *lastTimeNum = [userDefaults objectForKey:kLastSubmission]; - NSTimeInterval lastTime = lastTimeNum ? [lastTimeNum floatValue] : 0; - NSTimeInterval spanSeconds = CFAbsoluteTimeGetCurrent() - lastTime; - - if (spanSeconds >= uploadIntervalInSeconds_) - return 0; - return uploadIntervalInSeconds_ - static_cast<int>(spanSeconds); -} - -- (void)reportWillBeSent { - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:[NSNumber numberWithDouble:CFAbsoluteTimeGetCurrent()] - forKey:kLastSubmission]; - [userDefaults synchronize]; -} - -- (void)sendStoredCrashReports { - dispatch_async(queue_, ^{ - if (BreakpadGetCrashReportCount(breakpadRef_) == 0) - return; - - int timeToWait = [self sendDelay]; - - // Unable to ever send report. - if (timeToWait == -1) - return; - - // A report can be sent now. - if (timeToWait == 0) { - [self reportWillBeSent]; - BreakpadUploadNextReportWithParameters(breakpadRef_, - uploadTimeParameters_); - - // If more reports must be sent, make sure this method is called again. - if (BreakpadGetCrashReportCount(breakpadRef_) > 0) - timeToWait = uploadIntervalInSeconds_; - } - - // A report must be sent later. - if (timeToWait > 0) { - // performSelector: doesn't work on queue_ - dispatch_async(dispatch_get_main_queue(), ^{ - [self performSelector:@selector(sendStoredCrashReports) - withObject:nil - afterDelay:timeToWait]; - }); - } - }); -} - -@end |