// 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.
//


#define IGNORE_DEBUGGER "BREAKPAD_IGNORE_DEBUGGER"

#import "client/mac/Framework/Breakpad.h"

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

#import "client/mac/crash_generation/Inspector.h"
#import "client/mac/handler/exception_handler.h"
#import "client/mac/Framework/Breakpad.h"
#import "client/mac/Framework/OnDemandServer.h"
#import "client/mac/handler/protected_memory_allocator.h"
#include "common/mac/launch_reporter.h"
#import "common/mac/MachIPC.h"
#import "common/simple_string_dictionary.h"

#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::MachPortSender;
using google_breakpad::MachReceiveMessage;
using google_breakpad::MachSendMessage;
using google_breakpad::ReceivePort;
using google_breakpad::SimpleStringDictionary;

//=============================================================================
// 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);

  void GenerateAndSendReport();

  void SetFilterCallback(BreakpadFilterCallback callback, void* context) {
    filter_callback_ = callback;
    filter_callback_context_ = context;
  }

 private:
  Breakpad()
    : handler_(NULL),
      config_params_(NULL),
      send_and_exit_(true),
      filter_callback_(NULL),
      filter_callback_context_(NULL) {
    inspector_path_[0] = 0;
  }

  bool Initialize(NSDictionary* parameters);
  bool InitializeInProcess(NSDictionary* parameters);
  bool InitializeOutOfProcess(NSDictionary* parameters);

  bool ExtractParameters(NSDictionary* parameters);

  // Dispatches to HandleException()
  static bool ExceptionHandlerDirectCallback(void* context,
                                             int exception_type,
                                             int exception_code,
                                             int exception_subcode,
                                             mach_port_t crashing_thread);

  bool HandleException(int exception_type,
                       int exception_code,
                       int exception_subcode,
                       mach_port_t crashing_thread);

  // Dispatches to HandleMinidump().
  // This gets called instead of ExceptionHandlerDirectCallback when running
  // with the BREAKPAD_IN_PROCESS option.
  static bool HandleMinidumpCallback(const char* dump_dir,
                                     const char* minidump_id,
                                     void* context,
                                     bool succeeded);

  // This is only used when BREAKPAD_IN_PROCESS is YES.
  bool HandleMinidump(const char* dump_dir, const char* minidump_id);

  // 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)

  char                    inspector_path_[PATH_MAX];  // Path to inspector tool

  SimpleStringDictionary* config_params_; // Create parameters (STRONG)

  OnDemandServer          inspector_;

  bool                    send_and_exit_;  // Exit after sending, if true

  BreakpadFilterCallback  filter_callback_;
  void*                   filter_callback_context_;
};

#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::ExceptionHandlerDirectCallback(void* context,
                                              int exception_type,
                                              int exception_code,
                                              int exception_subcode,
                                              mach_port_t crashing_thread) {
  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)
    return false;

  return breakpad->HandleException( exception_type,
                                    exception_code,
                                    exception_subcode,
                                    crashing_thread);
}

//=============================================================================
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);
}

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

#include <dlfcn.h>

//=============================================================================
// Returns the pathname to the Resources directory for this version of
// Breakpad which we are now running.
//
// Don't make the function static, since _dyld_lookup_and_bind_fully needs a
// simple non-static C name
//
extern "C" {
NSString* GetResourcePath();
NSString* GetResourcePath() {
  NSString* resourcePath = nil;

  // If there are multiple breakpads installed then calling bundleWithIdentifier
  // will not work properly, so only use that as a backup plan.
  // We want to find the bundle containing the code where this function lives
  // and work from there
  //

  // Get the pathname to the code which contains this function
  Dl_info info;
  if (dladdr((const void*)GetResourcePath, &info) != 0) {
    NSFileManager* filemgr = [NSFileManager defaultManager];
    NSString* filePath =
        [filemgr stringWithFileSystemRepresentation:info.dli_fname
                                             length:strlen(info.dli_fname)];
    NSString* bundlePath = [filePath stringByDeletingLastPathComponent];
    // The "Resources" directory should be in the same directory as the
    // executable code, since that's how the Breakpad framework is built.
    resourcePath = [bundlePath stringByAppendingPathComponent:@"Resources/"];
  } else {
    // fallback plan
    NSBundle* bundle =
        [NSBundle bundleWithIdentifier:@"com.Google.BreakpadFramework"];
    resourcePath = [bundle resourcePath];
  }

  return resourcePath;
}
}  // extern "C"

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

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

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

  if ([[parameters objectForKey:@BREAKPAD_IN_PROCESS] boolValue])
    return InitializeInProcess(parameters);
  else
    return InitializeOutOfProcess(parameters);
}

