// Copyright 2011 Google LLC
//
// 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 LLC 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.

#define IGNORE_DEBUGGER "BREAKPAD_IGNORE_DEBUGGER"

#import "client/ios/Breakpad.h"

#include <assert.h>
#import <Foundation/Foundation.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <TargetConditionals.h>

#include <string>

#import "client/ios/handler/ios_exception_minidump_generator.h"
#import "client/mac/crash_generation/ConfigFile.h"
#import "client/mac/handler/minidump_generator.h"
#import "client/mac/handler/protected_memory_allocator.h"
#import "client/mac/sender/uploader.h"
#import "common/long_string_dictionary.h"

#if !TARGET_OS_TV && !TARGET_OS_WATCH
#import "client/mac/handler/exception_handler.h"
#else
#import "client/ios/exception_handler_no_mach.h"
#endif  // !TARGET_OS_TV && !TARGET_OS_WATCH

#if !defined(__EXCEPTIONS) || (__clang__ && !__has_feature(cxx_exceptions))
// This file uses C++ try/catch (but shouldn't). Duplicate the macros from
// <c++/4.2.1/exception_defines.h> allowing this file to work properly with
// exceptions disabled even when other C++ libraries are used. #undef the try
// and catch macros first in case libstdc++ is in use and has already provided
// its own definitions.
#undef try
#define try       if (true)
#undef catch
#define catch(X)  if (false)
#endif  // __EXCEPTIONS

using google_breakpad::ConfigFile;
using google_breakpad::EnsureDirectoryPathExists;
using google_breakpad::LongStringDictionary;

//=============================================================================
// We want any memory allocations which are used by breakpad during the
// exception handling process (after a crash has happened) to be read-only
// to prevent them from being smashed before a crash occurs.  Unfortunately
// we cannot protect against smashes to our exception handling thread's
// stack.
//
// NOTE: Any memory allocations which are not used during the exception
// handling process may be allocated in the normal ways.
//
// The ProtectedMemoryAllocator class provides an Allocate() method which
// we'll using in conjunction with placement operator new() to control
// allocation of C++ objects.  Note that we don't use operator delete()
// but instead call the objects destructor directly:  object->~ClassName();
//
ProtectedMemoryAllocator* gMasterAllocator = NULL;
ProtectedMemoryAllocator* gKeyValueAllocator = NULL;
ProtectedMemoryAllocator* gBreakpadAllocator = NULL;

// Mutex for thread-safe access to the key/value dictionary used by breakpad.
// It's a global instead of an instance variable of Breakpad
// since it can't live in a protected memory area.
pthread_mutex_t gDictionaryMutex;

//=============================================================================
// Stack-based object for thread-safe access to a memory-protected region.
// It's assumed that normally the memory block (allocated by the allocator)
// is protected (read-only).  Creating a stack-based instance of
// ProtectedMemoryLocker will unprotect this block after taking the lock.
// Its destructor will first re-protect the memory then release the lock.
class ProtectedMemoryLocker {
 public:
  ProtectedMemoryLocker(pthread_mutex_t* mutex,
                        ProtectedMemoryAllocator* allocator)
      : mutex_(mutex),
        allocator_(allocator) {
    // Lock the mutex
    __attribute__((unused)) int rv = pthread_mutex_lock(mutex_);
    assert(rv == 0);

    // Unprotect the memory
    allocator_->Unprotect();
  }

  ~ProtectedMemoryLocker() {
    // First protect the memory
    allocator_->Protect();

    // Then unlock the mutex
    __attribute__((unused)) int rv = pthread_mutex_unlock(mutex_);
    assert(rv == 0);
  }

 private:
  ProtectedMemoryLocker();
  ProtectedMemoryLocker(const ProtectedMemoryLocker&);
  ProtectedMemoryLocker& operator=(const ProtectedMemoryLocker&);

  pthread_mutex_t* mutex_;
  ProtectedMemoryAllocator* allocator_;
};

