Merge r1375 from trunk for M38 release.


git-svn-id: http://google-breakpad.googlecode.com/svn/branches/chrome_38@1383 4c0a9323-5329-0410-9bdc-e9ce6186880e
diff --git a/src/client/apple/Framework/BreakpadDefines.h b/src/client/apple/Framework/BreakpadDefines.h
index 8986cd1..410a5a6 100644
--- a/src/client/apple/Framework/BreakpadDefines.h
+++ b/src/client/apple/Framework/BreakpadDefines.h
@@ -62,6 +62,7 @@
 #define BREAKPAD_EMAIL                 "BreakpadEmail"
 #define BREAKPAD_SERVER_TYPE           "BreakpadServerType"
 #define BREAKPAD_SERVER_PARAMETER_DICT "BreakpadServerParameters"
+#define BREAKPAD_IN_PROCESS            "BreakpadInProcess"
 
 // The keys below are NOT user supplied, and are used internally.
 #define BREAKPAD_PROCESS_START_TIME       "BreakpadProcStartTime"
diff --git a/src/client/mac/Framework/Breakpad.h b/src/client/mac/Framework/Breakpad.h
index dbc620e..dc7e45d 100644
--- a/src/client/mac/Framework/Breakpad.h
+++ b/src/client/mac/Framework/Breakpad.h
@@ -158,6 +158,11 @@
 //                                but pass as URL parameters when
 //                                uploading theminidump to the crash
 //                                server.
+//
+// BREAKPAD_IN_PROCESS            A boolean NSNumber value. If YES, Breakpad
+//                                will write the dump file in-process and then
+//                                launch the reporter executable as a child
+//                                process.
 //=============================================================================
 // The BREAKPAD_PRODUCT, BREAKPAD_VERSION and BREAKPAD_URL are
 // required to have non-NULL values.  By default, the BREAKPAD_PRODUCT
diff --git a/src/client/mac/Framework/Breakpad.mm b/src/client/mac/Framework/Breakpad.mm
index fe592bf..3b4b667 100644
--- a/src/client/mac/Framework/Breakpad.mm
+++ b/src/client/mac/Framework/Breakpad.mm
@@ -44,6 +44,7 @@
 #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"
 
@@ -173,6 +174,8 @@
   }
 
   bool Initialize(NSDictionary *parameters);
+  bool InitializeInProcess(NSDictionary *parameters);
+  bool InitializeOutOfProcess(NSDictionary *parameters);
 
   bool ExtractParameters(NSDictionary *parameters);
 
@@ -188,6 +191,17 @@
                        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)
@@ -266,6 +280,21 @@
 }
 
 //=============================================================================
+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>
@@ -326,6 +355,25 @@
     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);
 
@@ -711,6 +759,16 @@
 }
 
 //=============================================================================
+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 -
diff --git a/src/client/mac/crash_generation/ConfigFile.mm b/src/client/mac/crash_generation/ConfigFile.mm
index dbb0f24..acab7de 100644
--- a/src/client/mac/crash_generation/ConfigFile.mm
+++ b/src/client/mac/crash_generation/ConfigFile.mm
@@ -36,7 +36,7 @@
 #include <sys/time.h>
 
 #import "client/apple/Framework/BreakpadDefines.h"
-#import "GTMDefines.h"
+#import "common/mac/GTMDefines.h"
 
 
 namespace google_breakpad {
diff --git a/src/client/mac/crash_generation/Inspector.h b/src/client/mac/crash_generation/Inspector.h
index 7e2eec8..6712355 100644
--- a/src/client/mac/crash_generation/Inspector.h
+++ b/src/client/mac/crash_generation/Inspector.h
@@ -138,7 +138,6 @@
 
   bool            InspectTask();
   kern_return_t   SendAcknowledgement();
-  void            LaunchReporter(const char *inConfigFilePath);
 
   // The bootstrap port in which the inspector is registered and into which it
   // must check in.
diff --git a/src/client/mac/crash_generation/Inspector.mm b/src/client/mac/crash_generation/Inspector.mm
index d226ca3..dc6f480 100644
--- a/src/client/mac/crash_generation/Inspector.mm
+++ b/src/client/mac/crash_generation/Inspector.mm
@@ -43,6 +43,7 @@
 
 #import "common/mac/MachIPC.h"
 #include "common/mac/bootstrap_compat.h"
+#include "common/mac/launch_reporter.h"
 
 #import "GTMDefines.h"
 
@@ -76,7 +77,9 @@
       if (wrote_minidump) {
         // Ask the user if he wants to upload the crash report to a server,
         // and do so if he agrees.
-        LaunchReporter(config_file_.GetFilePath());
+        LaunchReporter(
+            config_params_.GetValueForKey(BREAKPAD_REPORTER_EXE_LOCATION),
+            config_file_.GetFilePath());
       } else {
         fprintf(stderr, "Inspection of crashed process failed\n");
       }
@@ -355,51 +358,5 @@
   return KERN_INVALID_NAME;
 }
 
