crash: Introduce util.h/cc

Move IsCrashTestInProgress() and IsDeveloperImage() to
util.h/cc.  These functions will be needed for porting
the equivalents (is_crash_test_in_progress() and
is_developer_mode()) from crash_sender.sh to C++.
Add unit tests for them.

Also rename chrome_paths.h/cc to paths.h/cc and move
paths::Get() stuff to paths.h/cc.

BUG=chromium:391887
TEST=unit tests

Change-Id: I073e3dc783d9cc2ad840efc3d14b2bdef9d07f93
Reviewed-on: https://chromium-review.googlesource.com/1170710
Commit-Ready: Satoru Takabayashi <satorux@google.com>
Tested-by: Satoru Takabayashi <satorux@google.com>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Reviewed-by: Daichi Hirono <hirono@chromium.org>
diff --git a/crash-reporter/arc_collector.cc b/crash-reporter/arc_collector.cc
index ff01edd..a201fe0 100644
--- a/crash-reporter/arc_collector.cc
+++ b/crash-reporter/arc_collector.cc
@@ -24,6 +24,8 @@
 #include <brillo/key_value_store.h>
 #include <brillo/process.h>
 
+#include "crash-reporter/util.h"
+
 using base::File;
 using base::FilePath;
 using base::ReadFileToString;
@@ -153,7 +155,7 @@
                                    const std::string& cpu_abi) {
   std::string reason;
   const bool should_dump = UserCollectorBase::ShouldDump(
-      is_feedback_allowed_function_(), IsDeveloperImage(), &reason);
+      is_feedback_allowed_function_(), util::IsDeveloperImage(), &reason);
 
   std::ostringstream message;
   message << "Received " << crash_type << " notification";
@@ -335,7 +337,7 @@
   }
 
   return UserCollectorBase::ShouldDump(is_feedback_allowed_function_(),
-                                       IsDeveloperImage(), reason);
+                                       util::IsDeveloperImage(), reason);
 }
 
 UserCollectorBase::ErrorType ArcCollector::ConvertCoreToMinidump(
diff --git a/crash-reporter/crash-reporter.gyp b/crash-reporter/crash-reporter.gyp
index d063ea7..8416af1 100644
--- a/crash-reporter/crash-reporter.gyp
+++ b/crash-reporter/crash-reporter.gyp
@@ -5,6 +5,27 @@
       'type': 'static_library',
       'variables': {
         'exported_deps': [
+          'libchrome-<(libbase_ver)',
+        ],
+        'deps': ['<@(exported_deps)'],
+      },
+      'all_dependent_settings': {
+        'variables': {
+          'deps': [
+            '<@(exported_deps)',
+          ],
+        },
+      },
+      'sources': [
+        'paths.cc',
+        'util.cc',
+      ],
+    },
+    {
+      'target_name': 'libcrash_reporter',
+      'type': 'static_library',
+      'variables': {
+        'exported_deps': [
           'libbrillo-<(libbase_ver)',
           'libchrome-<(libbase_ver)',
           'libdebugd-client',
@@ -63,6 +84,7 @@
       },
       'dependencies': [
         'libcrash',
+        'libcrash_reporter',
       ],
       'defines': [
         'USE_CHEETS=<(USE_cheets)',
@@ -81,9 +103,11 @@
           'libminijail',
         ],
       },
+      'dependencies': [
+        'libcrash',
+      ],
       'sources': [
         'crash_sender.cc',
-        'crash_sender_paths.cc',
         'crash_sender_util.cc',
       ],
     },
@@ -159,20 +183,22 @@
           'target_name': 'crash_reporter_test',
           'type': 'executable',
           'includes': ['../common-mk/common_test.gypi'],
