Add the session id attribute to the component updater protocol.

Bug: 809760
Change-Id: Ia34c70ba563cdd11fbff2d545533c66df9a94601
Reviewed-on: https://chromium-review.googlesource.com/904945
Reviewed-by: Joshua Pawlicki <[email protected]>
Commit-Queue: Sorin Jianu <[email protected]>
Cr-Commit-Position: refs/heads/master@{#535103}
diff --git a/components/update_client/component.cc b/components/update_client/component.cc
index daf40fe..54887e51 100644
--- a/components/update_client/component.cc
+++ b/components/update_client/component.cc
@@ -177,6 +177,10 @@
   return update_context_.config;
 }
 
+std::string Component::session_id() const {
+  return update_context_.session_id;
+}
+
 void Component::Handle(CallbackHandleComplete callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(state_);
diff --git a/components/update_client/component.h b/components/update_client/component.h
index e577a8e7..d44e39a 100644
--- a/components/update_client/component.h
+++ b/components/update_client/component.h
@@ -122,6 +122,8 @@
 
   scoped_refptr<Configurator> config() const;
 
+  std::string session_id() const;
+
  private:
   friend class FakePingManagerImpl;
   friend class UpdateCheckerTest;
diff --git a/components/update_client/ping_manager_unittest.cc b/components/update_client/ping_manager_unittest.cc
index f7ce932..9f487ff 100644
--- a/components/update_client/ping_manager_unittest.cc
+++ b/components/update_client/ping_manager_unittest.cc
@@ -97,6 +97,7 @@
                   "<event eventtype=\"3\" eventresult=\"1\" "
                   "previousversion=\"1.0\" nextversion=\"2.0\"/></app>"))
         << interceptor->GetRequestsAsString();
+    EXPECT_NE(string::npos, interceptor->GetRequests()[0].find(" sessionid="));
     interceptor->Reset();
   }
 
diff --git a/components/update_client/protocol_builder.cc b/components/update_client/protocol_builder.cc
index b7e98e8..6613b26 100644
--- a/components/update_client/protocol_builder.cc
+++ b/components/update_client/protocol_builder.cc
@@ -202,6 +202,7 @@
 }
 
 std::string BuildProtocolRequest(
+    const std::string& session_id,
     const std::string& prod_id,
     const std::string& browser_version,
     const std::string& channel,
@@ -222,22 +223,27 @@
   // Constant information for this updater.
   base::StringAppendF(&request, "dedup=\"cr\" acceptformat=\"crx2,crx3\" ");
 
+  // Sesssion id and request id
+  DCHECK(!session_id.empty());
+  DCHECK(!base::StartsWith(session_id, "{", base::CompareCase::SENSITIVE));
+  DCHECK(!base::EndsWith(session_id, "}", base::CompareCase::SENSITIVE));
+  base::StringAppendF(&request, "sessionid=\"{%s}\" requestid=\"{%s}\" ",
+                      session_id.c_str(), base::GenerateGUID().c_str());
+
   // Chrome version and platform information.
-  base::StringAppendF(
-      &request,
-      "version=\"%s-%s\" prodversion=\"%s\" "
-      "requestid=\"{%s}\" lang=\"%s\" updaterchannel=\"%s\" prodchannel=\"%s\" "
-      "os=\"%s\" arch=\"%s\" nacl_arch=\"%s\"",
-      prod_id.c_str(),  // "version" is prefixed by prod_id.
-      browser_version.c_str(),
-      browser_version.c_str(),            // "prodversion"
-      base::GenerateGUID().c_str(),       // "requestid"
-      lang.c_str(),                       // "lang"
-      channel.c_str(),                    // "updaterchannel"
-      channel.c_str(),                    // "prodchannel"
-      UpdateQueryParams::GetOS(),         // "os"
-      UpdateQueryParams::GetArch(),       // "arch"
-      UpdateQueryParams::GetNaclArch());  // "nacl_arch"
+  base::StringAppendF(&request,
+                      "version=\"%s-%s\" prodversion=\"%s\" "
+                      "lang=\"%s\" updaterchannel=\"%s\" prodchannel=\"%s\" "
+                      "os=\"%s\" arch=\"%s\" nacl_arch=\"%s\"",
+                      prod_id.c_str(),  // "version" is prefixed by prod_id.
+                      browser_version.c_str(),
+                      browser_version.c_str(),            // "prodversion"
+                      lang.c_str(),                       // "lang"
+                      channel.c_str(),                    // "updaterchannel"
+                      channel.c_str(),                    // "prodchannel"
+                      UpdateQueryParams::GetOS(),         // "os"
+                      UpdateQueryParams::GetArch(),       // "arch"
+                      UpdateQueryParams::GetNaclArch());  // "nacl_arch"
 #if defined(OS_WIN)
   const bool is_wow64(base::win::OSInfo::GetInstance()->wow64_status() ==
                       base::win::OSInfo::WOW64_ENABLED);
@@ -296,6 +302,7 @@
 
 std::string BuildUpdateCheckRequest(
     const Configurator& config,
+    const std::string& session_id,
     const std::vector<std::string>& ids_checked,
     const IdToComponentPtrMap& components,
     PersistedData* metadata,
@@ -386,7 +393,7 @@
 
   // Include the updater state in the update check request.
   return BuildProtocolRequest(
-      config.GetProdId(), config.GetBrowserVersion().GetString(),
+      session_id, config.GetProdId(), config.GetBrowserVersion().GetString(),
       config.GetChannel(), config.GetLang(), config.GetOSLongName(),
       config.GetDownloadPreference(), app_elements, additional_attributes,
       updater_state_attributes);
@@ -405,10 +412,11 @@
   app.append("</app>");
 
   // The ping request does not include any updater state.
-  return BuildProtocolRequest(
-      config.GetProdId(), config.GetBrowserVersion().GetString(),
-      config.GetChannel(), config.GetLang(), config.GetOSLongName(),
-      config.GetDownloadPreference(), app, "", nullptr);
+  return BuildProtocolRequest(component.session_id(), config.GetProdId(),
+                              config.GetBrowserVersion().GetString(),
+                              config.GetChannel(), config.GetLang(),
+                              config.GetOSLongName(),
+                              config.GetDownloadPreference(), app, "", nullptr);
 }
 
 }  // namespace update_client
