Add buildtime to UMA upload data

r=tigerf
Review URL: http://codereview.chromium.org/519017

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35629 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/metrics/metrics_log.cc b/chrome/browser/metrics/metrics_log.cc
index 46a197c..2c7c617 100644
--- a/chrome/browser/metrics/metrics_log.cc
+++ b/chrome/browser/metrics/metrics_log.cc
@@ -12,6 +12,7 @@
 #include "base/scoped_ptr.h"
 #include "base/string_util.h"
 #include "base/sys_info.h"
+#include "base/third_party/nspr/prtime.h"
 #include "chrome/browser/autocomplete/autocomplete.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/common/logging_chrome.h"
@@ -37,6 +38,8 @@
   return reinterpret_cast<const unsigned char*>(input);
 }
 
+static int64 GetBuildTime();
+
 // static
 void MetricsLog::RegisterPrefs(PrefService* local_state) {
   local_state->RegisterListPref(prefs::kStabilityPluginStats);
@@ -62,6 +65,7 @@
 
   StartElement("log");
   WriteAttribute("clientid", client_id_);
+  WriteInt64Attribute("buildtime", GetBuildTime());
 
   DCHECK_GE(result, 0);
 }
@@ -709,3 +713,11 @@
     }
   }
 }
+
+static int64 GetBuildTime() {
+  Time parsed_time;
+  const char* kDateTime = __DATE__ " " __TIME__;
+  bool result = Time::FromString(ASCIIToWide(kDateTime).c_str(), &parsed_time);
+  DCHECK(result);
+  return static_cast<int64>(parsed_time.ToTimeT());
+}
diff --git a/chrome/browser/metrics/metrics_log_unittest.cc b/chrome/browser/metrics/metrics_log_unittest.cc
index d3324e3..85d7aaf8 100644
--- a/chrome/browser/metrics/metrics_log_unittest.cc
+++ b/chrome/browser/metrics/metrics_log_unittest.cc
@@ -17,8 +17,30 @@
   };
 };
 
+
+// Since buildtime is highly variable, this function will scan an output log and
+// replace it with a consistent number.
+static void NormalizeBuildtime(std::string* xml_encoded) {
+  std::string prefix = "buildtime=\"";
+  const char postfix = '\"';
+  size_t offset = xml_encoded->find(prefix);
+  ASSERT_GT(offset, 0u);
+  offset += prefix.size();
+  size_t postfix_position = xml_encoded->find(postfix, offset);
+  ASSERT_GT(postfix_position, offset);
+  for (size_t i = offset; i < postfix_position; ++i) {
+    char digit = xml_encoded->at(i);
+    ASSERT_GE(digit, '0');
+    ASSERT_LE(digit, '9');
+  }
+
+  // Insert a single fake buildtime.
+  xml_encoded->replace(offset, postfix_position - offset, "123246");
+}
+
 TEST(MetricsLogTest, EmptyRecord) {
-  std::string expected_output = "<log clientid=\"bogus client ID\"/>";
+  std::string expected_output =
+      "<log clientid=\"bogus client ID\" buildtime=\"123456789\"/>";
 
   MetricsLog log("bogus client ID", 0);
   log.CloseLog();
@@ -28,6 +50,8 @@
 
   std::string encoded;
   ASSERT_TRUE(log.GetEncodedLog(WriteInto(&encoded, size), size));
+  NormalizeBuildtime(&encoded);
+  NormalizeBuildtime(&expected_output);
 
   ASSERT_EQ(expected_output, encoded);
 }
@@ -50,14 +74,14 @@
 
 TEST(MetricsLogTest, WindowEvent) {
   std::string expected_output =
-    "<log clientid=\"bogus client ID\">\n"
-    " <window action=\"create\" windowid=\"0\" session=\"0\" time=\"\"/>\n"
-    " <window action=\"open\" windowid=\"1\" parent=\"0\" "
-        "session=\"0\" time=\"\"/>\n"
-    " <window action=\"close\" windowid=\"1\" parent=\"0\" "
-        "session=\"0\" time=\"\"/>\n"
-    " <window action=\"destroy\" windowid=\"0\" session=\"0\" time=\"\"/>\n"
-    "</log>";
+      "<log clientid=\"bogus client ID\" buildtime=\"123456789\">\n"
+      " <window action=\"create\" windowid=\"0\" session=\"0\" time=\"\"/>\n"
+      " <window action=\"open\" windowid=\"1\" parent=\"0\" "
+          "session=\"0\" time=\"\"/>\n"
+      " <window action=\"close\" windowid=\"1\" parent=\"0\" "
+          "session=\"0\" time=\"\"/>\n"
+      " <window action=\"destroy\" windowid=\"0\" session=\"0\" time=\"\"/>\n"
+      "</log>";
 
   NoTimeMetricsLog log("bogus client ID", 0);
   log.RecordWindowEvent(MetricsLog::WINDOW_CREATE, 0, -1);
@@ -73,17 +97,19 @@
 
   std::string encoded;
   ASSERT_TRUE(log.GetEncodedLog(WriteInto(&encoded, size), size));
+  NormalizeBuildtime(&encoded);
+  NormalizeBuildtime(&expected_output);
 
   ASSERT_EQ(expected_output, encoded);
 }
 
 TEST(MetricsLogTest, LoadEvent) {
   std::string expected_output =
-    "<log clientid=\"bogus client ID\">\n"
-    " <document action=\"load\" docid=\"1\" window=\"3\" loadtime=\"7219\" "
-    "origin=\"link\" "
-    "session=\"0\" time=\"\"/>\n"
-    "</log>";
+      "<log clientid=\"bogus client ID\" buildtime=\"123456789\">\n"
+      " <document action=\"load\" docid=\"1\" window=\"3\" loadtime=\"7219\" "
+      "origin=\"link\" "
+      "session=\"0\" time=\"\"/>\n"
+      "</log>";
 
   NoTimeMetricsLog log("bogus client ID", 0);
   log.RecordLoadEvent(3, GURL("http://google.com"), PageTransition::LINK,
@@ -98,6 +124,8 @@
 
   std::string encoded;
   ASSERT_TRUE(log.GetEncodedLog(WriteInto(&encoded, size), size));
+  NormalizeBuildtime(&encoded);
+  NormalizeBuildtime(&expected_output);
 
   ASSERT_EQ(expected_output, encoded);
 }