//=============================================================================
bool Breakpad::InitializeInProcess(NSDictionary* parameters) {
  handler_ =
      new (gBreakpadAllocator->Allocate(
          sizeof(google_breakpad::ExceptionHandler)))
          google_breakpad::ExceptionHandler(
              config_params_->GetValueForKey(BREAKPAD_DUMP_DIRECTORY),
              0, &HandleMinidumpCallback, this, true, 0);
  return true;    
}

//=============================================================================
bool Breakpad::InitializeOutOfProcess(NSDictionary* parameters) {
  // Get path to Inspector executable.
  NSString* inspectorPathString = KeyValue(@BREAKPAD_INSPECTOR_LOCATION);

  // Standardize path (resolve symlinkes, etc.)  and escape spaces
  inspectorPathString = [inspectorPathString stringByStandardizingPath];
  inspectorPathString = [[inspectorPathString componentsSeparatedByString:@" "]
                                              componentsJoinedByString:@"\\ "];

  // Create an on-demand server object representing the Inspector.
  // In case of a crash, we simply need to call the LaunchOnDemand()
  // method on it, then send a mach message to its service port.
  // It will then launch and perform a process inspection of our crashed state.
  // See the HandleException() method for the details.
#define RECEIVE_PORT_NAME "com.Breakpad.Inspector"

  name_t portName;
  snprintf(portName, sizeof(name_t),  "%s%d", RECEIVE_PORT_NAME, getpid());

  // Save the location of the Inspector
  strlcpy(inspector_path_, [inspectorPathString fileSystemRepresentation],
          sizeof(inspector_path_));

  // Append a single command-line argument to the Inspector path
  // representing the bootstrap name of the launch-on-demand receive port.
  // When the Inspector is launched, it can use this to lookup the port
  // by calling bootstrap_check_in().
  strlcat(inspector_path_, " ", sizeof(inspector_path_));
  strlcat(inspector_path_, portName, sizeof(inspector_path_));

  kern_return_t kr = inspector_.Initialize(inspector_path_,
                                           portName,
                                           true);        // shutdown on exit

  if (kr != KERN_SUCCESS) {
    return false;
  }

  // Create the handler (allocating it in our special protected pool)
  handler_ =
      new (gBreakpadAllocator->Allocate(
          sizeof(google_breakpad::ExceptionHandler)))
          google_breakpad::ExceptionHandler(
              Breakpad::ExceptionHandlerDirectCallback, this, true);
  return true;
}

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

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