//=============================================================================
class Breakpad {
 public:
  // factory method
  static Breakpad* Create(NSDictionary* parameters) {
    // Allocate from our special allocation pool
    Breakpad* breakpad =
      new (gBreakpadAllocator->Allocate(sizeof(Breakpad)))
        Breakpad();

    if (!breakpad)
      return NULL;

    if (!breakpad->Initialize(parameters)) {
      // Don't use operator delete() here since we allocated from special pool
      breakpad->~Breakpad();
      return NULL;
    }

    return breakpad;
  }

  ~Breakpad();

  void SetKeyValue(NSString* key, NSString* value);
  NSString* KeyValue(NSString* key);
  void RemoveKeyValue(NSString* key);
  NSArray* CrashReportsToUpload();
  NSString* NextCrashReportToUpload();
  NSDictionary* NextCrashReportConfiguration();
  NSDictionary* FixedUpCrashReportConfiguration(NSDictionary* configuration);
  NSDate* DateOfMostRecentCrashReport();
  void UploadNextReport(NSDictionary* server_parameters);
  void UploadReportWithConfiguration(NSDictionary* configuration,
                                     NSDictionary* server_parameters,
                                     BreakpadUploadCompletionCallback callback);
  void UploadData(NSData* data, NSString* name,
                  NSDictionary* server_parameters);
  void HandleNetworkResponse(NSDictionary* configuration,
                             NSData* data,
                             NSError* error);
  NSDictionary* GenerateReport(NSDictionary* server_parameters);

 private:
  Breakpad()
    : handler_(NULL),
      config_params_(NULL) {}

  bool Initialize(NSDictionary* parameters);

  bool ExtractParameters(NSDictionary* parameters);

  // Dispatches to HandleMinidump()
  static bool HandleMinidumpCallback(const char* dump_dir,
                                     const char* minidump_id,
                                     void* context, bool succeeded);

  bool HandleMinidump(const char* dump_dir,
                      const char* minidump_id);

  // NSException handler
  static void UncaughtExceptionHandler(NSException* exception);

  // Handle an uncaught NSException.
  void HandleUncaughtException(NSException* exception);

  // Since ExceptionHandler (w/o namespace) is defined as typedef in OSX's
  // MachineExceptions.h, we have to explicitly name the handler.
  google_breakpad::ExceptionHandler* handler_; // The actual handler (STRONG)

  LongStringDictionary* config_params_; // Create parameters (STRONG)

  ConfigFile config_file_;

  // A static reference to the current Breakpad instance. Used for handling
  // NSException.
  static Breakpad* current_breakpad_;
};

Breakpad* Breakpad::current_breakpad_ = NULL;

#pragma mark -
#pragma mark Helper functions

//=============================================================================
// Helper functions

//=============================================================================
static BOOL IsDebuggerActive() {
  BOOL result = NO;
  NSUserDefaults* stdDefaults = [NSUserDefaults standardUserDefaults];

  // We check both defaults and the environment variable here

  BOOL ignoreDebugger = [stdDefaults boolForKey:@IGNORE_DEBUGGER];

  if (!ignoreDebugger) {
    char* ignoreDebuggerStr = getenv(IGNORE_DEBUGGER);
    ignoreDebugger =
        (ignoreDebuggerStr ? strtol(ignoreDebuggerStr, NULL, 10) : 0) != 0;
  }

  if (!ignoreDebugger) {
    pid_t pid = getpid();
    int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
    int mibSize = sizeof(mib) / sizeof(int);
    size_t actualSize;

    if (sysctl(mib, mibSize, NULL, &actualSize, NULL, 0) == 0) {
      struct kinfo_proc* info = (struct kinfo_proc*)malloc(actualSize);

      if (info) {
        // This comes from looking at the Darwin xnu Kernel
        if (sysctl(mib, mibSize, info, &actualSize, NULL, 0) == 0)
          result = (info->kp_proc.p_flag & P_TRACED) ? YES : NO;

        free(info);
      }
    }
  }

  return result;
}

