buffet: Move WebServClient out of libweave

libweave now relies on platform specific implementation of
weave::HttpServer.

BUG=brillo:1252
TEST='FEATURES=test emerge-gizmo buffet'

Change-Id: I8f2c2f119699ff5096a74dc05948db0eaf108ea3
Reviewed-on: https://chromium-review.googlesource.com/290142
Commit-Queue: Vitaly Buka <vitalybuka@chromium.org>
Trybot-Ready: Vitaly Buka <vitalybuka@chromium.org>
Tested-by: Vitaly Buka <vitalybuka@chromium.org>
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/buffet.gyp b/buffet/buffet.gyp
index c72b4d8..400bf44 100644
--- a/buffet/buffet.gyp
+++ b/buffet/buffet.gyp
@@ -35,6 +35,7 @@
         'manager.cc',
         'peerd_client.cc',
         'shill_client.cc',
+        'webserv_client.cc',
         '../libweave/src/base_api_handler.cc',
         '../libweave/src/buffet_config.cc',
         '../libweave/src/commands/cloud_command_proxy.cc',
@@ -67,7 +68,6 @@
         '../libweave/src/privet/privet_types.cc',
         '../libweave/src/privet/publisher.cc',
         '../libweave/src/privet/security_manager.cc',
-        '../libweave/src/privet/webserv_client.cc',
         '../libweave/src/privet/wifi_bootstrap_manager.cc',
         '../libweave/src/privet/wifi_ssid_generator.cc',
         '../libweave/src/registration_status.cc',
diff --git a/buffet/manager.cc b/buffet/manager.cc
index 9df8caa..047c121 100644
--- a/buffet/manager.cc
+++ b/buffet/manager.cc
@@ -27,6 +27,7 @@
 #include "buffet/dbus_conversion.h"
 #include "buffet/peerd_client.h"
 #include "buffet/shill_client.h"
+#include "buffet/webserv_client.h"
 #include "weave/enum_to_string.h"
 
 using chromeos::dbus_utils::AsyncEventSequencer;
