buffet: When XMPP channel created, poll the server for commands once

As soon as we get confirmation that XMPP channel is established, we will
rely on push notification for command delivery from then on. However we
need to make sure there have been no new commands queued since the last
time we polled the server and before XMPPP channel was created.

So, poll the server once more after we have established XMPP channel,
to make sure there is no command pending.

BUG=brillo:1244
TEST=`FEATURES=test emerge-storm buffet`

Change-Id: I496917d96ae5c9cae1b9c7715f6b2b39c3068606
Reviewed-on: https://chromium-review.googlesource.com/285921
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
Reviewed-by: Aaron Kemp <kemp@google.com>
Tested-by: Aaron Kemp <kemp@google.com>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/device_registration_info.cc b/buffet/device_registration_info.cc
index c4c0112..2a4ab60 100644
--- a/buffet/device_registration_info.cc
+++ b/buffet/device_registration_info.cc
@@ -881,6 +881,12 @@
       nullptr, base::Bind(&HandleFetchCommandsResult, on_success), on_failure);
 }
 
+void DeviceRegistrationInfo::FetchAndPublishCommands() {
+  FetchCommands(base::Bind(&DeviceRegistrationInfo::PublishCommands,
+                           weak_factory_.GetWeakPtr()),
+                base::Bind(&IgnoreCloudError));
+}
+
 void DeviceRegistrationInfo::ProcessInitialCommandList(
     const base::ListValue& commands) {
   for (const base::Value* command : commands) {
@@ -1057,8 +1063,14 @@
   pull_channel_->UpdatePullInterval(
       base::TimeDelta::FromMilliseconds(config_->backup_polling_period_ms()));
   current_notification_channel_ = primary_notification_channel_.get();
-  UpdateDeviceResource(base::Bind(&base::DoNothing),
-                       base::Bind(&IgnoreCloudError));
+  // Once we update the device resource with the new notification channel,
+  // do the last poll for commands from the server, to make sure we have the
+  // latest command baseline and no other commands have been queued between
+  // the moment of the last poll and the time we successfully told the server
+  // to send new commands over the new notification channel.
+  UpdateDeviceResource(
+      base::Bind(&DeviceRegistrationInfo::FetchAndPublishCommands, AsWeakPtr()),
+      base::Bind(&IgnoreCloudError));
 }
 
 void DeviceRegistrationInfo::OnDisconnected() {
@@ -1096,9 +1108,7 @@
   // If the command was too big to be delivered over a notification channel,
   // or OnCommandCreated() was initiated from the Pull notification,
   // perform a manual command fetch from the server here.
-  FetchCommands(base::Bind(&DeviceRegistrationInfo::PublishCommands,
-                           weak_factory_.GetWeakPtr()),
-                base::Bind(&IgnoreCloudError));
+  FetchAndPublishCommands();
 }
 
 void DeviceRegistrationInfo::OnDeviceDeleted(const std::string& device_id) {
diff --git a/buffet/device_registration_info.h b/buffet/device_registration_info.h
index 5a57966..ce8c0d5 100644
--- a/buffet/device_registration_info.h
+++ b/buffet/device_registration_info.h
@@ -252,6 +252,10 @@
   void PublishCommands(const base::ListValue& commands);
   void PublishCommand(const base::DictionaryValue& command);
 
+  // Helper function to pull the pending command list from the server using
+  // FetchCommands() and make them available on D-Bus with PublishCommands().
+  void FetchAndPublishCommands();
+
   void PublishStateUpdates();
   void OnPublishStateSuccess(StateChangeQueueInterface::UpdateID update_id,
                              const base::DictionaryValue& reply);