//=============================================================================
bool Breakpad::HandleMinidumpCallback(const char* dump_dir,
                                      const char* minidump_id,
                                      void* context, bool succeeded) {
  Breakpad* breakpad = (Breakpad*)context;

  // If our context is damaged or something, just return false to indicate that
  // the handler should continue without us.
  if (!breakpad || !succeeded)
    return false;

  return breakpad->HandleMinidump(dump_dir, minidump_id);
}

//=============================================================================
void Breakpad::UncaughtExceptionHandler(NSException* exception) {
  NSSetUncaughtExceptionHandler(NULL);
  if (current_breakpad_) {
    current_breakpad_->HandleUncaughtException(exception);
    BreakpadRelease(current_breakpad_);
  }
}

//=============================================================================
#pragma mark -

//=============================================================================
bool Breakpad::Initialize(NSDictionary* parameters) {
  // Initialize
  current_breakpad_ = this;
  config_params_ = NULL;
  handler_ = NULL;

  // Gather any user specified parameters
  if (!ExtractParameters(parameters)) {
    return false;
  }

  // Check for debugger
  if (IsDebuggerActive()) {
    return true;
  }

  // Create the handler (allocating it in our special protected pool)
  handler_ =
      new (gBreakpadAllocator->Allocate(
          sizeof(google_breakpad::ExceptionHandler)))
          google_breakpad::ExceptionHandler(
              config_params_->GetValueForKey(BREAKPAD_DUMP_DIRECTORY),
              0, &HandleMinidumpCallback, this, true, 0);
  NSSetUncaughtExceptionHandler(&Breakpad::UncaughtExceptionHandler);
  return true;
}

//=============================================================================
Breakpad::~Breakpad() {
  NSSetUncaughtExceptionHandler(NULL);
  current_breakpad_ = NULL;
  // Note that we don't use operator delete() on these pointers,
  // since they were allocated by ProtectedMemoryAllocator objects.
  //
  if (config_params_) {
    config_params_->~LongStringDictionary();
  }

  if (handler_)
    handler_->~ExceptionHandler();
}

//=============================================================================
bool Breakpad::ExtractParameters(NSDictionary* parameters) {
  NSString* serverType = [parameters objectForKey:@BREAKPAD_SERVER_TYPE];
  NSString* display = [parameters objectForKey:@BREAKPAD_PRODUCT_DISPLAY];
  NSString* product = [parameters objectForKey:@BREAKPAD_PRODUCT];
  NSString* version = [parameters objectForKey:@BREAKPAD_VERSION];
  NSString* urlStr = [parameters objectForKey:@BREAKPAD_URL];
  NSString* vendor =
      [parameters objectForKey:@BREAKPAD_VENDOR];
  // We check both parameters and the environment variable here.
  char* envVarDumpSubdirectory = getenv(BREAKPAD_DUMP_DIRECTORY);
  NSString* dumpSubdirectory = envVarDumpSubdirectory ?
      [NSString stringWithUTF8String:envVarDumpSubdirectory] :
          [parameters objectForKey:@BREAKPAD_DUMP_DIRECTORY];

  NSDictionary* serverParameters =
      [parameters objectForKey:@BREAKPAD_SERVER_PARAMETER_DICT];

  if (!product)
    product = [parameters objectForKey:@"CFBundleName"];

  if (!display) {
    display = [parameters objectForKey:@"CFBundleDisplayName"];
    if (!display) {
      display = product;
    }
  }

  if (!version.length)  // Default nil or empty string to CFBundleVersion
    version = [parameters objectForKey:@"CFBundleVersion"];

  if (!vendor) {
    vendor = @"Vendor not specified";
  }

  if (!dumpSubdirectory) {
    NSString* cachePath =
        [NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
                                             NSUserDomainMask,
                                             YES)
            objectAtIndex:0];
    dumpSubdirectory =
        [cachePath stringByAppendingPathComponent:@kDefaultLibrarySubdirectory];

    EnsureDirectoryPathExists(dumpSubdirectory);
  }

  // The product, version, and URL are required values.
  if (![product length]) {
    return false;
  }

  if (![version length]) {
    return false;
  }

  if (![urlStr length]) {
    return false;
  }

  config_params_ =
      new (gKeyValueAllocator->Allocate(sizeof(LongStringDictionary)))
          LongStringDictionary();

  LongStringDictionary& dictionary = *config_params_;

  dictionary.SetKeyValue(BREAKPAD_SERVER_TYPE,     [serverType UTF8String]);
  dictionary.SetKeyValue(BREAKPAD_PRODUCT_DISPLAY, [display UTF8String]);
  dictionary.SetKeyValue(BREAKPAD_PRODUCT,         [product UTF8String]);
  dictionary.SetKeyValue(BREAKPAD_VERSION,         [version UTF8String]);
  dictionary.SetKeyValue(BREAKPAD_URL,             [urlStr UTF8String]);
  dictionary.SetKeyValue(BREAKPAD_VENDOR,          [vendor UTF8String]);
  dictionary.SetKeyValue(BREAKPAD_DUMP_DIRECTORY,
                         [dumpSubdirectory UTF8String]);

  struct timeval tv;
  gettimeofday(&tv, NULL);
  char timeStartedString[32];
  sprintf(timeStartedString, "%zd", tv.tv_sec);
  dictionary.SetKeyValue(BREAKPAD_PROCESS_START_TIME, timeStartedString);

  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;
}

