AU: Send a previous version event after reboot following an update.

The previous version event is sent along with the first update check. This is
best effort -- if the update check doesn't reach the server, the event is lost.

BUG=9198
TEST=unit tests, tested on device

Change-Id: I5ceb7c8e99ae54eb331f6ac58b8977d2a111461c

Review URL: http://codereview.chromium.org/5993007
diff --git a/omaha_request_action.cc b/omaha_request_action.cc
index 5166315..bb2275d 100644
--- a/omaha_request_action.cc
+++ b/omaha_request_action.cc
@@ -93,11 +93,31 @@
 string FormatRequest(const OmahaEvent* event,
                      const OmahaRequestParams& params,
                      int ping_active_days,
-                     int ping_roll_call_days) {
+                     int ping_roll_call_days,
+                     PrefsInterface* prefs) {
   string body;
   if (event == NULL) {
     body = GetPingBody(ping_active_days, ping_roll_call_days) +
         "        <o:updatecheck></o:updatecheck>\n";
+    // If this is the first update check after a reboot following a previous
+    // update, generate an event containing the previous version number. If the
+    // previous version preference file doesn't exist the event is still
+    // generated with a previous version of 0.0.0.0 -- this is relevant for
+    // older clients or new installs.
+    string prev_version;
+    if (!prefs->GetString(kPrefsPreviousVersion, &prev_version)) {
+      prev_version = "0.0.0.0";
+    }
+    if (!prev_version.empty()) {
+      body += StringPrintf(
+          "        <o:event eventtype=\"%d\" eventresult=\"%d\" "
+          "previousversion=\"%s\"></o:event>\n",
+          OmahaEvent::kTypeUpdateComplete,
+          OmahaEvent::kResultSuccessReboot,
+          prev_version.c_str());
+      LOG_IF(WARNING, !prefs->SetString(kPrefsPreviousVersion, ""))
+          << "Unable to reset the previous version.";
+    }
   } else {
     // The error code is an optional attribute so append it only if
     // the result is not success.
@@ -197,7 +217,8 @@
   string request_post(FormatRequest(event_.get(),
                                     params_,
                                     ping_active_days_,
-                                    ping_roll_call_days_));
+                                    ping_roll_call_days_,
+                                    prefs_));
   http_fetcher_->SetPostData(request_post.data(), request_post.size());
   LOG(INFO) << "Posting an Omaha request to " << params_.update_url;
   LOG(INFO) << "Request: " << request_post;
diff --git a/omaha_request_action.h b/omaha_request_action.h
index b65d3f8..948bcc7 100644
--- a/omaha_request_action.h
+++ b/omaha_request_action.h
@@ -70,6 +70,7 @@
   enum Result {
     kResultError = 0,
     kResultSuccess = 1,
+    kResultSuccessReboot = 2,
   };
 
   OmahaEvent()
diff --git a/omaha_request_action_unittest.cc b/omaha_request_action_unittest.cc
index 8fe2482..4ac2b74 100755
--- a/omaha_request_action_unittest.cc
+++ b/omaha_request_action_unittest.cc
@@ -521,7 +521,11 @@
 
 TEST(OmahaRequestActionTest, FormatUpdateCheckOutputTest) {
   vector<char> post_data;
-  ASSERT_FALSE(TestUpdateCheck(NULL,  // prefs
+  NiceMock<PrefsMock> prefs;
+  EXPECT_CALL(prefs, GetString(kPrefsPreviousVersion, _))
+      .WillOnce(DoAll(SetArgumentPointee<1>(string("")), Return(true)));
+  EXPECT_CALL(prefs, SetString(kPrefsPreviousVersion, _)).Times(0);
+  ASSERT_FALSE(TestUpdateCheck(&prefs,
                                kDefaultTestParams,
                                "invalid xml>",
                                -1,
@@ -538,6 +542,35 @@
   EXPECT_EQ(post_str.find("o:event"), string::npos);
 }
 
+TEST(OmahaRequestActionTest, FormatUpdateCheckPrevVersionOutputTest) {
+  vector<char> post_data;
+  NiceMock<PrefsMock> prefs;
+  EXPECT_CALL(prefs, GetString(kPrefsPreviousVersion, _))
+      .WillOnce(DoAll(SetArgumentPointee<1>(string("1.2.3.4")), Return(true)));
+  EXPECT_CALL(prefs, SetString(kPrefsPreviousVersion, ""))
+      .WillOnce(Return(true));
+  ASSERT_FALSE(TestUpdateCheck(&prefs,
+                               kDefaultTestParams,
+                               "invalid xml>",
+                               -1,
+                               kActionCodeOmahaRequestXMLParseError,
+                               NULL,  // response
+                               &post_data));
+  // convert post_data to string
+  string post_str(&post_data[0], post_data.size());
+  EXPECT_NE(post_str.find("        <o:ping a=\"-1\" r=\"-1\"></o:ping>\n"
+                          "        <o:updatecheck></o:updatecheck>\n"),
+            string::npos);
+  EXPECT_NE(post_str.find("hardware_class=\"OEM MODEL 09235 7471\""),
+            string::npos);
+  string prev_version_event = StringPrintf(
+      "        <o:event eventtype=\"%d\" eventresult=\"%d\" "
+      "previousversion=\"1.2.3.4\"></o:event>\n",
+      OmahaEvent::kTypeUpdateComplete,
+      OmahaEvent::kResultSuccessReboot);
+  EXPECT_NE(post_str.find(prev_version_event), string::npos);
+}
+
 TEST(OmahaRequestActionTest, FormatSuccessEventOutputTest) {
   vector<char> post_data;
   TestEvent(kDefaultTestParams,
diff --git a/prefs.cc b/prefs.cc
index 223fc9b..1bde4cd 100644
--- a/prefs.cc
+++ b/prefs.cc
@@ -19,6 +19,7 @@
 const char kPrefsLastActivePingDay[] = "last-active-ping-day";
 const char kPrefsLastRollCallPingDay[] = "last-roll-call-ping-day";
 const char kPrefsManifestMetadataSize[] = "manifest-metadata-size";
+const char kPrefsPreviousVersion[] = "previous-version";
 const char kPrefsResumedUpdateFailures[] = "resumed-update-failures";
 const char kPrefsUpdateCheckResponseHash[] = "update-check-response-hash";
 const char kPrefsUpdateStateNextDataOffset[] = "update-state-next-data-offset";
diff --git a/prefs_interface.h b/prefs_interface.h
index 81aa770..8d07dde 100644
--- a/prefs_interface.h
+++ b/prefs_interface.h
@@ -13,6 +13,7 @@
 extern const char kPrefsLastActivePingDay[];
 extern const char kPrefsLastRollCallPingDay[];
 extern const char kPrefsManifestMetadataSize[];
+extern const char kPrefsPreviousVersion[];
 extern const char kPrefsResumedUpdateFailures[];
 extern const char kPrefsUpdateCheckResponseHash[];
 extern const char kPrefsUpdateStateNextDataOffset[];
diff --git a/update_attempter.cc b/update_attempter.cc
index 8139687..3ea1c18 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -289,6 +289,7 @@
   if (code == kActionCodeSuccess) {
     utils::WriteFile(kUpdateCompletedMarker, "", 0);
     prefs_->SetInt64(kPrefsDeltaUpdateFailures, 0);
+    prefs_->SetString(kPrefsPreviousVersion, omaha_request_params_.app_version);
     DeltaPerformer::ResetUpdateProgress(prefs_, false);
     SetStatusAndNotify(UPDATE_STATUS_UPDATED_NEED_REBOOT);