-//=============================================================================
-void Inspector::LaunchReporter(const char *inConfigFilePath) {
-  // Extract the path to the reporter executable.
-  const char *reporterExecutablePath =
-          config_params_.GetValueForKey(BREAKPAD_REPORTER_EXE_LOCATION);
-
-  // Setup and launch the crash dump sender.
-  const char *argv[3];
-  argv[0] = reporterExecutablePath;
-  argv[1] = inConfigFilePath;
-  argv[2] = NULL;
-
-  // Launch the reporter
-  pid_t pid = fork();
-
-  // If we're in the child, load in our new executable and run.
-  // The parent will not wait for the child to complete.
-  if (pid == 0) {
-    execv(argv[0], (char * const *)argv);
-    config_file_.Unlink();  // launch failed - get rid of config file
-    _exit(1);
-  }
-
-  // Wait until the Reporter child process exits.
-  //
-
-  // We'll use a timeout of one minute.
-  int timeoutCount = 60;   // 60 seconds
-
-  while (timeoutCount-- > 0) {
-    int status;
-    pid_t result = waitpid(pid, &status, WNOHANG);
-
-    if (result == 0) {
-      // The child has not yet finished.
-      sleep(1);
-    } else if (result == -1) {
-      // error occurred.
-      break;
-    } else {
-      // child has finished
-      break;
-    }
-  }
-}
-
 } // namespace google_breakpad
 
diff --git a/src/common/mac/launch_reporter.cc b/src/common/mac/launch_reporter.cc
new file mode 100644
index 0000000..245be82
--- /dev/null
+++ b/src/common/mac/launch_reporter.cc
@@ -0,0 +1,84 @@
+// Copyright (c) 2014, 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.
+
+#include <stdio.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+namespace google_breakpad {
+
+void LaunchReporter(const char *reporter_executable_path,
+                    const char *config_file_path) {
+  const char* argv[] = { reporter_executable_path, config_file_path, NULL };
+
+  // Launch the reporter
+  pid_t pid = fork();
+
+  if (pid == -1) {
+    perror("fork");
+    fprintf(stderr, "Failed to fork reporter process\n");
+    return;
+  }
+
+  // If we're in the child, load in our new executable and run.
+  // The parent will not wait for the child to complete.
+  if (pid == 0) {
+    execv(argv[0], (char* const*)argv);
+    perror("exec");
+    fprintf(stderr,
+            "Failed to launch reporter process from path %s\n",
+            reporter_executable_path);
+    unlink(config_file_path);  // launch failed - get rid of config file
+    _exit(1);
+  }
+
+  // Wait until the Reporter child process exits.
+  //
+
+  // We'll use a timeout of one minute.
+  int timeout_count = 60;   // 60 seconds
+
+  while (timeout_count-- > 0) {
+    int status;
+    pid_t result = waitpid(pid, &status, WNOHANG);
+
+    if (result == 0) {
+      // The child has not yet finished.
+      sleep(1);
+    } else if (result == -1) {
+      // error occurred.
+      break;
+    } else {
+      // child has finished
+      break;
+    }
+  }
+}
+
+}  // namespace google_breakpad
diff --git a/src/common/mac/launch_reporter.h b/src/common/mac/launch_reporter.h
new file mode 100644
index 0000000..4531123
--- /dev/null
+++ b/src/common/mac/launch_reporter.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2014, 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.
+
+#ifndef COMMON_MAC_LAUNCH_REPORTER_H__
+#define COMMON_MAC_LAUNCH_REPORTER_H__
+
+namespace google_breakpad {
+
+// Launch the crash dump sender app.
+// |reporter_executable_path| is the path to the sender executable.
+// |config_file_path| is the path to the config file.
+void LaunchReporter(const char *reporter_executable_path,
+                    const char *config_file_path);
+
+}  // namespace google_breakpad
+
+#endif  // COMMON_MAC_LAUNCH_REPORTER_H__