//=============================================================================
bool Breakpad::ExtractParameters(NSDictionary* parameters) {
  NSUserDefaults* stdDefaults = [NSUserDefaults standardUserDefaults];
  NSString* skipConfirm = [stdDefaults stringForKey:@BREAKPAD_SKIP_CONFIRM];
  NSString* sendAndExit = [stdDefaults stringForKey:@BREAKPAD_SEND_AND_EXIT];

  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* interval = [parameters objectForKey:@BREAKPAD_REPORT_INTERVAL];
  NSString* inspectorPathString =
      [parameters objectForKey:@BREAKPAD_INSPECTOR_LOCATION];
  NSString* reporterPathString =
      [parameters objectForKey:@BREAKPAD_REPORTER_EXE_LOCATION];
  NSString* timeout = [parameters objectForKey:@BREAKPAD_CONFIRM_TIMEOUT];
  NSArray*  logFilePaths = [parameters objectForKey:@BREAKPAD_LOGFILES];
  NSString* logFileTailSize =
      [parameters objectForKey:@BREAKPAD_LOGFILE_UPLOAD_SIZE];
  NSString* requestUserText =
      [parameters objectForKey:@BREAKPAD_REQUEST_COMMENTS];
  NSString* requestEmail = [parameters objectForKey:@BREAKPAD_REQUEST_EMAIL];
  NSString* vendor =
      [parameters objectForKey:@BREAKPAD_VENDOR];
  NSString* dumpSubdirectory =
      [parameters objectForKey:@BREAKPAD_DUMP_DIRECTORY];

  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];
  }
  if (!sendAndExit) {
    sendAndExit = [parameters objectForKey:@BREAKPAD_SEND_AND_EXIT];
  }

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

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

  if (!version)
    version = [parameters objectForKey:@"CFBundleVersion"];

  if (!interval)
    interval = @"3600";

  if (!timeout)
    timeout = @"300";

  if (!logFileTailSize)
    logFileTailSize = @"200000";

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

  // Normalize the values.
  if (skipConfirm) {
    skipConfirm = [skipConfirm uppercaseString];

    if ([skipConfirm isEqualToString:@"YES"] ||
        [skipConfirm isEqualToString:@"TRUE"] ||
        [skipConfirm isEqualToString:@"1"])
      skipConfirm = @"YES";
    else
      skipConfirm = @"NO";
  } else {
    skipConfirm = @"NO";
  }

  send_and_exit_ = true;
  if (sendAndExit) {
    sendAndExit = [sendAndExit uppercaseString];

    if ([sendAndExit isEqualToString:@"NO"] ||
        [sendAndExit isEqualToString:@"FALSE"] ||
        [sendAndExit isEqualToString:@"0"])
      send_and_exit_ = false;
  }

  if (requestUserText) {
    requestUserText = [requestUserText uppercaseString];

    if ([requestUserText isEqualToString:@"YES"] ||
        [requestUserText isEqualToString:@"TRUE"] ||
        [requestUserText isEqualToString:@"1"])
      requestUserText = @"YES";
    else
      requestUserText = @"NO";
  } else {
    requestUserText = @"NO";
  }

  // Find the helper applications if not specified in user config.
  NSString* resourcePath = nil;
  if (!inspectorPathString || !reporterPathString) {
    resourcePath = GetResourcePath();
    if (!resourcePath) {
      return false;
    }
  }

  // Find Inspector.
  if (!inspectorPathString) {
    inspectorPathString =
        [resourcePath stringByAppendingPathComponent:@"Inspector"];
  }

  // Verify that there is an Inspector tool.
  if (![[NSFileManager defaultManager] fileExistsAtPath:inspectorPathString]) {
    return false;
  }

  // Find Reporter.
  if (!reporterPathString) {
    reporterPathString =
        [resourcePath
         stringByAppendingPathComponent:@"crash_report_sender.app"];
    reporterPathString =
        [[NSBundle bundleWithPath:reporterPathString] executablePath];
  }

  // Verify that there is a Reporter application.
  if (![[NSFileManager defaultManager]
             fileExistsAtPath:reporterPathString]) {
    return false;
  }

  if (!dumpSubdirectory) {
    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(SimpleStringDictionary)) )
        SimpleStringDictionary();

  SimpleStringDictionary& 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_REPORT_INTERVAL, [interval UTF8String]);
  dictionary.SetKeyValue(BREAKPAD_SKIP_CONFIRM,    [skipConfirm UTF8String]);
  dictionary.SetKeyValue(BREAKPAD_CONFIRM_TIMEOUT, [timeout UTF8String]);
  dictionary.SetKeyValue(BREAKPAD_INSPECTOR_LOCATION,
                         [inspectorPathString fileSystemRepresentation]);
  dictionary.SetKeyValue(BREAKPAD_REPORTER_EXE_LOCATION,
                         [reporterPathString fileSystemRepresentation]);
  dictionary.SetKeyValue(BREAKPAD_LOGFILE_UPLOAD_SIZE,
                         [logFileTailSize UTF8String]);
  dictionary.SetKeyValue(BREAKPAD_REQUEST_COMMENTS,
                         [requestUserText UTF8String]);
  dictionary.SetKeyValue(BREAKPAD_REQUEST_EMAIL, [requestEmail 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 (logFilePaths) {
    char logFileKey[255];
    for(unsigned int i = 0; i < [logFilePaths count]; i++) {
      sprintf(logFileKey,"%s%d", BREAKPAD_LOGFILE_KEY_PREFIX, i);
      dictionary.SetKeyValue(logFileKey,
                             [[logFilePaths objectAtIndex:i]
                               fileSystemRepresentation]);
    }
  }

  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 char* value = config_params_->GetValueForKey([key UTF8String]);
  return value ? [NSString stringWithUTF8String:value] : nil;
}

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

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

//=============================================================================
void Breakpad::GenerateAndSendReport() {
  config_params_->SetKeyValue(BREAKPAD_ON_DEMAND, "YES");
  HandleException(0, 0, 0, mach_thread_self());
  config_params_->SetKeyValue(BREAKPAD_ON_DEMAND, "NO");
}

//=============================================================================
bool Breakpad::HandleException(int exception_type,
                               int exception_code,
                               int exception_subcode,
                               mach_port_t crashing_thread) {
  if (filter_callback_) {
    bool should_handle = filter_callback_(exception_type,
                                          exception_code,
                                          crashing_thread,
                                          filter_callback_context_);
    if (!should_handle) return false;
  }

  // We need to reset the memory protections to be read/write,
  // since LaunchOnDemand() requires changing state.
  gBreakpadAllocator->Unprotect();
  // Configure the server to launch when we message the service port.
  // The reason we do this here, rather than at startup, is that we
  // can leak a bootstrap service entry if this method is called and
  // there never ends up being a crash.
  inspector_.LaunchOnDemand();
  gBreakpadAllocator->Protect();

  // The Inspector should send a message to this port to verify it
  // received our information and has finished the inspection.
  ReceivePort acknowledge_port;

  // Send initial information to the Inspector.
  MachSendMessage message(kMsgType_InspectorInitialInfo);
  message.AddDescriptor(mach_task_self());          // our task
  message.AddDescriptor(crashing_thread);           // crashing thread
  message.AddDescriptor(mach_thread_self());        // exception-handling thread
  message.AddDescriptor(acknowledge_port.GetPort());// message receive port

  InspectorInfo info;
  info.exception_type = exception_type;
  info.exception_code = exception_code;
  info.exception_subcode = exception_subcode;
  info.parameter_count = config_params_->GetCount();
  message.SetData(&info, sizeof(info));

  MachPortSender sender(inspector_.GetServicePort());

  kern_return_t result = sender.SendMessage(message, 2000);

  if (result == KERN_SUCCESS) {
    // Now, send a series of key-value pairs to the Inspector.
    const SimpleStringDictionary::Entry* entry = NULL;
    SimpleStringDictionary::Iterator iter(*config_params_);

    while ( (entry = iter.Next()) ) {
      KeyValueMessageData keyvalue_data(*entry);

      MachSendMessage keyvalue_message(kMsgType_InspectorKeyValuePair);
      keyvalue_message.SetData(&keyvalue_data, sizeof(keyvalue_data));

      result = sender.SendMessage(keyvalue_message, 2000);

      if (result != KERN_SUCCESS) {
        break;
      }
    }

    if (result == KERN_SUCCESS) {
      // Wait for acknowledgement that the inspection has finished.
      MachReceiveMessage acknowledge_messsage;
      result = acknowledge_port.WaitForMessage(&acknowledge_messsage, 5000);
    }
  }

#if VERBOSE
  PRINT_MACH_RESULT(result, "Breakpad: SendMessage ");
  printf("Breakpad: Inspector service port = %#x\n",
    inspector_.GetServicePort());
#endif

  // If we don't want any forwarding, return true here to indicate that we've
  // processed things as much as we want.
  if (send_and_exit_) return true;

  return false;
}

//=============================================================================
bool Breakpad::HandleMinidump(const char* dump_dir, const char* minidump_id) {
  google_breakpad::ConfigFile config_file;
  config_file.WriteFile(dump_dir, config_params_, dump_dir, minidump_id);
  google_breakpad::LaunchReporter(
      config_params_->GetValueForKey(BREAKPAD_REPORTER_EXE_LOCATION),
      config_file.GetFilePath());
  return true;
}

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

#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(SimpleStringDictionary));

    // Create a mutex for use in accessing the SimpleStringDictionary
    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");
  }
}

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

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

      gBreakpadAllocator->Unprotect();
      breakpad->GenerateAndSendReport();
      gBreakpadAllocator->Protect();
    }
  } catch(...) {    // don't let exceptions leave this C API
    fprintf(stderr, "BreakpadGenerateAndSendReport() : error\n");
  }
}