//=============================================================================
void Breakpad::SetKeyValue(NSString* key, NSString* value) {
  // We allow nil values. This is the same as removing the keyvalue.
  if (!config_params_ || !key)
    return;

  config_params_->SetKeyValue([key UTF8String], [value UTF8String]);
}

//=============================================================================
NSString* Breakpad::KeyValue(NSString* key) {
  if (!config_params_ || !key)
    return nil;

  const std::string value = config_params_->GetValueForKey([key UTF8String]);
  return value.empty() ? nil : [NSString stringWithUTF8String:value.c_str()];
}

//=============================================================================
void Breakpad::RemoveKeyValue(NSString* key) {
  if (!config_params_ || !key) return;

  config_params_->RemoveKey([key UTF8String]);
}

//=============================================================================
NSArray* Breakpad::CrashReportsToUpload() {
  NSString* directory = KeyValue(@BREAKPAD_DUMP_DIRECTORY);
  if (!directory)
    return nil;
  NSArray* dirContents = [[NSFileManager defaultManager]
      contentsOfDirectoryAtPath:directory error:nil];
  NSArray* configs = [dirContents filteredArrayUsingPredicate:[NSPredicate
      predicateWithFormat:@"self BEGINSWITH 'Config-'"]];
  return configs;
}

//=============================================================================
NSString* Breakpad::NextCrashReportToUpload() {
  NSString* directory = KeyValue(@BREAKPAD_DUMP_DIRECTORY);
  if (!directory)
    return nil;
  NSString* config = [CrashReportsToUpload() lastObject];
  if (!config)
    return nil;
  return [NSString stringWithFormat:@"%@/%@", directory, config];
}

//=============================================================================
NSDictionary* Breakpad::NextCrashReportConfiguration() {
  NSDictionary* configuration = [Uploader readConfigurationDataFromFile:NextCrashReportToUpload()];
  return FixedUpCrashReportConfiguration(configuration);
}

//=============================================================================
NSDictionary* Breakpad::FixedUpCrashReportConfiguration(NSDictionary* configuration) {
  NSMutableDictionary* fixedConfiguration = [[configuration mutableCopy] autorelease];
  // kReporterMinidumpDirectoryKey can become stale because the app's data container path includes
  // an UUID that is not guaranteed to stay the same over time.
  [fixedConfiguration setObject:KeyValue(@BREAKPAD_DUMP_DIRECTORY)
                    forKey:@kReporterMinidumpDirectoryKey];
  return fixedConfiguration;
}

