Queue pending state updates while offline

This avoids having to wait for them to timeout after coming back
online.

Change-Id: Ic0ae6662653f6232e1bc60258dfe7ddd06986231
diff --git a/src/device_registration_info.cc b/src/device_registration_info.cc
index 751e530..3ee71ea 100644
--- a/src/device_registration_info.cc
+++ b/src/device_registration_info.cc
@@ -272,6 +272,12 @@
                  weak_factory_.GetWeakPtr()));
   state_manager_->AddChangedCallback(base::Bind(
       &DeviceRegistrationInfo::OnStateChanged, weak_factory_.GetWeakPtr()));
+
+  if (network_) {
+    network_->AddConnectionChangedCallback(base::Bind(
+        &DeviceRegistrationInfo::OnNetworkStateChanged,
+        weak_factory_.GetWeakPtr()));
+  }
 }
 
 DeviceRegistrationInfo::~DeviceRegistrationInfo() = default;
@@ -682,6 +688,13 @@
   if (!VerifyRegistrationCredentials(&error))
     return data->callback.Run({}, std::move(error));
 
+  if (network_ &&
+      network_->GetConnectionState() != provider::Network::State::kOnline) {
+    LOG(INFO) << "Cloud request delayed because not online";
+    offline_cloud_requests_.push_back(data);
+    return;
+  }
+
   if (cloud_backoff_entry_->ShouldRejectRequest()) {
     VLOG(1) << "Cloud request delayed for "
             << cloud_backoff_entry_->GetTimeUntilRelease()
@@ -1192,6 +1205,20 @@
   PublishStateUpdates();
 }
 
+void DeviceRegistrationInfo::OnNetworkStateChanged() {
+  if (network_ &&
+      network_->GetConnectionState() == provider::Network::State::kOnline &&
+      !offline_cloud_requests_.empty()) {
+    LOG(INFO) << "Sending queued cloud requests: "
+              << offline_cloud_requests_.size();
+    for (const auto &data : offline_cloud_requests_) {
+      SendCloudRequest(data);
+    }
+    offline_cloud_requests_.clear();
+    return;
+  }
+}
+
 void DeviceRegistrationInfo::OnConnected(const std::string& channel_name) {
   LOG(INFO) << "Notification channel successfully established over "
             << channel_name;
diff --git a/src/device_registration_info.h b/src/device_registration_info.h
index 1399b37..bc87ec9 100644
--- a/src/device_registration_info.h
+++ b/src/device_registration_info.h
@@ -257,6 +257,9 @@
   void OnCommandDefsChanged();
   void OnStateChanged();
 
+  // Callback for network connectivity changes.
+  void OnNetworkStateChanged();
+
   // Overrides from NotificationDelegate.
   void OnConnected(const std::string& channel_name) override;
   void OnDisconnected() override;
@@ -343,6 +346,8 @@
 
   std::vector<Device::GcdStateChangedCallback> gcd_state_changed_callbacks_;
 
+  std::vector<std::shared_ptr<const CloudRequestData>> offline_cloud_requests_;
+
   base::WeakPtrFactory<DeviceRegistrationInfo> weak_factory_{this};
   DISALLOW_COPY_AND_ASSIGN(DeviceRegistrationInfo);
 };
diff --git a/src/weave_unittest.cc b/src/weave_unittest.cc
index c2f1e8f..67c3c97 100644
--- a/src/weave_unittest.cc
+++ b/src/weave_unittest.cc
@@ -307,6 +307,7 @@
 
 TEST_F(WeaveTest, StartMinimal) {
   InitConfigStore();
+  InitNetwork();
   device_ = weave::Device::Create(&config_store_, &task_runner_, &http_client_,
                                   &network_, nullptr, nullptr, &wifi_, nullptr);
 }