libweave: 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-link buffet`

Change-Id: If5801de9008bced3babbc91c9f7e8bec8fe075a6
Reviewed-on: https://chromium-review.googlesource.com/285776
Trybot-Ready: Alex Vakulenko <avakulenko@chromium.org>
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
Reviewed-by: Vitaly Buka <vitalybuka@chromium.org>
Commit-Queue: Vitaly Buka <vitalybuka@chromium.org>
diff --git a/libweave/src/device_registration_info.cc b/libweave/src/device_registration_info.cc
index d88b00a..1b5a07d 100644
--- a/libweave/src/device_registration_info.cc
+++ b/libweave/src/device_registration_info.cc
@@ -865,6 +865,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) {
@@ -1040,8 +1046,14 @@
   notification_channel_starting_ = false;
   pull_channel_->UpdatePullInterval(config_->backup_polling_period());
   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() {
@@ -1078,9 +1090,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/libweave/src/device_registration_info.h b/libweave/src/device_registration_info.h
index afb64d1..4dff0a5 100644
--- a/libweave/src/device_registration_info.h
+++ b/libweave/src/device_registration_info.h
@@ -254,6 +254,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);