//=============================================================================
NSDate* Breakpad::DateOfMostRecentCrashReport() {
  NSString* directory = KeyValue(@BREAKPAD_DUMP_DIRECTORY);
  if (!directory) {
    return nil;
  }
  NSFileManager* fileManager = [NSFileManager defaultManager];
  NSArray* dirContents = [fileManager contentsOfDirectoryAtPath:directory error:nil];
  NSArray* dumps = [dirContents filteredArrayUsingPredicate:[NSPredicate
      predicateWithFormat:@"self ENDSWITH '.dmp'"]];
  NSDate* mostRecentCrashReportDate = nil;
  for (NSString* dump in dumps) {
    NSString* filePath = [directory stringByAppendingPathComponent:dump];
    NSDate* crashReportDate =
        [[fileManager attributesOfItemAtPath:filePath error:nil] fileCreationDate];
    if (!mostRecentCrashReportDate) {
      mostRecentCrashReportDate = crashReportDate;
    } else if (crashReportDate) {
      mostRecentCrashReportDate = [mostRecentCrashReportDate laterDate:crashReportDate];
    }
  }
  return mostRecentCrashReportDate;
}

//=============================================================================
void Breakpad::HandleNetworkResponse(NSDictionary* configuration,
                                     NSData* data,
                                     NSError* error) {
  Uploader* uploader = [[[Uploader alloc]
      initWithConfig:configuration] autorelease];
  [uploader handleNetworkResponse:data withError:error];
}

//=============================================================================
void Breakpad::UploadReportWithConfiguration(
    NSDictionary* configuration,
    NSDictionary* server_parameters,
    BreakpadUploadCompletionCallback callback) {
  Uploader* uploader = [[[Uploader alloc]
      initWithConfig:configuration] autorelease];
  if (!uploader)
    return;
  for (NSString* key in server_parameters) {
    [uploader addServerParameter:[server_parameters objectForKey:key]
                          forKey:key];
  }
  if (callback) {
    [uploader setUploadCompletionBlock:^(NSString* report_id, NSError* error) {
      dispatch_async(dispatch_get_main_queue(), ^{
        callback(report_id, error);
      });
    }];
  }
  [uploader report];
}

//=============================================================================
void Breakpad::UploadNextReport(NSDictionary* server_parameters) {
  NSDictionary* configuration = NextCrashReportConfiguration();
  if (configuration) {
    return UploadReportWithConfiguration(configuration, server_parameters,
                                         nullptr);
  }
}

//=============================================================================
void Breakpad::UploadData(NSData* data, NSString* name,
                          NSDictionary* server_parameters) {
  NSMutableDictionary* config = [NSMutableDictionary dictionary];

  LongStringDictionary::Iterator it(*config_params_);
  while (const LongStringDictionary::Entry* next = it.Next()) {
    [config setValue:[NSString stringWithUTF8String:next->value]
              forKey:[NSString stringWithUTF8String:next->key]];
  }

  Uploader* uploader =
      [[[Uploader alloc] initWithConfig:config] autorelease];
  for (NSString* key in server_parameters) {
    [uploader addServerParameter:[server_parameters objectForKey:key]
                          forKey:key];
  }
  [uploader uploadData:data name:name];
}

//=============================================================================
NSDictionary* Breakpad::GenerateReport(NSDictionary* server_parameters) {
  NSString* dumpDirAsNSString = KeyValue(@BREAKPAD_DUMP_DIRECTORY);
  if (!dumpDirAsNSString)
    return nil;
  const char* dumpDir = [dumpDirAsNSString UTF8String];

  google_breakpad::MinidumpGenerator generator(mach_task_self(),
                                               MACH_PORT_NULL);
  std::string dumpId;
  std::string dumpFilename = generator.UniqueNameInDirectory(dumpDir, &dumpId);
  bool success = generator.Write(dumpFilename.c_str());
  if (!success)
    return nil;

  LongStringDictionary params = *config_params_;
  for (NSString* key in server_parameters) {
    params.SetKeyValue([key UTF8String],
                       [[server_parameters objectForKey:key] UTF8String]);
  }
  ConfigFile config_file;
  config_file.WriteFile(dumpDir, &params, dumpDir, dumpId.c_str());

  // Handle results.
  NSMutableDictionary* result = [NSMutableDictionary dictionary];
  NSString* dumpFullPath = [NSString stringWithUTF8String:dumpFilename.c_str()];
  [result setValue:dumpFullPath
            forKey:@BREAKPAD_OUTPUT_DUMP_FILE];
  [result setValue:[NSString stringWithUTF8String:config_file.GetFilePath()]
            forKey:@BREAKPAD_OUTPUT_CONFIG_FILE];
  return result;
}

