metrics: Send ability to notify chrome of system crashes

Change-Id: I11df903c020141a8123055620f9ad23fedc06c7d

BUG=9352
TEST=
1) UserCrash
2) Crash random process and verify Chrome indicates "other user" crashes
occurred in its stability UMA data.

Review URL: http://codereview.chromium.org/6211001
diff --git a/metrics/c_metrics_library.cc b/metrics/c_metrics_library.cc
index 3450918..8946699 100644
--- a/metrics/c_metrics_library.cc
+++ b/metrics/c_metrics_library.cc
@@ -51,6 +51,14 @@
   return lib->SendUserActionToUMA(std::string(action));
 }
 
+extern "C" int CMetricsLibrarySendCrashToUMA(CMetricsLibrary handle,
+                                            const char* crash_kind) {
+  MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
+  if (lib == NULL)
+    return 0;
+  return lib->SendCrashToUMA(crash_kind);
+}
+
 extern "C" int CMetricsLibraryAreMetricsEnabled(CMetricsLibrary handle) {
   MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
   if (lib == NULL)
diff --git a/metrics/c_metrics_library.h b/metrics/c_metrics_library.h
index 9500aad..5c7003d 100644
--- a/metrics/c_metrics_library.h
+++ b/metrics/c_metrics_library.h
@@ -32,6 +32,10 @@
 int CMetricsLibrarySendUserActionToUMA(CMetricsLibrary handle,
                                        const char* action);
 
+// C wrapper for MetricsLibrary::SendCrashToUMA.
+int CMetricsLibrarySendCrashToUMA(CMetricsLibrary handle,
+                                  const char* crash_kind);
+
 // C wrapper for MetricsLibrary::AreMetricsEnabled.
 int CMetricsLibraryAreMetricsEnabled(CMetricsLibrary handle);
 
diff --git a/metrics/metrics_library.cc b/metrics/metrics_library.cc
index 05e63ac..f2046a3 100644
--- a/metrics/metrics_library.cc
+++ b/metrics/metrics_library.cc
@@ -255,3 +255,17 @@
   // Send the message.
   return SendMessageToChrome(message_length, message);
 }
+
+bool MetricsLibrary::SendCrashToUMA(const char *crash_kind) {
+  // Format the message.
+  char message[kBufferSize];
+  int32_t message_length =
+      FormatChromeMessage(kBufferSize, message,
+                          "crash%c%s", '\0', crash_kind);
+
+  if (message_length < 0)
+    return false;
+
+  // Send the message.
+  return SendMessageToChrome(message_length, message);
+}
diff --git a/metrics/metrics_library.h b/metrics/metrics_library.h
index ed83862..3f860eb 100644
--- a/metrics/metrics_library.h
+++ b/metrics/metrics_library.h
@@ -82,6 +82,10 @@
   // |action| is the user-generated event (e.g., "MuteKeyPressed").
   bool SendUserActionToUMA(const std::string& action);
 
+  // Sends a signal to UMA that a crash of the given |crash_kind|
+  // has occurred.  Used by UMA to generate stability statistics.
+  bool SendCrashToUMA(const char *crash_kind);
+
   // Sends to Autotest and returns true on success.
   static bool SendToAutotest(const std::string& name, int value);
 
diff --git a/metrics/metrics_library_test.cc b/metrics/metrics_library_test.cc
index 3e49f69..762be4a 100644
--- a/metrics/metrics_library_test.cc
+++ b/metrics/metrics_library_test.cc
@@ -231,6 +231,23 @@
   EXPECT_FALSE(file_util::PathExists(kTestUMAEventsFile));
 }
 
+TEST_F(MetricsLibraryTest, SendCrashToUMAEnabled) {
+  EXPECT_TRUE(lib_.SendCrashToUMA("kernel"));
+  char exp[100];
+  int len = sprintf(exp, "%c%c%c%ccrash%ckernel",
+                    0, 0, 0, 0, 0) + 1;
+  exp[0] = len;
+  char buf[100];
+  EXPECT_EQ(len, file_util::ReadFile(kTestUMAEventsFile, buf, 100));
+  EXPECT_EQ(0, memcmp(exp, buf, len));
+}
+
+TEST_F(MetricsLibraryTest, SendCrashToUMANotEnabled) {
+  SetMetricsEnabled(false);
+  EXPECT_TRUE(lib_.SendCrashToUMA("kernel"));
+  EXPECT_FALSE(file_util::PathExists(kTestUMAEventsFile));
+}
+
 class CMetricsLibraryTest : public testing::Test {
  protected:
   virtual void SetUp() {
@@ -296,6 +313,17 @@
   EXPECT_EQ(0, memcmp(exp, buf, kLen));
 }
 
+TEST_F(CMetricsLibraryTest, SendCrashToUMA) {
+  char buf[100];
+  char exp[100];
+  int len = sprintf(exp, "%c%c%c%ccrash%cuser", 0, 0, 0, 0, 0) + 1;
+  exp[0] = len;
+  EXPECT_TRUE(CMetricsLibrarySendCrashToUMA(lib_, "user"));
+  EXPECT_EQ(len, file_util::ReadFile(kTestUMAEventsFile, buf, 100));
+
+  EXPECT_EQ(0, memcmp(exp, buf, len));
+}
+
 int main(int argc, char** argv) {
   testing::InitGoogleTest(&argc, argv);
   return RUN_ALL_TESTS();