ios: Add API to DumpWithoutCrashAndDeferProcessingAtPath.

DumpWithoutCrashAndDeferProcessingAtPath(path) generate an intermediate
dump that can only be processed if ProcessIntermediateDump(file)
is called.  This means the client retains ownership of cleaning up the
intermediate dump if for whatever reason it is no longer needed.

This is useful for Chromium hang reports, which are speculatively
generated during a hang, but are later deleted if a hang recovers or if
the hang leads to an actual crash.

Bug: crashpad: 31
Change-Id: If91a8d7036ae26306e3f4d688b15159013a045df
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3021668
Reviewed-by: Mark Mentovai <mark@chromium.org>
Commit-Queue: Justin Cohen <justincohen@chromium.org>
GitOrigin-RevId: 202283a85c33595fde5da730e3add2c4df9df835
diff --git a/client/crashpad_client.h b/client/crashpad_client.h
index ec6c5e5..10ad404 100644
--- a/client/crashpad_client.h
+++ b/client/crashpad_client.h
@@ -462,7 +462,7 @@
   //! \param[in] database The path to a Crashpad database.
   //! \param[in] url The URL of an upload server.
   //! \param[in] annotations Process annotations to set in each crash report.
-  void StartCrashpadInProcessHandler(
+  static void StartCrashpadInProcessHandler(
       const base::FilePath& database,
       const std::string& url,
       const std::map<std::string, std::string>& annotations);
@@ -479,7 +479,24 @@
   //! \param[in] annotations Process annotations to set in each crash report.
   //!     Useful when adding crash annotations detected on the next run after a
   //!     crash but before upload.
-  void ProcessIntermediateDumps(
+  static void ProcessIntermediateDumps(
+      const std::map<std::string, std::string>& annotations = {});
+
+  //! \brief Requests that the handler convert a single intermediate dump at \a
+  //!     file generated by DumpWithoutCrashAndDeferProcessingAtPath into a
+  //!     minidump and trigger an upload if possible.
+  //!
+  //! A handler must have already been installed before calling this method.
+  //! This method should be called when an application is ready to start
+  //! processing previously created intermediate dumps. Processing will block,
+  //! so this should not be called on the main UI thread.
+  //!
+  //! \param[in] file The intermediate dump to process.
+  //! \param[in] annotations Process annotations to set in each crash report.
+  //!     Useful when adding crash annotations detected on the next run after a
+  //!     crash but before upload.
+  static void ProcessIntermediateDump(
+      const base::FilePath& file,
       const std::map<std::string, std::string>& annotations = {});
 
   //! \brief Requests that the handler begin in-process uploading of any
@@ -489,7 +506,7 @@
   //! on another thread. This method does not block.
   //!
   //! A handler must have already been installed before calling this method.
-  void StartProcesingPendingReports();
+  static void StartProcesingPendingReports();
 
   //! \brief Requests that the handler capture an intermediate dump even though
   //!     there hasn't been a crash. The intermediate dump will be converted
@@ -516,6 +533,23 @@
   //! \param[in] context A NativeCPUContext, generally captured by
   //!     CaptureContext() or similar.
   static void DumpWithoutCrashAndDeferProcessing(NativeCPUContext* context);
+
+  //! \brief Requests that the handler capture an intermediate dump and store it
+  //!     in path, even though there hasn't been a crash. The intermediate dump
+  //!     will not be converted to a mindump until ProcessIntermediateDump() is
+  //!     called.
+  //!
+  //! For internal use only. Clients should use
+  //! CRASHPAD_SIMULATE_CRASH_AND_DEFER_PROCESSING_AT_PATH().
+  //!
+  //! A handler must have already been installed before calling this method.
+  //!
+  //! \param[in] context A NativeCPUContext, generally captured by
+  //!     CaptureContext() or similar.
+  //! \param[in] path The path for writing the intermediate dump.
+  static void DumpWithoutCrashAndDeferProcessingAtPath(
+      NativeCPUContext* context,
+      const base::FilePath path);
 #endif
 
 #if defined(OS_APPLE) || DOXYGEN
diff --git a/client/crashpad_client_ios.cc b/client/crashpad_client_ios.cc
index 69e90d8..5c1f1ee 100644
--- a/client/crashpad_client_ios.cc
+++ b/client/crashpad_client_ios.cc
@@ -55,6 +55,10 @@
   void ProcessIntermediateDumps(
       const std::map<std::string, std::string>& annotations = {}) {}
 
+  void ProcessIntermediateDump(
+      const base::FilePath& file,
+      const std::map<std::string, std::string>& annotations = {}) {}
+
   void DumpWithoutCrash(NativeCPUContext* context) {
     INITIALIZATION_STATE_DCHECK_VALID(initialized_);
     mach_exception_data_type_t code[2] = {};
@@ -220,6 +224,15 @@
 }
 
 // static
+void CrashpadClient::ProcessIntermediateDump(
+    const base::FilePath& file,
+    const std::map<std::string, std::string>& annotations) {
+  CrashHandler* crash_handler = CrashHandler::Get();
+  DCHECK(crash_handler);
+  crash_handler->ProcessIntermediateDump(file, annotations);
+}
+
+// static
 void CrashpadClient::StartProcesingPendingReports() {
   // TODO(justincohen): Start the CrashReportUploadThread.
 }
@@ -242,4 +255,14 @@
   crash_handler->DumpWithoutCrash(context);
 }
 
+// static
+void CrashpadClient::DumpWithoutCrashAndDeferProcessingAtPath(
+    NativeCPUContext* context,
+    const base::FilePath path) {
+  CrashHandler* crash_handler = CrashHandler::Get();
+  DCHECK(crash_handler);
+  // TODO(justincohen): Change to DumpWithoutCrashAtPath(context, path).
+  crash_handler->DumpWithoutCrash(context);
+}
+
 }  // namespace crashpad
diff --git a/client/simulate_crash_ios.h b/client/simulate_crash_ios.h
index 87a9457..14e1e15 100644
--- a/client/simulate_crash_ios.h
+++ b/client/simulate_crash_ios.h
@@ -47,4 +47,12 @@
         &cpu_context);                                            \
   } while (false)
 
+#define CRASHPAD_SIMULATE_CRASH_AND_DEFER_PROCESSING_AT_PATH(path)      \
+  do {                                                                  \
+    crashpad::NativeCPUContext cpu_context;                             \
+    crashpad::CaptureContext(&cpu_context);                             \
+    crashpad::CrashpadClient::DumpWithoutCrashAndDeferProcessingAtPath( \
+        &cpu_context, path);                                            \
+  } while (false)
+
 #endif  // CRASHPAD_CLIENT_SIMULATE_CRASH_IOS_H_