//=============================================================================
bool Breakpad::HandleMinidump(const char* dump_dir,
                              const char* minidump_id) {
  config_file_.WriteFile(dump_dir,
                         config_params_,
                         dump_dir,
                         minidump_id);

  // Return true here to indicate that we've processed things as much as we
  // want.
  return true;
}

//=============================================================================
void Breakpad::HandleUncaughtException(NSException* exception) {
  // Generate the minidump.
  google_breakpad::IosExceptionMinidumpGenerator generator(exception);
  const std::string minidump_path =
      config_params_->GetValueForKey(BREAKPAD_DUMP_DIRECTORY);
  std::string minidump_id;
  std::string minidump_filename = generator.UniqueNameInDirectory(minidump_path,
                                                                  &minidump_id);
  generator.Write(minidump_filename.c_str());

  // Copy the config params and our custom parameter. This is necessary for 2
  // reasons:
  // 1- config_params_ is protected.
  // 2- If the application crash while trying to handle this exception, a usual
  //    report will be generated. This report must not contain these special
  //    keys.
  LongStringDictionary params = *config_params_;
  params.SetKeyValue(BREAKPAD_SERVER_PARAMETER_PREFIX "type", "exception");
  params.SetKeyValue(BREAKPAD_SERVER_PARAMETER_PREFIX "exceptionName",
                     [[exception name] UTF8String]);
  params.SetKeyValue(BREAKPAD_SERVER_PARAMETER_PREFIX "exceptionReason",
                     [[exception reason] UTF8String]);

  // And finally write the config file.
  ConfigFile config_file;
  config_file.WriteFile(minidump_path.c_str(),
                        &params,
                        minidump_path.c_str(),
                        minidump_id.c_str());
}

//=============================================================================

#pragma mark -
#pragma mark Public API

//=============================================================================
BreakpadRef BreakpadCreate(NSDictionary* parameters) {
  try {
    // This is confusing.  Our two main allocators for breakpad memory are:
    //    - gKeyValueAllocator for the key/value memory
    //    - gBreakpadAllocator for the Breakpad, ExceptionHandler, and other
    //      breakpad allocations which are accessed at exception handling time.
    //
    // But in order to avoid these two allocators themselves from being smashed,
    // we'll protect them as well by allocating them with gMasterAllocator.
    //
    // gMasterAllocator itself will NOT be protected, but this doesn't matter,
    // since once it does its allocations and locks the memory, smashes to
    // itself don't affect anything we care about.
    gMasterAllocator =
        new ProtectedMemoryAllocator(sizeof(ProtectedMemoryAllocator) * 2);

    gKeyValueAllocator =
        new (gMasterAllocator->Allocate(sizeof(ProtectedMemoryAllocator)))
            ProtectedMemoryAllocator(sizeof(LongStringDictionary));

    // Create a mutex for use in accessing the LongStringDictionary
    int mutexResult = pthread_mutex_init(&gDictionaryMutex, NULL);
    if (mutexResult == 0) {

      // With the current compiler, gBreakpadAllocator is allocating 1444 bytes.
      // Let's round up to the nearest page size.
      //
      int breakpad_pool_size = 4096;

      /*
       sizeof(Breakpad)
       + sizeof(google_breakpad::ExceptionHandler)
       + sizeof( STUFF ALLOCATED INSIDE ExceptionHandler )
       */

      gBreakpadAllocator =
          new (gMasterAllocator->Allocate(sizeof(ProtectedMemoryAllocator)))
              ProtectedMemoryAllocator(breakpad_pool_size);

      // Stack-based autorelease pool for Breakpad::Create() obj-c code.
      NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
      Breakpad* breakpad = Breakpad::Create(parameters);

      if (breakpad) {
        // Make read-only to protect against memory smashers
        gMasterAllocator->Protect();
        gKeyValueAllocator->Protect();
        gBreakpadAllocator->Protect();
        // Can uncomment this line to figure out how much space was actually
        // allocated using this allocator
        //     printf("gBreakpadAllocator allocated size = %d\n",
        //         gBreakpadAllocator->GetAllocatedSize() );
        [pool release];
        return (BreakpadRef)breakpad;
      }

      [pool release];
    }
  } catch(...) {    // don't let exceptions leave this C API
    fprintf(stderr, "BreakpadCreate() : error\n");
  }

  if (gKeyValueAllocator) {
    gKeyValueAllocator->~ProtectedMemoryAllocator();
    gKeyValueAllocator = NULL;
  }

  if (gBreakpadAllocator) {
    gBreakpadAllocator->~ProtectedMemoryAllocator();
    gBreakpadAllocator = NULL;
  }

  delete gMasterAllocator;
  gMasterAllocator = NULL;

  return NULL;
}