diff --git a/components/update_client/protocol_builder.h b/components/update_client/protocol_builder.h
index 969126e..15ffcf4 100644
--- a/components/update_client/protocol_builder.h
+++ b/components/update_client/protocol_builder.h
@@ -35,6 +35,7 @@
 // </request>
 std::string BuildUpdateCheckRequest(
     const Configurator& config,
+    const std::string& session_id,
     const std::vector<std::string>& ids_checked,
     const IdToComponentPtrMap& components,
     PersistedData* metadata,
@@ -82,7 +83,8 @@
 // For example:
 //
 // <?xml version="1.0" encoding="UTF-8"?>
-// <request protocol="3.0" version="chrome-32.0.1.0" prodversion="32.0.1.0"
+// <request protocol="3.0" sessionid="{D505492F-95FE-4F90-8253-AEA75772DCC4}"
+//        version="chrome-32.0.1.0" prodversion="32.0.1.0"
 //        requestid="{7383396D-B4DD-46E1-9104-AAC6B918E792}"
 //        updaterchannel="canary" arch="x86" nacl_arch="x86-64"
 //        ADDITIONAL ATTRIBUTES>
@@ -101,6 +103,7 @@
 // parameter specifying that an <updater> element is serialized as part of
 // the request.
 std::string BuildProtocolRequest(
+    const std::string& session_id,
     const std::string& prod_id,
     const std::string& browser_version,
     const std::string& channel,
diff --git a/components/update_client/protocol_builder_unittest.cc b/components/update_client/protocol_builder_unittest.cc
index 1a6dc5a..1a979fe 100644
--- a/components/update_client/protocol_builder_unittest.cc
+++ b/components/update_client/protocol_builder_unittest.cc
@@ -15,30 +15,36 @@
 
 namespace update_client {
 
-TEST(UpdateClientUtils, BuildProtocolRequest_ProdIdVersion) {
-  // Verifies that |prod_id| and |version| are serialized.
-  const string request = BuildProtocolRequest("some_prod_id", "1.0", "", "", "",
-                                              "", "", "", nullptr);
-  EXPECT_NE(string::npos, request.find(" version=\"some_prod_id-1.0\" "));
+TEST(BuildProtocolRequest, SessionIdProdIdVersion) {
+  // Verifies that |session_id|, |prod_id| and |version| are serialized.
+  const string request = BuildProtocolRequest(
+      "15160585-8ADE-4D3C-839B-1281A6035D1F", "some_prod_id", "1.0", "", "", "",
+      "", "", "", nullptr);
+  EXPECT_NE(
+      string::npos,
+      request.find(" sessionid=\"{15160585-8ADE-4D3C-839B-1281A6035D1F}\" "));
+  EXPECT_NE(string::npos,
+            request.find(" version=\"some_prod_id-1.0\" prodversion=\"1.0\" "));
 }
 
-TEST(UpdateClientUtils, BuildProtocolRequest_DownloadPreference) {
+TEST(BuildProtocolRequest, DownloadPreference) {
   // Verifies that an empty |download_preference| is not serialized.
   const string request_no_dlpref =
-      BuildProtocolRequest("", "", "", "", "", "", "", "", nullptr);
+      BuildProtocolRequest("1", "", "", "", "", "", "", "", "", nullptr);
   EXPECT_EQ(string::npos, request_no_dlpref.find(" dlpref="));
 
   // Verifies that |download_preference| is serialized.
-  const string request_with_dlpref =
-      BuildProtocolRequest("", "", "", "", "", "some pref", "", "", nullptr);
+  const string request_with_dlpref = BuildProtocolRequest(
+      "1", "", "", "", "", "", "some pref", "", "", nullptr);
   EXPECT_NE(string::npos, request_with_dlpref.find(" dlpref=\"some pref\""));
 }
 
-TEST(UpdateClientUtils, BuildProtocolRequestUpdaterStateAttributes) {
+TEST(BuildProtocolRequest, UpdaterStateAttributes) {
   // When no updater state is provided, then check that the elements and
   // attributes related to the updater state are not serialized.
   std::string request =
-      BuildProtocolRequest("", "", "", "", "", "", "", "", nullptr).c_str();
+      BuildProtocolRequest("1", "", "", "", "", "", "", "", "", nullptr)
+          .c_str();
   EXPECT_EQ(std::string::npos, request.find(" domainjoined"));
   EXPECT_EQ(std::string::npos, request.find("<updater"));
 
@@ -52,7 +58,7 @@
   attributes["autoupdatecheckenabled"] = "0";
   attributes["updatepolicy"] = "-1";
   request = BuildProtocolRequest(
-      "", "", "", "", "", "", "", "",
+      "1", "", "", "", "", "", "", "", "",
       std::make_unique<UpdaterState::Attributes>(attributes));
   EXPECT_NE(std::string::npos, request.find(" domainjoined=\"1\""));
   const std::string updater_element =
diff --git a/components/update_client/update_checker.cc b/components/update_client/update_checker.cc
index 1bd3915..098b6f26 100644
--- a/components/update_client/update_checker.cc
+++ b/components/update_client/update_checker.cc
@@ -55,7 +55,8 @@
   ~UpdateCheckerImpl() override;
 
   // Overrides for UpdateChecker.
-  void CheckForUpdates(const std::vector<std::string>& ids_checked,
+  void CheckForUpdates(const std::string& session_id,
+                       const std::vector<std::string>& ids_checked,
                        const IdToComponentPtrMap& components,
                        const std::string& additional_attributes,
                        bool enabled_component_updates,
@@ -63,7 +64,8 @@
 
  private:
   void ReadUpdaterStateAttributes();
-  void CheckForUpdatesHelper(const IdToComponentPtrMap& components,
+  void CheckForUpdatesHelper(const std::string& session_id,
+                             const IdToComponentPtrMap& components,
                              const std::string& additional_attributes,
                              bool enabled_component_updates);
   void OnRequestSenderComplete(const IdToComponentPtrMap& components,
@@ -98,6 +100,7 @@
 }
 
 void UpdateCheckerImpl::CheckForUpdates(
+    const std::string& session_id,
     const std::vector<std::string>& ids_checked,
     const IdToComponentPtrMap& components,
     const std::string& additional_attributes,
@@ -113,8 +116,9 @@
       base::BindOnce(&UpdateCheckerImpl::ReadUpdaterStateAttributes,
                      base::Unretained(this)),
       base::BindOnce(&UpdateCheckerImpl::CheckForUpdatesHelper,
-                     base::Unretained(this), base::ConstRef(components),
-                     additional_attributes, enabled_component_updates));
+                     base::Unretained(this), session_id,
+                     base::ConstRef(components), additional_attributes,
+                     enabled_component_updates));
 }
 
 // This function runs on the blocking pool task runner.
@@ -132,6 +136,7 @@
 }
 
 void UpdateCheckerImpl::CheckForUpdatesHelper(
+    const std::string& session_id,
     const IdToComponentPtrMap& components,
     const std::string& additional_attributes,
     bool enabled_component_updates) {
@@ -144,8 +149,9 @@
   request_sender_ = std::make_unique<RequestSender>(config_);
   request_sender_->Send(
       config_->EnabledCupSigning(),
-      BuildUpdateCheckRequest(*config_, ids_checked_, components, metadata_,
-                              additional_attributes, enabled_component_updates,
+      BuildUpdateCheckRequest(*config_, session_id, ids_checked_, components,
+                              metadata_, additional_attributes,
+                              enabled_component_updates,
                               updater_state_attributes_),
       urls,
       base::BindOnce(&UpdateCheckerImpl::OnRequestSenderComplete,
diff --git a/components/update_client/update_checker.h b/components/update_client/update_checker.h
index 0f2cb3ed..ce5928f 100644
--- a/components/update_client/update_checker.h
+++ b/components/update_client/update_checker.h
@@ -37,7 +37,8 @@
   // XML attribute string.
   // On completion, the state of |components| is mutated as required by the
   // server response received.
-  virtual void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+  virtual void CheckForUpdates(const std::string& session_id,
+                               const std::vector<std::string>& ids_to_check,
                                const IdToComponentPtrMap& components,
                                const std::string& additional_attributes,
                                bool enabled_component_updates,
diff --git a/components/update_client/update_checker_unittest.cc b/components/update_client/update_checker_unittest.cc
index 107d906..91bb1b40 100644
--- a/components/update_client/update_checker_unittest.cc
+++ b/components/update_client/update_checker_unittest.cc
@@ -238,8 +238,8 @@
   component->crx_component_.installer_attributes["ap"] = "some_ap";
 
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "extra=\"params\"",
-      true,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "extra=\"params\"", true,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -270,6 +270,9 @@
       string::npos,
       request.find(" version=\"fake_prodid-30.0\" prodversion=\"30.0\" "));
 
+  // Tests that there is a sessionid attribute.
+  EXPECT_NE(string::npos, request.find(" sessionid="));
+
   // Sanity check the arguments of the callback after parsing.
   EXPECT_EQ(0, error_);
 
@@ -306,7 +309,8 @@
   component->crx_component_.installer_attributes["ap"] = std::string(257, 'a');
 
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", true,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", true,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
 
@@ -332,7 +336,8 @@
   components[kUpdateItemId] = MakeComponent();
 
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", true,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", true,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
 
@@ -360,7 +365,8 @@
   auto& component = components[kUpdateItemId];
 
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", true,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", true,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -386,8 +392,8 @@
   components[kUpdateItemId] = MakeComponent();
 
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "extra=\"params\"",
-      true,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "extra=\"params\"", true,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
 
@@ -414,7 +420,8 @@
   const auto& component = components[kUpdateItemId];
 
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", true,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", true,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
 
@@ -454,7 +461,8 @@
   component->crx_component_.requires_network_encryption = true;
 
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", true,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", true,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -479,16 +487,16 @@
   // Do two update-checks.
   activity_data_service_->SetDaysSinceLastRollCall(kUpdateItemId, 5);
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "extra=\"params\"",
-      true,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "extra=\"params\"", true,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
 
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "extra=\"params\"",
-      true,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "extra=\"params\"", true,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -519,8 +527,8 @@
   activity_data_service_->SetActiveBit(kUpdateItemId, true);
   activity_data_service_->SetDaysSinceLastActive(kUpdateItemId, 10);
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "extra=\"params\"",
-      true,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "extra=\"params\"", true,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -531,8 +539,8 @@
   activity_data_service_->SetActiveBit(kUpdateItemId, true);
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "extra=\"params\"",
-      true,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "extra=\"params\"", true,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -542,8 +550,8 @@
 
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "extra=\"params\"",
-      true,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "extra=\"params\"", true,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -574,7 +582,8 @@
   EXPECT_TRUE(post_interceptor_->ExpectRequest(
       new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", false,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", false,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -586,7 +595,8 @@
   EXPECT_TRUE(post_interceptor_->ExpectRequest(
       new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", false,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", false,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -599,7 +609,8 @@
   EXPECT_TRUE(post_interceptor_->ExpectRequest(
       new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", false,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", false,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -612,7 +623,8 @@
   EXPECT_TRUE(post_interceptor_->ExpectRequest(
       new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", false,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", false,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -633,7 +645,8 @@
   EXPECT_TRUE(post_interceptor_->ExpectRequest(
       new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", false,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", false,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -647,7 +660,8 @@
   EXPECT_TRUE(post_interceptor_->ExpectRequest(
       new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", false,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", false,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -660,7 +674,8 @@
   EXPECT_TRUE(post_interceptor_->ExpectRequest(
       new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", false,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", false,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -674,7 +689,8 @@
   EXPECT_TRUE(post_interceptor_->ExpectRequest(
       new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", false,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", false,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -688,7 +704,8 @@
   EXPECT_TRUE(post_interceptor_->ExpectRequest(
       new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", false,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", false,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -706,7 +723,8 @@
   EXPECT_TRUE(post_interceptor_->ExpectRequest(
       new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", false,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", false,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -742,7 +760,8 @@
   EXPECT_TRUE(post_interceptor_->ExpectRequest(
       new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", false,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", false,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -761,7 +780,8 @@
   EXPECT_TRUE(post_interceptor_->ExpectRequest(
       new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", false,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", false,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -780,7 +800,8 @@
   EXPECT_TRUE(post_interceptor_->ExpectRequest(
       new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", true,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", true,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -799,7 +820,8 @@
   EXPECT_TRUE(post_interceptor_->ExpectRequest(
       new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", true,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", true,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -822,7 +844,8 @@
   auto& component = components[kUpdateItemId];
 
   update_checker_->CheckForUpdates(
-      std::vector<std::string>{kUpdateItemId}, components, "", true,
+      update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+      components, "", true,
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
diff --git a/components/update_client/update_client_unittest.cc b/components/update_client/update_client_unittest.cc
index 57fefe0..56d4a15b 100644
--- a/components/update_client/update_client_unittest.cc
+++ b/components/update_client/update_client_unittest.cc
@@ -240,11 +240,13 @@
       return std::make_unique<FakeUpdateChecker>();
     }
 
-    void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
                          const IdToComponentPtrMap& components,
                          const std::string& additional_attributes,
                          bool enabled_component_updates,
                          UpdateCheckCallback update_check_callback) override {
+      EXPECT_FALSE(session_id.empty());
       EXPECT_TRUE(enabled_component_updates);
       EXPECT_EQ(1u, ids_to_check.size());
       const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
@@ -350,7 +352,8 @@
       return std::make_unique<FakeUpdateChecker>();
     }
 
-    void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
                          const IdToComponentPtrMap& components,
                          const std::string& additional_attributes,
                          bool enabled_component_updates,
@@ -376,7 +379,7 @@
         </app>
       </response>
       */
-
+      EXPECT_FALSE(session_id.empty());
       EXPECT_TRUE(enabled_component_updates);
       EXPECT_EQ(2u, ids_to_check.size());
 
@@ -560,7 +563,8 @@
       return std::make_unique<FakeUpdateChecker>();
     }
 
-    void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
                          const IdToComponentPtrMap& components,
                          const std::string& additional_attributes,
                          bool enabled_component_updates,
@@ -600,6 +604,7 @@
         </app>
       </response>
       */
+      EXPECT_FALSE(session_id.empty());
       EXPECT_TRUE(enabled_component_updates);
       EXPECT_EQ(2u, ids_to_check.size());
 
@@ -828,7 +833,8 @@
       return std::make_unique<FakeUpdateChecker>();
     }
 
-    void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
                          const IdToComponentPtrMap& components,
                          const std::string& additional_attributes,
                          bool enabled_component_updates,
@@ -869,6 +875,7 @@
       </response>
       */
 
+      EXPECT_FALSE(session_id.empty());
       EXPECT_TRUE(enabled_component_updates);
       EXPECT_EQ(2u, ids_to_check.size());
 
@@ -1095,11 +1102,14 @@
       return std::make_unique<FakeUpdateChecker>();
     }
 
-    void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
                          const IdToComponentPtrMap& components,
                          const std::string& additional_attributes,
                          bool enabled_component_updates,
                          UpdateCheckCallback update_check_callback) override {
+      EXPECT_FALSE(session_id.empty());
+
       static int num_call = 0;
       ++num_call;
 
@@ -1421,7 +1431,8 @@
       return std::make_unique<FakeUpdateChecker>();
     }
 
-    void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
                          const IdToComponentPtrMap& components,
                          const std::string& additional_attributes,
                          bool enabled_component_updates,
@@ -1447,6 +1458,8 @@
         </app>
       </response>
       */
+      EXPECT_FALSE(session_id.empty());
+
       const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
       EXPECT_EQ(id, ids_to_check[0]);
       EXPECT_EQ(1u, components.count(id));
@@ -1608,11 +1621,14 @@
       return std::make_unique<FakeUpdateChecker>();
     }
 
-    void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
                          const IdToComponentPtrMap& components,
                          const std::string& additional_attributes,
                          bool enabled_component_updates,
                          UpdateCheckCallback update_check_callback) override {
+      EXPECT_FALSE(session_id.empty());
+
       static int num_call = 0;
       ++num_call;
 
@@ -1909,11 +1925,13 @@
       return std::make_unique<FakeUpdateChecker>();
     }
 
-    void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
                          const IdToComponentPtrMap& components,
                          const std::string& additional_attributes,
                          bool enabled_component_updates,
                          UpdateCheckCallback update_check_callback) override {
+      EXPECT_FALSE(session_id.empty());
       EXPECT_TRUE(enabled_component_updates);
       EXPECT_EQ(1u, ids_to_check.size());
       const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
@@ -2020,7 +2038,8 @@
       return std::make_unique<FakeUpdateChecker>();
     }
 
-    void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
                          const IdToComponentPtrMap& components,
                          const std::string& additional_attributes,
                          bool enabled_component_updates,
@@ -2046,6 +2065,7 @@
         </app>
       </response>
       */
+      EXPECT_FALSE(session_id.empty());
       EXPECT_TRUE(enabled_component_updates);
       EXPECT_EQ(1u, ids_to_check.size());
 
@@ -2211,11 +2231,13 @@
       return std::make_unique<FakeUpdateChecker>();
     }
 
-    void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
                          const IdToComponentPtrMap& components,
                          const std::string& additional_attributes,
                          bool enabled_component_updates,
                          UpdateCheckCallback update_check_callback) override {
+      EXPECT_FALSE(session_id.empty());
       EXPECT_TRUE(enabled_component_updates);
       EXPECT_EQ(1u, ids_to_check.size());
       const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
@@ -2315,11 +2337,14 @@
       return std::make_unique<FakeUpdateChecker>();
     }
 
-    void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
                          const IdToComponentPtrMap& components,
                          const std::string& additional_attributes,
                          bool enabled_component_updates,
-                         UpdateCheckCallback update_check_callback) override {}
+                         UpdateCheckCallback update_check_callback) override {
+      NOTREACHED();
+    }
   };
 
   class FakeCrxDownloader : public CrxDownloader {
@@ -2364,11 +2389,14 @@
       return nullptr;
     }
 
-    void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
                          const IdToComponentPtrMap& components,
                          const std::string& additional_attributes,
                          bool enabled_component_updates,
-                         UpdateCheckCallback update_check_callback) override {}
+                         UpdateCheckCallback update_check_callback) override {
+      NOTREACHED();
+    }
   };
 
   class FakeCrxDownloader : public CrxDownloader {
@@ -2462,11 +2490,14 @@
       return std::make_unique<FakeUpdateChecker>();
     }
 
-    void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
                          const IdToComponentPtrMap& components,
                          const std::string& additional_attributes,
                          bool enabled_component_updates,
                          UpdateCheckCallback update_check_callback) override {
+      EXPECT_FALSE(session_id.empty());
+
       static int num_call = 0;
       ++num_call;
 
@@ -2635,7 +2666,8 @@
       return std::make_unique<FakeUpdateChecker>();
     }
 
-    void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
                          const IdToComponentPtrMap& components,
                          const std::string& additional_attributes,
                          bool enabled_component_updates,
@@ -2680,8 +2712,8 @@
       // configurator instance, persists its value in the corresponding
       // update context, and propagates it down to each of the update actions,
       // and further down to the UpdateChecker instance.
+      EXPECT_FALSE(session_id.empty());
       EXPECT_FALSE(enabled_component_updates);
-
       EXPECT_EQ(2u, ids_to_check.size());
 
       {
@@ -2881,11 +2913,13 @@
       return std::make_unique<FakeUpdateChecker>();
     }
 
-    void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
                          const IdToComponentPtrMap& components,
                          const std::string& additional_attributes,
                          bool enabled_component_updates,
                          UpdateCheckCallback update_check_callback) override {
+      EXPECT_FALSE(session_id.empty());
       EXPECT_TRUE(enabled_component_updates);
       EXPECT_EQ(1u, ids_to_check.size());
       const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
@@ -2961,7 +2995,8 @@
       return std::make_unique<FakeUpdateChecker>();
     }
 
-    void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
                          const IdToComponentPtrMap& components,
                          const std::string& additional_attributes,
                          bool enabled_component_updates,
@@ -2989,6 +3024,7 @@
         </app>
       </response>
       */
+      EXPECT_FALSE(session_id.empty());
       EXPECT_TRUE(enabled_component_updates);
       EXPECT_EQ(1u, ids_to_check.size());
 
@@ -3122,7 +3158,8 @@
       return std::make_unique<FakeUpdateChecker>();
     }
 
-    void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
                          const IdToComponentPtrMap& components,
                          const std::string& additional_attributes,
                          bool enabled_component_updates,
@@ -3141,6 +3178,7 @@
         </app>
       </response>
       */
+      EXPECT_FALSE(session_id.empty());
       EXPECT_EQ(1u, ids_to_check.size());
       const std::string id = "gjpmebpgbhcamgdgjcmnjfhggjpgcimm";
       EXPECT_EQ(id, ids_to_check[0]);
diff --git a/components/update_client/update_engine.cc b/components/update_client/update_engine.cc
index e30cedd..fac4278 100644
--- a/components/update_client/update_engine.cc
+++ b/components/update_client/update_engine.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/guid.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
@@ -39,7 +40,8 @@
       crx_data_callback(std::move(crx_data_callback)),
       notify_observers_callback(notify_observers_callback),
       callback(std::move(callback)),
-      crx_downloader_factory(crx_downloader_factory) {
+      crx_downloader_factory(crx_downloader_factory),
+      session_id(base::GenerateGUID()) {
   for (const auto& id : ids)
     components.insert(
         std::make_pair(id, std::make_unique<Component>(*this, id)));
@@ -157,8 +159,9 @@
       update_checker_factory_(config_, metadata_.get());
 
   update_context->update_checker->CheckForUpdates(
-      update_context->ids, update_context->components,
-      config_->ExtraRequestParams(), update_context->enabled_component_updates,
+      update_context->session_id, update_context->ids,
+      update_context->components, config_->ExtraRequestParams(),
+      update_context->enabled_component_updates,
       base::BindOnce(&UpdateEngine::UpdateCheckDone, base::Unretained(this),
                      it));
 }
diff --git a/components/update_client/update_engine.h b/components/update_client/update_engine.h
index 9e37892..bcd4f02 100644
--- a/components/update_client/update_engine.h
+++ b/components/update_client/update_engine.h
@@ -118,6 +118,7 @@
 };
 
 // TODO(sorin): consider making this a ref counted type.
+// Describes a group of components which are installed or updated together.
 struct UpdateContext {
   UpdateContext(
       const scoped_refptr<Configurator>& config,
@@ -173,6 +174,9 @@
   // is handling the next component in the queue.
   base::TimeDelta next_update_delay;
 
+  // The session id this context is associated with.
+  const std::string session_id;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(UpdateContext);
 };