//=============================================================================
void BreakpadSetFilterCallback(BreakpadRef ref,
                               BreakpadFilterCallback callback,
                               void* context) {

  try {
    Breakpad* breakpad = (Breakpad*)ref;

    if (breakpad && gBreakpadAllocator) {
      // share the dictionary mutex here (we really don't need a mutex)
      ProtectedMemoryLocker locker(&gDictionaryMutex, gBreakpadAllocator);

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

//============================================================================
void BreakpadAddLogFile(BreakpadRef ref, NSString* logPathname) {
  int logFileCounter = 0;

  NSString* logFileKey = [NSString stringWithFormat:@"%@%d",
                                   @BREAKPAD_LOGFILE_KEY_PREFIX,
                                   logFileCounter];

  NSString* existingLogFilename = nil;
  existingLogFilename = BreakpadKeyValue(ref, logFileKey);
  // Find the first log file key that we can use by testing for existence
  while (existingLogFilename) {
    if ([existingLogFilename isEqualToString:logPathname]) {
      return;
    }
    logFileCounter++;
    logFileKey = [NSString stringWithFormat:@"%@%d",
                           @BREAKPAD_LOGFILE_KEY_PREFIX,
                           logFileCounter];
    existingLogFilename = BreakpadKeyValue(ref, logFileKey);
  }

  BreakpadSetKeyValue(ref, logFileKey, logPathname);
}