//=============================================================================
void BreakpadRelease(BreakpadRef ref) {
  try {
    Breakpad* breakpad = (Breakpad*)ref;

    if (gMasterAllocator) {
      gMasterAllocator->Unprotect();
      gKeyValueAllocator->Unprotect();
      gBreakpadAllocator->Unprotect();

      breakpad->~Breakpad();

      // Unfortunately, it's not possible to deallocate this stuff
      // because the exception handling thread is still finishing up
      // asynchronously at this point...  OK, it could be done with
      // locks, etc.  But since BreakpadRelease() should usually only
      // be called right before the process exits, it's not worth
      // deallocating this stuff.
#if 0
      gKeyValueAllocator->~ProtectedMemoryAllocator();
      gBreakpadAllocator->~ProtectedMemoryAllocator();
      delete gMasterAllocator;

      gMasterAllocator = NULL;
      gKeyValueAllocator = NULL;
      gBreakpadAllocator = NULL;
#endif

      pthread_mutex_destroy(&gDictionaryMutex);
    }
  } catch(...) {    // don't let exceptions leave this C API
    fprintf(stderr, "BreakpadRelease() : error\n");
  }
}

//=============================================================================
void BreakpadSetKeyValue(BreakpadRef ref, NSString* key, NSString* value) {
  try {
    // Not called at exception time
    Breakpad* breakpad = (Breakpad*)ref;

    if (breakpad && key && gKeyValueAllocator) {
      ProtectedMemoryLocker locker(&gDictionaryMutex, gKeyValueAllocator);

      breakpad->SetKeyValue(key, value);
    }
  } 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;

  try {
    // Not called at exception time
    Breakpad* breakpad = (Breakpad*)ref;

    if (!breakpad || !key || !gKeyValueAllocator)
      return nil;

    ProtectedMemoryLocker locker(&gDictionaryMutex, gKeyValueAllocator);

    value = breakpad->KeyValue(key);
  } catch(...) {    // don't let exceptions leave this C API
    fprintf(stderr, "BreakpadKeyValue() : error\n");
  }

  return value;
}

//=============================================================================
void BreakpadRemoveKeyValue(BreakpadRef ref, NSString* key) {
  try {
    // Not called at exception time
    Breakpad* breakpad = (Breakpad*)ref;

    if (breakpad && key && gKeyValueAllocator) {
      ProtectedMemoryLocker locker(&gDictionaryMutex, gKeyValueAllocator);

      breakpad->RemoveKeyValue(key);
    }
  } catch(...) {    // don't let exceptions leave this C API
    fprintf(stderr, "BreakpadRemoveKeyValue() : error\n");
  }
}

//=============================================================================
int BreakpadGetCrashReportCount(BreakpadRef ref) {
  try {
    // Not called at exception time
    Breakpad* breakpad = (Breakpad*)ref;

    if (breakpad) {
       return static_cast<int>([breakpad->CrashReportsToUpload() count]);
    }
  } catch(...) {    // don't let exceptions leave this C API
    fprintf(stderr, "BreakpadGetCrashReportCount() : error\n");
  }
  return false;
}