-          'dependencies': ['libcrash'],
+          'dependencies': [
+            'libcrash',
+            'libcrash_reporter',
+          ],
           'sources': [
             'chrome_collector_test.cc',
             'crash_collector_test.cc',
             'crash_collector_test.h',
             'crash_reporter_logs_test.cc',
-            'crash_sender_paths.cc',
-            'crash_sender_paths_test.cc',
             'crash_sender_util.cc',
             'crash_sender_util_test.cc',
             'ec_collector_test.cc',
             'kernel_collector_test.cc',
             'kernel_collector_test.h',
             'kernel_warning_collector_test.cc',
+            'paths_test.cc',
             'selinux_violation_collector_test.cc',
             'service_failure_collector_test.cc',
             'test_util.cc',
@@ -180,6 +206,7 @@
             'udev_collector_test.cc',
             'unclean_shutdown_collector_test.cc',
             'user_collector_test.cc',
+            'util_test.cc',
           ],
           'conditions': [
             ['USE_cheets == 1', {
diff --git a/crash-reporter/crash_collector.cc b/crash-reporter/crash_collector.cc
index d643c17..41e9a4f 100644
--- a/crash-reporter/crash_collector.cc
+++ b/crash-reporter/crash_collector.cc
@@ -32,17 +32,16 @@
 #include <brillo/key_value_store.h>
 #include <brillo/process.h>
 
-#include "crash-reporter/crash_common_paths.h"
+#include "crash-reporter/paths.h"
+#include "crash-reporter/util.h"
 
 namespace {
 
 const char kCollectChromeFile[] =
     "/mnt/stateful_partition/etc/collect_chrome_crashes";
-const char kCrashTestInProgressPath[] = "crash-test-in-progress";
 const char kCrashReporterStatePath[] = "/var/lib/crash_reporter";
 const char kDefaultLogConfig[] = "/etc/crash_reporter_logs.conf";
 const char kDefaultUserName[] = "chronos";
-const char kLeaveCoreFile[] = "/root/.leave_core";
 const char kLsbRelease[] = "/etc/lsb-release";
 const char kShellPath[] = "/bin/sh";
 const char kSystemCrashPath[] = "/var/spool/crash";
@@ -832,24 +831,11 @@
   }
 }
 
-bool CrashCollector::IsCrashTestInProgress() {
-  return base::PathExists(FilePath(paths::kSystemRunStateDirectory)
-                              .Append(kCrashTestInProgressPath));
-}
-
-bool CrashCollector::IsDeveloperImage() {
-  // If we're testing crash reporter itself, we don't want to special-case
-  // for developer images.
-  if (IsCrashTestInProgress())
-    return false;
-  return base::PathExists(FilePath(kLeaveCoreFile));
-}
-
 bool CrashCollector::ShouldHandleChromeCrashes() {
   // If we're testing crash reporter itself, we don't want to allow an
   // override for chrome crashes.  And, let's be conservative and only
   // allow an override for developer images.
-  if (!IsCrashTestInProgress() && IsDeveloperImage()) {
+  if (!util::IsCrashTestInProgress() && util::IsDeveloperImage()) {
     // Check if there's an override to indicate we should indeed collect
     // chrome crashes.  This allows the crashes to still be tracked when
     // they occur in autotests.  See "crosbug.com/17987".
diff --git a/crash-reporter/crash_collector.h b/crash-reporter/crash_collector.h
index 33437e8..102f0da 100644
--- a/crash-reporter/crash_collector.h
+++ b/crash-reporter/crash_collector.h
@@ -212,11 +212,6 @@
                           const std::string& exec_name,
                           const std::string& payload_name);
 
-  // Returns true if the a crash test is currently running.
-  bool IsCrashTestInProgress();
-  // Returns true if we should consider ourselves to be running on a
-  // developer image.
-  bool IsDeveloperImage();
   // Returns true if chrome crashes should be handled.
   bool ShouldHandleChromeCrashes();
   // Returns true if user crash directory may be used.
diff --git a/crash-reporter/crash_common_paths.h b/crash-reporter/crash_common_paths.h
deleted file mode 100644
index 602de3b..0000000
--- a/crash-reporter/crash_common_paths.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2018 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CRASH_REPORTER_CRASH_COMMON_PATHS_H_
-#define CRASH_REPORTER_CRASH_COMMON_PATHS_H_
-
-namespace paths {
-
-// The base directory where we keep various state flags.
-constexpr char kSystemRunStateDirectory[] = "/run/crash_reporter";
-
-}  // namespace paths
-
-#endif  // CRASH_REPORTER_CRASH_COMMON_PATHS_H_
diff --git a/crash-reporter/crash_sender.cc b/crash-reporter/crash_sender.cc
index 9d1984a..b29f77a 100644
--- a/crash-reporter/crash_sender.cc
+++ b/crash-reporter/crash_sender.cc
@@ -20,6 +20,7 @@
 
 #include "crash-reporter/crash_sender_paths.h"
 #include "crash-reporter/crash_sender_util.h"
+#include "crash-reporter/paths.h"
 
 namespace {
 
diff --git a/crash-reporter/crash_sender.sh b/crash-reporter/crash_sender.sh
index 8e80471..346a23c 100755
--- a/crash-reporter/crash_sender.sh
+++ b/crash-reporter/crash_sender.sh
@@ -86,14 +86,14 @@
 }
 
 # Returns 0 if the a crash test is currently running.  NOTE: Mirrors
-# crash_collector.cc:CrashCollector::IsCrashTestInProgress().
+# util.cc:IsCrashTestInProgress().
 is_crash_test_in_progress() {
   [ -f "${CRASH_TEST_IN_PROGRESS_FILE}" ] && return 0
   return 1
 }
 
 # Returns 0 if we should consider ourselves to be running on a developer
-# image.  NOTE: Mirrors crash_collector.cc:CrashCollector::IsDeveloperImage().
+# image.  NOTE: Mirrors util.cc:IsDeveloperImage().
 is_developer_image() {
   # If we're testing crash reporter itself, we don't want to special-case
   # for developer images.
diff --git a/crash-reporter/crash_sender_paths.h b/crash-reporter/crash_sender_paths.h
index ebb3bc4..3821974 100644
--- a/crash-reporter/crash_sender_paths.h
+++ b/crash-reporter/crash_sender_paths.h
@@ -5,13 +5,8 @@
 #ifndef CRASH_REPORTER_CRASH_SENDER_PATHS_H_
 #define CRASH_REPORTER_CRASH_SENDER_PATHS_H_
 
-#include <base/files/file_path.h>
-#include <base/strings/string_piece.h>
-
 namespace paths {
 
-// The path constants here should be used with Get() function below.
-
 // File whose existence mocks crash sending.  If empty we pretend the
 // crash sending was successful, otherwise unsuccessful.
 constexpr char kMockCrashSending[] = "mock-crash-sending";
@@ -23,19 +18,6 @@
 // Must be stateful to enable testing kernel crashes.
 constexpr char kPauseCrashSending[] = "/var/lib/crash_sender_paused";
 
-// Gets a FilePath from the given path. A prefix will be added if the prefix is
-// set with SetPrefixForTesting().
-base::FilePath Get(base::StringPiece file_path);
-
-// Gets a FilePath from the given directory and the base name. A prefix will be
-// added if the prefix is set with SetPrefixForTesting().
-base::FilePath GetAt(base::StringPiece directory, base::StringPiece base_name);
-
-// Sets a prefix that'll be added when Get() is called, for unit testing.
-// For example, if "/tmp" is set as the prefix, Get("/run/foo") will return
-// "/tmp/run/foo". Passing "" will reset the prefix.
-void SetPrefixForTesting(const base::FilePath& prefix);
-
 }  // namespace paths
 
 #endif  // CRASH_REPORTER_CRASH_SENDER_PATHS_H_
diff --git a/crash-reporter/crash_sender_util.cc b/crash-reporter/crash_sender_util.cc
index ddbd2c8..01a81f1 100644
--- a/crash-reporter/crash_sender_util.cc
+++ b/crash-reporter/crash_sender_util.cc
@@ -15,8 +15,8 @@
 #include <base/strings/string_number_conversions.h>
 #include <brillo/flag_helper.h>
 
-#include "crash-reporter/crash_common_paths.h"
 #include "crash-reporter/crash_sender_paths.h"
+#include "crash-reporter/paths.h"
 
 namespace util {
 
diff --git a/crash-reporter/crash_sender_util_test.cc b/crash-reporter/crash_sender_util_test.cc
index 9ecadd0..cb322c8 100644
--- a/crash-reporter/crash_sender_util_test.cc
+++ b/crash-reporter/crash_sender_util_test.cc
@@ -13,8 +13,8 @@
 #include <brillo/flag_helper.h>
 #include <gtest/gtest.h>
 
-#include "crash-reporter/crash_common_paths.h"
 #include "crash-reporter/crash_sender_paths.h"
+#include "crash-reporter/paths.h"
 #include "crash-reporter/test_util.h"
 
 namespace util {
diff --git a/crash-reporter/ec_collector.cc b/crash-reporter/ec_collector.cc
index b77dc5c..44fde30 100644
--- a/crash-reporter/ec_collector.cc
+++ b/crash-reporter/ec_collector.cc
@@ -10,6 +10,8 @@
 #include <base/logging.h>
 #include <base/strings/stringprintf.h>
 
+#include "crash-reporter/util.h"
+
 using base::FilePath;
 using base::StringPiece;
 using base::StringPrintf;
@@ -55,7 +57,7 @@
 
   std::string reason = "handling";
   bool feedback = true;
-  if (IsDeveloperImage()) {
+  if (util::IsDeveloperImage()) {
     reason = "developer build - always dumping";
     feedback = true;
   } else if (!is_feedback_allowed_function_()) {
diff --git a/crash-reporter/kernel_collector.cc b/crash-reporter/kernel_collector.cc
index ae53a25..f40224b 100644
--- a/crash-reporter/kernel_collector.cc
+++ b/crash-reporter/kernel_collector.cc
@@ -19,6 +19,8 @@
 using base::StringPiece;
 using base::StringPrintf;
 
+#include "crash-reporter/util.h"
+
 namespace {
 
 const char kDefaultKernelStackSignature[] = "kernel-UnspecifiedStackSignature";
@@ -628,7 +630,7 @@
   FilePath root_crash_directory;
   std::string reason = "handling";
   bool feedback = true;
-  if (IsDeveloperImage()) {
+  if (util::IsDeveloperImage()) {
     reason = "developer build - always dumping";
     feedback = true;
   } else if (!is_feedback_allowed_function_()) {
diff --git a/crash-reporter/kernel_warning_collector.cc b/crash-reporter/kernel_warning_collector.cc
index a1397fc..91d0b94 100644
--- a/crash-reporter/kernel_warning_collector.cc
+++ b/crash-reporter/kernel_warning_collector.cc
@@ -10,6 +10,8 @@
 #include <base/strings/string_util.h>
 #include <base/strings/stringprintf.h>
 
+#include "crash-reporter/util.h"
+
 namespace {
 const char kGenericWarningExecName[] = "kernel-warning";
 const char kWifiWarningExecName[] = "kernel-wifi-warning";
@@ -47,7 +49,7 @@
 bool KernelWarningCollector::Collect(WarningType type) {
   std::string reason = "normal collection";
   bool feedback = true;
-  if (IsDeveloperImage()) {
+  if (util::IsDeveloperImage()) {
     reason = "always collect from developer builds";
     feedback = true;
   } else if (!is_feedback_allowed_function_()) {
diff --git a/crash-reporter/crash_sender_paths.cc b/crash-reporter/paths.cc
similarity index 94%
rename from crash-reporter/crash_sender_paths.cc
rename to crash-reporter/paths.cc
index 32fc300..cba904e 100644
--- a/crash-reporter/crash_sender_paths.cc
+++ b/crash-reporter/paths.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "crash-reporter/crash_sender_paths.h"
+#include "crash-reporter/paths.h"
 
 namespace paths {
 
diff --git a/crash-reporter/paths.h b/crash-reporter/paths.h
new file mode 100644
index 0000000..8626d8a
--- /dev/null
+++ b/crash-reporter/paths.h
@@ -0,0 +1,38 @@
+// Copyright 2018 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRASH_REPORTER_PATHS_H_
+#define CRASH_REPORTER_PATHS_H_
+
+#include <base/files/file_path.h>
+#include <base/strings/string_piece.h>
+
+namespace paths {
+
+// The base directory where we keep various state flags.
+constexpr char kSystemRunStateDirectory[] = "/run/crash_reporter";
+
+// File whose existence indicates this is a developer image.
+constexpr char kLeaveCoreFile[] = "/root/.leave_core";
+
+// Base name of file whose existence indicates a crash test is currently
+// running.
+constexpr char kCrashTestInProgress[] = "crash-test-in-progress";
+
+// Gets a FilePath from the given path. A prefix will be added if the prefix is
+// set with SetPrefixForTesting().
+base::FilePath Get(base::StringPiece file_path);
+
+// Gets a FilePath from the given directory and the base name. A prefix will be
+// added if the prefix is set with SetPrefixForTesting().
+base::FilePath GetAt(base::StringPiece directory, base::StringPiece base_name);
+
+// Sets a prefix that'll be added when Get() is called, for unit testing.
+// For example, if "/tmp" is set as the prefix, Get("/run/foo") will return
+// "/tmp/run/foo". Passing "" will reset the prefix.
+void SetPrefixForTesting(const base::FilePath& prefix);
+
+}  // namespace paths
+
+#endif  // CRASH_REPORTER_PATHS_H_
diff --git a/crash-reporter/crash_sender_paths_test.cc b/crash-reporter/paths_test.cc
similarity index 81%
rename from crash-reporter/crash_sender_paths_test.cc
rename to crash-reporter/paths_test.cc
index d467ac9..2f3b0e8 100644
--- a/crash-reporter/crash_sender_paths_test.cc
+++ b/crash-reporter/paths_test.cc
@@ -2,25 +2,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "crash-reporter/crash_sender_paths.h"
+#include "crash-reporter/paths.h"
 
 #include <base/files/file_path.h>
 #include <gtest/gtest.h>
 
 namespace util {
 
-TEST(CrashSenderPathsTest, Get) {
+TEST(CrashCommonPathsTest, Get) {
   EXPECT_EQ("/run/foo", paths::Get("/run/foo").value());
 }
 
-TEST(CrashSenderPathsTest, SetPrefixForTesting) {
+TEST(CrashCommonPathsTest, SetPrefixForTesting) {
   paths::SetPrefixForTesting(base::FilePath("/tmp"));
   EXPECT_EQ("/tmp/run/foo", paths::Get("/run/foo").value());
   paths::SetPrefixForTesting(base::FilePath());
   EXPECT_EQ("/run/foo", paths::Get("/run/foo").value());
 }
 
-TEST(CrashSenderPathsTest, GetAtWithPrefix) {
+TEST(CrashCommonPathsTest, GetAtWithPrefix) {
   paths::SetPrefixForTesting(base::FilePath("/tmp"));
   EXPECT_EQ("/tmp/run/foo", paths::GetAt("/run", "foo").value());
   paths::SetPrefixForTesting(base::FilePath());
diff --git a/crash-reporter/selinux_violation_collector.cc b/crash-reporter/selinux_violation_collector.cc
index 4494e16..a9690f2 100644
--- a/crash-reporter/selinux_violation_collector.cc
+++ b/crash-reporter/selinux_violation_collector.cc
@@ -11,6 +11,8 @@
 #include <base/rand_util.h>
 #include <base/strings/stringprintf.h>
 
+#include "crash-reporter/util.h"
+
 namespace {
 constexpr char kExecName[] = "selinux-violation";
 constexpr char kSignatureKey[] = "sig";
@@ -66,7 +68,7 @@
 bool SELinuxViolationCollector::Collect() {
   std::string reason = "normal collection";
   bool feedback = true;
-  if (IsDeveloperImage() || developer_image_for_testing_) {
+  if (util::IsDeveloperImage() || developer_image_for_testing_) {
     feedback = true;
     reason = "always collect from developer builds";
   } else if (!is_feedback_allowed_function_()) {
diff --git a/crash-reporter/service_failure_collector.cc b/crash-reporter/service_failure_collector.cc
index 01f6871..9c62061 100644
--- a/crash-reporter/service_failure_collector.cc
+++ b/crash-reporter/service_failure_collector.cc
@@ -8,6 +8,8 @@
 #include <base/logging.h>
 #include <base/strings/stringprintf.h>
 
+#include "crash-reporter/util.h"
+
 namespace {
 const char kExecName[] = "service-failure";
 const char kSignatureKey[] = "sig";
@@ -41,7 +43,7 @@
 bool ServiceFailureCollector::Collect() {
   std::string reason = "normal collection";
   bool feedback = true;
-  if (IsDeveloperImage()) {
+  if (util::IsDeveloperImage()) {
     reason = "always collect from developer builds";
     feedback = true;
   } else if (!is_feedback_allowed_function_()) {
diff --git a/crash-reporter/udev_collector.cc b/crash-reporter/udev_collector.cc
index bca4e59..5a7645e 100644
--- a/crash-reporter/udev_collector.cc
+++ b/crash-reporter/udev_collector.cc
@@ -17,6 +17,8 @@
 #include <base/strings/stringprintf.h>
 #include <brillo/process.h>
 
+#include "crash-reporter/util.h"
+
 using base::FilePath;
 
 namespace {
@@ -38,7 +40,7 @@
 UdevCollector::~UdevCollector() {}
 
 bool UdevCollector::HandleCrash(const std::string& udev_event) {
-  if (IsDeveloperImage()) {
+  if (util::IsDeveloperImage()) {
     LOG(INFO) << "developer image - collect udev crash info.";
   } else if (is_feedback_allowed_function_()) {
     LOG(INFO) << "Consent given - collect udev crash info.";
@@ -80,7 +82,7 @@
 
 bool UdevCollector::Enable() {
   return base::WriteFile(FilePath(kDevCoredumpDisabledPath),
-                         IsDeveloperImage() ? "0" : "1", 1);
+                         util::IsDeveloperImage() ? "0" : "1", 1);
 }
 
 bool UdevCollector::ProcessUdevCrashLogs(const FilePath& crash_directory,
diff --git a/crash-reporter/user_collector.cc b/crash-reporter/user_collector.cc
index f4dd755..408ca90 100644
--- a/crash-reporter/user_collector.cc
+++ b/crash-reporter/user_collector.cc
@@ -19,6 +19,8 @@
 #include <base/strings/stringprintf.h>
 #include <brillo/process.h>
 
+#include "crash-reporter/util.h"
+
 using base::FilePath;
 using base::StringPrintf;
 
@@ -289,8 +291,9 @@
                                uid_t,
                                const std::string& exec,
                                std::string* reason) {
-  return ShouldDump(pid, is_feedback_allowed_function_(), IsDeveloperImage(),
-                    ShouldHandleChromeCrashes(), exec, reason);
+  return ShouldDump(pid, is_feedback_allowed_function_(),
+                    util::IsDeveloperImage(), ShouldHandleChromeCrashes(), exec,
+                    reason);
 }
 
 UserCollector::ErrorType UserCollector::ConvertCoreToMinidump(
diff --git a/crash-reporter/user_collector_base.cc b/crash-reporter/user_collector_base.cc
index ec55161..d9aab85 100644
--- a/crash-reporter/user_collector_base.cc
+++ b/crash-reporter/user_collector_base.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "crash-reporter/user_collector_base.h"
+
 #include <pcrecpp.h>
 
 #if USE_DIRENCRYPTION
@@ -13,7 +15,7 @@
 #include <base/strings/stringprintf.h>
 #include <brillo/syslog_logging.h>
 
-#include "crash-reporter/user_collector_base.h"
+#include "crash-reporter/util.h"
 
 using base::FilePath;
 using base::ReadFileToString;
@@ -295,7 +297,7 @@
   // crash report.
   WriteCrashMetaData(meta_path, exec, minidump_path.value());
 
-  if (!IsDeveloperImage()) {
+  if (!util::IsDeveloperImage()) {
     base::DeleteFile(core_path, false);
   } else {
     LOG(INFO) << "Leaving core file at " << core_path.value()
diff --git a/crash-reporter/util.cc b/crash-reporter/util.cc
new file mode 100644
index 0000000..ce31bd8
--- /dev/null
+++ b/crash-reporter/util.cc
@@ -0,0 +1,26 @@
+// Copyright 2018 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crash-reporter/util.h"
+
+#include <base/files/file_util.h>
+
+#include "crash-reporter/paths.h"
+
+namespace util {
+
+bool IsCrashTestInProgress() {
+  return base::PathExists(paths::GetAt(paths::kSystemRunStateDirectory,
+                                       paths::kCrashTestInProgress));
+}
+
+bool IsDeveloperImage() {
+  // If we're testing crash reporter itself, we don't want to special-case
+  // for developer images.
+  if (IsCrashTestInProgress())
+    return false;
+  return base::PathExists(paths::Get(paths::kLeaveCoreFile));
+}
+
+}  // namespace util
diff --git a/crash-reporter/util.h b/crash-reporter/util.h
new file mode 100644
index 0000000..1b1595e
--- /dev/null
+++ b/crash-reporter/util.h
@@ -0,0 +1,18 @@
+// Copyright 2018 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRASH_REPORTER_UTIL_H_
+#define CRASH_REPORTER_UTIL_H_
+
+namespace util {
+
+// Returns true if integration tests are currently running.
+bool IsCrashTestInProgress();
+
+// Returns true if running on a developer image.
+bool IsDeveloperImage();
+
+}  // namespace util
+
+#endif  // CRASH_REPORTER_UTIL_H_
diff --git a/crash-reporter/util_test.cc b/crash-reporter/util_test.cc
new file mode 100644
index 0000000..a458741
--- /dev/null
+++ b/crash-reporter/util_test.cc
@@ -0,0 +1,53 @@
+// Copyright 2018 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crash-reporter/util.h"
+
+#include <base/files/file_util.h>
+#include <base/files/scoped_temp_dir.h>
+#include <gtest/gtest.h>
+
+#include "crash-reporter/crash_sender_paths.h"
+#include "crash-reporter/paths.h"
+#include "crash-reporter/test_util.h"
+
+namespace util {
+
+class CrashCommonUtilTest : public testing::Test {
+ private:
+  void SetUp() override {
+    ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
+    test_dir_ = scoped_temp_dir_.GetPath();
+    paths::SetPrefixForTesting(test_dir_);
+  }
+
+  void TearDown() override { paths::SetPrefixForTesting(base::FilePath()); }
+
+  base::FilePath test_dir_;
+  base::ScopedTempDir scoped_temp_dir_;
+};
+
+TEST_F(CrashCommonUtilTest, IsCrashTestInProgress) {
+  EXPECT_FALSE(IsCrashTestInProgress());
+  ASSERT_TRUE(
+      test_util::CreateFile(paths::GetAt(paths::kSystemRunStateDirectory,
+                                         paths::kCrashTestInProgress),
+                            ""));
+  EXPECT_TRUE(IsCrashTestInProgress());
+}
+
+TEST_F(CrashCommonUtilTest, IsDeveloperImage) {
+  EXPECT_FALSE(IsDeveloperImage());
+
+  ASSERT_TRUE(test_util::CreateFile(paths::Get(paths::kLeaveCoreFile), ""));
+  EXPECT_TRUE(IsDeveloperImage());
+
+  ASSERT_TRUE(
+      test_util::CreateFile(paths::GetAt(paths::kSystemRunStateDirectory,
+                                         paths::kCrashTestInProgress),
+                            ""));
+  EXPECT_FALSE(IsDeveloperImage());
+}
+
+}  // namespace util