@@ -57,12 +58,15 @@
 void Manager::Start(const weave::Device::Options& options,
                     const std::set<std::string>& device_whitelist,
                     AsyncEventSequencer* sequencer) {
-  peerd_client_.reset(new PeerdClient{dbus_object_.GetBus()});
   shill_client_.reset(new ShillClient{dbus_object_.GetBus(), device_whitelist});
+  if (!options.disable_privet) {
+    peerd_client_.reset(new PeerdClient{dbus_object_.GetBus()});
+    web_serv_client_.reset(new WebServClient{dbus_object_.GetBus(), sequencer});
+  }
 
   device_ = weave::Device::Create();
-  device_->Start(options, peerd_client_.get(), shill_client_.get(),
-                 &dbus_object_, sequencer);
+  device_->Start(options, shill_client_.get(), peerd_client_.get(),
+                 web_serv_client_.get(), &dbus_object_, sequencer);
 
   command_dispatcher_.reset(new DBusCommandDispacher{
       dbus_object_.GetObjectManager(), device_->GetCommands()});
diff --git a/buffet/manager.h b/buffet/manager.h
index c0037e9..880d753 100644
--- a/buffet/manager.h
+++ b/buffet/manager.h
@@ -33,6 +33,7 @@
 class DBusCommandDispacher;
 class PeerdClient;
 class ShillClient;
+class WebServClient;
 
 template<typename... Types>
 using DBusMethodResponsePtr =
@@ -117,8 +118,9 @@
   org::chromium::Buffet::ManagerAdaptor dbus_adaptor_{this};
   chromeos::dbus_utils::DBusObject dbus_object_;
 
-  std::unique_ptr<PeerdClient> peerd_client_;
   std::unique_ptr<ShillClient> shill_client_;
+  std::unique_ptr<PeerdClient> peerd_client_;
+  std::unique_ptr<WebServClient> web_serv_client_;
   std::unique_ptr<weave::Device> device_;
   std::unique_ptr<DBusCommandDispacher> command_dispatcher_;
 
diff --git a/buffet/webserv_client.cc b/buffet/webserv_client.cc
new file mode 100644
index 0000000..2ae5910
--- /dev/null
+++ b/buffet/webserv_client.cc
@@ -0,0 +1,135 @@
+// Copyright 2015 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "buffet/webserv_client.h"
+
+#include <memory>
+#include <string>
+
+#include <libwebserv/protocol_handler.h>
+#include <libwebserv/request.h>
+#include <libwebserv/response.h>
+#include <libwebserv/server.h>
+
+#include "buffet/dbus_constants.h"
+
+namespace buffet {
+
+namespace {
+
+class RequestImpl : public weave::HttpServer::Request {
+ public:
+  explicit RequestImpl(std::unique_ptr<libwebserv::Request> request)
+      : request_{std::move(request)} {}
+  ~RequestImpl() override {}
+
+  // HttpServer::Request implementation.
+  const std::string& GetPath() const override { return request_->GetPath(); }
+  std::string GetFirstHeader(const std::string& name) const override {
+    return request_->GetFirstHeader(name);
+  }
+  const std::vector<uint8_t>& GetData() const override {
+    return request_->GetData();
+  }
+
+ private:
+  std::unique_ptr<libwebserv::Request> request_;
+
+  DISALLOW_COPY_AND_ASSIGN(RequestImpl);
+};
+
+}  // namespace
+
+WebServClient::~WebServClient() {
+  web_server_->Disconnect();
+}
+
+void WebServClient::AddOnStateChangedCallback(
+    const OnStateChangedCallback& callback) {
+  on_state_changed_callbacks_.push_back(callback);
+  callback.Run(*this);
+}
+
+void WebServClient::AddRequestHandler(const std::string& path_prefix,
+                                      const OnRequestCallback& callback) {
+  web_server_->GetDefaultHttpHandler()->AddHandlerCallback(
+      path_prefix, "", base::Bind(&WebServClient::OnRequest,
+                                  weak_ptr_factory_.GetWeakPtr(), callback));
+  web_server_->GetDefaultHttpsHandler()->AddHandlerCallback(
+      path_prefix, "", base::Bind(&WebServClient::OnRequest,
+                                  weak_ptr_factory_.GetWeakPtr(), callback));
+}
+
+uint16_t WebServClient::GetHttpPort() const {
+  return http_port_;
+}
+
+uint16_t WebServClient::GetHttpsPort() const {
+  return https_port_;
+}
+
+const chromeos::Blob& WebServClient::GetHttpsCertificateFingerprint() const {
+  return certificate_;
+}
+
+WebServClient::WebServClient(
+    const scoped_refptr<dbus::Bus>& bus,
+    chromeos::dbus_utils::AsyncEventSequencer* sequencer) {
+  web_server_.reset(new libwebserv::Server);
+  web_server_->OnProtocolHandlerConnected(
+      base::Bind(&WebServClient::OnProtocolHandlerConnected,
+                 weak_ptr_factory_.GetWeakPtr()));
+  web_server_->OnProtocolHandlerDisconnected(
+      base::Bind(&WebServClient::OnProtocolHandlerDisconnected,
+                 weak_ptr_factory_.GetWeakPtr()));
+
+  web_server_->Connect(bus, buffet::kServiceName,
+                       sequencer->GetHandler("Server::Connect failed.", true),
+                       base::Bind(&base::DoNothing),
+                       base::Bind(&base::DoNothing));
+}
+
+void WebServClient::OnRequest(const OnRequestCallback& callback,
+                              std::unique_ptr<libwebserv::Request> request,
+                              std::unique_ptr<libwebserv::Response> response) {
+  callback.Run(
+      RequestImpl{std::move(request)},
+      base::Bind(&WebServClient::OnResponse, weak_ptr_factory_.GetWeakPtr(),
+                 base::Passed(&response)));
+}
+
+void WebServClient::OnResponse(std::unique_ptr<libwebserv::Response> response,
+                               int status_code,
+                               const std::string& data,
+                               const std::string& mime_type) {
+  response->Reply(status_code, data.data(), data.size(), mime_type);
+}
+
+void WebServClient::OnProtocolHandlerConnected(
+    libwebserv::ProtocolHandler* protocol_handler) {
+  if (protocol_handler->GetName() == libwebserv::ProtocolHandler::kHttp) {
+    http_port_ = *protocol_handler->GetPorts().begin();
+  } else if (protocol_handler->GetName() ==
+             libwebserv::ProtocolHandler::kHttps) {
+    https_port_ = *protocol_handler->GetPorts().begin();
+    certificate_ = protocol_handler->GetCertificateFingerprint();
+  }
+  for (const auto& cb : on_state_changed_callbacks_)
+    cb.Run(*this);
+}
+
+void WebServClient::OnProtocolHandlerDisconnected(
+    libwebserv::ProtocolHandler* protocol_handler) {
+  if (protocol_handler->GetName() == libwebserv::ProtocolHandler::kHttp) {
+    http_port_ = 0;
+  } else if (protocol_handler->GetName() ==
+             libwebserv::ProtocolHandler::kHttps) {
+    https_port_ = 0;
+    certificate_.clear();
+  }
+  for (const auto& cb : on_state_changed_callbacks_)
+    cb.Run(*this);
+}
+
+}  // namespace buffet
diff --git a/buffet/webserv_client.h b/buffet/webserv_client.h
new file mode 100644
index 0000000..cbfbf23
--- /dev/null
+++ b/buffet/webserv_client.h
@@ -0,0 +1,81 @@
+// Copyright 2015 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BUFFET_WEBSERV_CLIENT_H_
+#define BUFFET_WEBSERV_CLIENT_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <base/memory/weak_ptr.h>
+
+#include "weave/http_server.h"
+
+namespace dbus {
+class Bus;
+}
+
+namespace chromeos {
+namespace dbus_utils {
+class AsyncEventSequencer;
+}
+}
+
+namespace libwebserv {
+class ProtocolHandler;
+class Request;
+class Response;
+class Server;
+}
+
+namespace buffet {
+
+// Wrapper around libwebserv that implements HttpServer interface.
+class WebServClient : public weave::HttpServer {
+ public:
+  WebServClient(const scoped_refptr<dbus::Bus>& bus,
+                chromeos::dbus_utils::AsyncEventSequencer* sequencer);
+  ~WebServClient() override;
+
+  // HttpServer implementation.
+  void AddOnStateChangedCallback(
+      const OnStateChangedCallback& callback) override;
+  void AddRequestHandler(const std::string& path_prefix,
+                         const OnRequestCallback& callback) override;
+  uint16_t GetHttpPort() const override;
+  uint16_t GetHttpsPort() const override;
+  const chromeos::Blob& GetHttpsCertificateFingerprint() const override;
+
+ private:
+  void OnRequest(const OnRequestCallback& callback,
+                 std::unique_ptr<libwebserv::Request> request,
+                 std::unique_ptr<libwebserv::Response> response);
+
+  void OnResponse(std::unique_ptr<libwebserv::Response> response,
+                  int status_code,
+                  const std::string& data,
+                  const std::string& mime_type);
+
+  void OnProtocolHandlerConnected(
+      libwebserv::ProtocolHandler* protocol_handler);
+
+  void OnProtocolHandlerDisconnected(
+      libwebserv::ProtocolHandler* protocol_handler);
+
+  uint16_t http_port_{0};
+  uint16_t https_port_{0};
+  chromeos::Blob certificate_;
+
+  std::vector<OnStateChangedCallback> on_state_changed_callbacks_;
+
+  std::unique_ptr<libwebserv::Server> web_server_;
+
+  base::WeakPtrFactory<WebServClient> weak_ptr_factory_{this};
+  DISALLOW_COPY_AND_ASSIGN(WebServClient);
+};
+
+}  // namespace buffet
+
+#endif  // BUFFET_WEBSERV_CLIENT_H_