//=============================================================================
void BreakpadUploadNextReport(BreakpadRef ref) {
  BreakpadUploadNextReportWithParameters(ref, nil, nullptr);
}

//=============================================================================
NSDictionary* BreakpadGetNextReportConfiguration(BreakpadRef ref) {
  try {
    Breakpad* breakpad = (Breakpad*)ref;
    if (breakpad)
      return breakpad->NextCrashReportConfiguration();
  } catch(...) {    // don't let exceptions leave this C API
    fprintf(stderr, "BreakpadGetNextReportConfiguration() : error\n");
  }
  return nil;
}

//=============================================================================
NSDate* BreakpadGetDateOfMostRecentCrashReport(BreakpadRef ref) {
  try {
    Breakpad* breakpad = (Breakpad*)ref;
    if (breakpad) {
      return breakpad->DateOfMostRecentCrashReport();
    }
  } catch (...) {    // don't let exceptions leave this C API
    fprintf(stderr, "BreakpadGetDateOfMostRecentCrashReport() : error\n");
  }
  return nil;
}

//=============================================================================
void BreakpadUploadReportWithParametersAndConfiguration(
    BreakpadRef ref,
    NSDictionary* server_parameters,
    NSDictionary* configuration,
    BreakpadUploadCompletionCallback callback) {
  try {
    Breakpad* breakpad = (Breakpad*)ref;
    if (!breakpad || !configuration)
      return;
    breakpad->UploadReportWithConfiguration(configuration, server_parameters,
                                            callback);
  } catch(...) {    // don't let exceptions leave this C API
    fprintf(stderr,
        "BreakpadUploadReportWithParametersAndConfiguration() : error\n");
  }
}

//=============================================================================
void BreakpadUploadNextReportWithParameters(
    BreakpadRef ref,
    NSDictionary* server_parameters,
    BreakpadUploadCompletionCallback callback) {
  try {
    Breakpad* breakpad = (Breakpad*)ref;
    if (!breakpad)
      return;
    NSDictionary* configuration = breakpad->NextCrashReportConfiguration();
    if (!configuration)
      return;
    return BreakpadUploadReportWithParametersAndConfiguration(
        ref, server_parameters, configuration, callback);
  } catch(...) {    // don't let exceptions leave this C API
    fprintf(stderr, "BreakpadUploadNextReportWithParameters() : error\n");
  }
}

void BreakpadHandleNetworkResponse(BreakpadRef ref,
                                   NSDictionary* configuration,
                                   NSData* data,
                                   NSError* error) {
  try {
    // Not called at exception time
    Breakpad* breakpad = (Breakpad*)ref;
    if (breakpad && configuration)
      breakpad->HandleNetworkResponse(configuration,data, error);

  } catch(...) {    // don't let exceptions leave this C API
    fprintf(stderr, "BreakpadHandleNetworkResponse() : error\n");
  }
}

//=============================================================================
void BreakpadUploadData(BreakpadRef ref, NSData* data, NSString* name,
                        NSDictionary* server_parameters) {
  try {
    // Not called at exception time
    Breakpad* breakpad = (Breakpad*)ref;

    if (breakpad) {
      breakpad->UploadData(data, name, server_parameters);
    }
  } catch(...) {    // don't let exceptions leave this C API
    fprintf(stderr, "BreakpadUploadData() : error\n");
  }
}

//=============================================================================
NSDictionary* BreakpadGenerateReport(BreakpadRef ref,
                                     NSDictionary* server_parameters) {
  try {
    // Not called at exception time
    Breakpad* breakpad = (Breakpad*)ref;

    if (breakpad) {
      return breakpad->GenerateReport(server_parameters);
    } else {
      return nil;
    }
  } catch(...) {    // don't let exceptions leave this C API
    fprintf(stderr, "BreakpadGenerateReport() : error\n");
    return nil;
  }
}
