buffet: Integrate the XmppClient into buffet

TEST=FEATURES=test emerge-${BOARD} buffet
BUG=brillo:95

Change-Id: Ife3abac34db8e331d936891cfe4f3e937ecfb49c
Reviewed-on: https://chromium-review.googlesource.com/250462
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Nathan Bullock <nathanbullock@google.com>
Tested-by: Nathan Bullock <nathanbullock@google.com>
diff --git a/buffet/device_registration_info.cc b/buffet/device_registration_info.cc
index a0b684e..b44498d 100644
--- a/buffet/device_registration_info.cc
+++ b/buffet/device_registration_info.cc
@@ -326,12 +326,24 @@
                            "Access token unavailable");
     return false;
   }
-
   access_token_expiration_ = base::Time::Now() +
                              base::TimeDelta::FromSeconds(expires_in);
-
   LOG(INFO) << "Access token is refreshed for additional " << expires_in
             << " seconds.";
+
+  // If no MessageLoop assume we're in unittests.
+  if (base::MessageLoop::current()) {
+    std::unique_ptr<XmppConnection> connection(new XmppConnection());
+    CHECK(connection->Initialize()) << "Failed to connect to XMPP server";
+    xmpp_client_.reset(new XmppClient(device_robot_account_, access_token_,
+                                      std::move(connection)));
+    CHECK(base::MessageLoopForIO::current()->WatchFileDescriptor(
+        xmpp_client_->GetFileDescriptor(), true,
+        base::MessageLoopForIO::WATCH_READ, &fd_watcher_, this))
+        << "Failed to watch XMPP file descriptor";
+    xmpp_client_->StartStream();
+  }
+
   return true;
 }
 
diff --git a/buffet/device_registration_info.h b/buffet/device_registration_info.h
index 31cc508..96979dc 100644
--- a/buffet/device_registration_info.h
+++ b/buffet/device_registration_info.h
@@ -13,12 +13,14 @@
 #include <base/callback.h>
 #include <base/macros.h>
 #include <base/memory/weak_ptr.h>
+#include <base/message_loop/message_loop.h>
 #include <base/time/time.h>
 #include <chromeos/data_encoding.h>
 #include <chromeos/errors/error.h>
 #include <chromeos/http/http_transport.h>
 
 #include "buffet/storage_interface.h"
+#include "buffet/xmpp/xmpp_client.h"
 
 namespace base {
 class Value;
@@ -38,7 +40,7 @@
 extern const char kErrorDomainGCDServer[];
 
 // The DeviceRegistrationInfo class represents device registration information.
-class DeviceRegistrationInfo {
+class DeviceRegistrationInfo : public base::MessageLoopForIO::Watcher {
  public:
   // This is a helper class for unit testing.
   class TestHelper;
@@ -50,7 +52,17 @@
       const std::shared_ptr<chromeos::http::Transport>& transport,
       const std::shared_ptr<StorageInterface>& state_store);
 
-  ~DeviceRegistrationInfo();
+  ~DeviceRegistrationInfo() override;
+
+  void OnFileCanReadWithoutBlocking(int fd) override {
+    if (xmpp_client_ && xmpp_client_->GetFileDescriptor() == fd) {
+      xmpp_client_->Read();
+    }
+  }
+
+  void OnFileCanWriteWithoutBlocking(int fd) override {
+    LOG(FATAL) << "No write watcher is configured";
+  }
 
   // Returns the authorization HTTP header that can be used to talk
   // to GCD server for authenticated device communication.
@@ -179,6 +191,9 @@
   std::unique_ptr<base::DictionaryValue> BuildDeviceResource(
       chromeos::ErrorPtr* error);
 
+  std::unique_ptr<XmppClient> xmpp_client_;
+  base::MessageLoopForIO::FileDescriptorWatcher fd_watcher_;
+
   std::string client_id_;
   std::string client_secret_;
   std::string api_key_;
@@ -187,17 +202,17 @@
   std::string device_robot_account_;
   std::string oauth_url_;
   std::string service_url_;
-
-  // Transient data
-  std::string access_token_;
-  base::Time access_token_expiration_;
-  std::string ticket_id_;
   std::string device_kind_;
   std::string name_;
   std::string display_name_;
   std::string description_;
   std::string location_;
 
+  // Transient data
+  std::string access_token_;
+  base::Time access_token_expiration_;
+  std::string ticket_id_;
+
   // HTTP transport used for communications.
   std::shared_ptr<chromeos::http::Transport> transport_;
   // Serialization interface to save and load device registration info.
diff --git a/buffet/xmpp/xmpp_connection.cc b/buffet/xmpp/xmpp_connection.cc
index 8799493..38e99e3 100644
--- a/buffet/xmpp/xmpp_connection.cc
+++ b/buffet/xmpp/xmpp_connection.cc
@@ -56,12 +56,12 @@
     return false;
   }
   *msg = std::string{buffer, static_cast<size_t>(bytes)};
-  VLOG(1) << "READ: (" << msg->size() << ")" << *msg;
+  LOG(INFO) << "Read: (" << msg->size() << ")" << *msg;
   return true;
 }
 
 bool XmppConnection::Write(const std::string& msg) const {
-  VLOG(1) << "WRITE: (" << msg.size() << ")" << msg;
+  LOG(INFO) << "Write: (" << msg.size() << ")" << msg;
   if (!base::WriteFileDescriptor(fd_, msg.c_str(), msg.size())) {
     LOG(WARNING) << "Failure writing";
     return false;