Hide Server implementation

Hide the DBus details from the server interface.  In the future, we
will guard the DBus specific headers and static factory behind ifdefs and
add support for a binder alternative.

Bug: 25932908
Test: `mmma -j16 system/webservd`

Change-Id: Iceb73eb3470ff5130195802dd1962eb8361d3f0e
diff --git a/libwebserv/Android.mk b/libwebserv/Android.mk
index 17d800d..50235bc 100644
--- a/libwebserv/Android.mk
+++ b/libwebserv/Android.mk
@@ -25,6 +25,7 @@
 LOCAL_SHARED_LIBRARIES := libwebservd-client-internal
 LOCAL_SRC_FILES := \
     dbus_bindings/org.chromium.WebServer.RequestHandler.dbus-xml \
+    dbus_server.cc \
     protocol_handler.cc \
     request.cc \
     request_handler_callback.cc \
diff --git a/libwebserv/dbus_server.cc b/libwebserv/dbus_server.cc
new file mode 100644
index 0000000..091b02f
--- /dev/null
+++ b/libwebserv/dbus_server.cc
@@ -0,0 +1,247 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <libwebserv/dbus_server.h>
+
+#include <tuple>
+#include <vector>
+
+#include <libwebserv/protocol_handler.h>
+#include <libwebserv/request_impl.h>
+
+#include "dbus_bindings/org.chromium.WebServer.RequestHandler.h"
+#include "webservd/dbus-proxies.h"
+
+namespace libwebserv {
+
+class DBusServer::RequestHandler final
+    : public org::chromium::WebServer::RequestHandlerInterface {
+ public:
+  explicit RequestHandler(DBusServer* server) : server_{server} {}
+  bool ProcessRequest(
+      brillo::ErrorPtr* error,
+      const std::tuple<std::string, std::string, std::string, std::string,
+                       std::string>& in_request_info,
+      const std::vector<std::tuple<std::string, std::string>>& in_headers,
+      const std::vector<std::tuple<bool, std::string, std::string>>& in_params,
+      const std::vector<std::tuple<int32_t, std::string, std::string,
+                                   std::string, std::string>>& in_files,
+      const dbus::FileDescriptor& in_body) override;
+
+ private:
+  DBusServer* server_{nullptr};
+  DISALLOW_COPY_AND_ASSIGN(RequestHandler);
+};
+
+bool DBusServer::RequestHandler::ProcessRequest(
+    brillo::ErrorPtr* error,
+    const std::tuple<std::string, std::string, std::string, std::string,
+                     std::string>& in_request_info,
+    const std::vector<std::tuple<std::string, std::string>>& in_headers,
+    const std::vector<std::tuple<bool, std::string, std::string>>& in_params,
+    const std::vector<std::tuple<int32_t, std::string, std::string, std::string,
+                                 std::string>>& in_files,
+    const dbus::FileDescriptor& in_body) {
+  std::string protocol_handler_id = std::get<0>(in_request_info);
+  std::string request_handler_id = std::get<1>(in_request_info);
+  std::string request_id = std::get<2>(in_request_info);
+  std::string url = std::get<3>(in_request_info);
+  std::string method = std::get<4>(in_request_info);
+  ProtocolHandler* protocol_handler =
+      server_->GetProtocolHandlerByID(protocol_handler_id);
+  if (!protocol_handler) {
+    brillo::Error::AddToPrintf(error, FROM_HERE,
+                               brillo::errors::dbus::kDomain,
+                               DBUS_ERROR_FAILED,
+                               "Unknown protocol handler '%s'",
+                               protocol_handler_id.c_str());
+    return false;
+  }
+  std::unique_ptr<RequestImpl> request{
+    new RequestImpl{protocol_handler, url, method}};
+  // Convert request data into format required by the Request object.
+  for (const auto& tuple : in_params) {
+    if (std::get<0>(tuple))
+      request->post_data_.emplace(std::get<1>(tuple), std::get<2>(tuple));
+    else
+      request->get_data_.emplace(std::get<1>(tuple), std::get<2>(tuple));
+  }
+
+  for (const auto& tuple : in_headers)
+    request->headers_.emplace(std::get<0>(tuple), std::get<1>(tuple));
+
+  for (const auto& tuple : in_files) {
+    request->file_info_.emplace(
+        std::get<1>(tuple),  // field_name
+        std::unique_ptr<FileInfo>{new FileInfo{
+            protocol_handler,
+            std::get<0>(tuple),     // file_id
+            request_id,
+            std::get<2>(tuple),     // file_name
+            std::get<3>(tuple),     // content_type
+            std::get<4>(tuple)}});  // transfer_encoding
+  }
+
+  request->raw_data_fd_ = base::File(dup(in_body.value()));
+  CHECK(request->raw_data_fd_.IsValid());
+
+  return protocol_handler->ProcessRequest(protocol_handler_id,
+                                          request_handler_id,
+                                          request_id,
+                                          std::move(request),
+                                          error);
+}
+
+DBusServer::DBusServer()
+    : request_handler_{new RequestHandler{this}},
+      dbus_adaptor_{new org::chromium::WebServer::RequestHandlerAdaptor{
+          request_handler_.get()}} {}
+
+void DBusServer::Connect(
+    const scoped_refptr<dbus::Bus>& bus,
+    const std::string& service_name,
+    const brillo::dbus_utils::AsyncEventSequencer::CompletionAction& cb,
+    const base::Closure& on_server_online,
+    const base::Closure& on_server_offline) {
+  service_name_ = service_name;
+  dbus_object_.reset(new brillo::dbus_utils::DBusObject{
+      nullptr, bus, dbus_adaptor_->GetObjectPath()});
+  dbus_adaptor_->RegisterWithDBusObject(dbus_object_.get());
+  dbus_object_->RegisterAsync(cb);
+  on_server_online_ = on_server_online;
+  on_server_offline_ = on_server_offline;
+  object_manager_.reset(new org::chromium::WebServer::ObjectManagerProxy{bus});
+  object_manager_->SetServerAddedCallback(
+      base::Bind(&DBusServer::Online, base::Unretained(this)));
+  object_manager_->SetServerRemovedCallback(
+      base::Bind(&DBusServer::Offline, base::Unretained(this)));
+  object_manager_->SetProtocolHandlerAddedCallback(
+      base::Bind(&DBusServer::ProtocolHandlerAdded, base::Unretained(this)));
+  object_manager_->SetProtocolHandlerRemovedCallback(
+      base::Bind(&DBusServer::ProtocolHandlerRemoved, base::Unretained(this)));
+}
+
+void DBusServer::Disconnect() {
+  on_server_offline_.Reset();
+  on_server_online_.Reset();
+  protocol_handlers_ids_.clear();
+  protocol_handlers_names_.clear();
+  // Release D-Bus object manager proxy after all the dependent maps are freed
+  // (e.g. |protocol_handlers_names_| contains pointers to ProtocolHandlerProxy,
+  // instances of which are owned by the D-Bus object manager).
+  object_manager_.reset();
+  dbus_object_.reset();
+}
+
+void DBusServer::Online(
+    org::chromium::WebServer::ServerProxyInterface* server) {
+  VLOG(1) << "Web server is on-line.";
+  proxy_ = server;
+  if (!on_server_online_.is_null())
+    on_server_online_.Run();
+}
+
+bool DBusServer::IsConnected() const {
+  return proxy_ != nullptr;
+}
+
+void DBusServer::Offline(const dbus::ObjectPath& object_path) {
+  if (!on_server_offline_.is_null())
+    on_server_offline_.Run();
+  proxy_ = nullptr;
+  VLOG(1) << "Web server is off-line.";
+}
+
+void DBusServer::ProtocolHandlerAdded(
+    org::chromium::WebServer::ProtocolHandlerProxyInterface* handler) {
+  VLOG(1) << "Server-side protocol handler with ID '" << handler->id()
+          << "' is on-line (" << handler->name() << ")";
+
+  protocol_handler_id_map_.emplace(handler->GetObjectPath(), handler->id());
+  ProtocolHandler* registered_handler = GetProtocolHandler(handler->name());
+  if (registered_handler) {
+    protocol_handlers_ids_.emplace(handler->id(), registered_handler);
+    registered_handler->Connect(handler);
+    if (!on_protocol_handler_connected_.is_null())
+      on_protocol_handler_connected_.Run(registered_handler);
+  }
+}
+
+void DBusServer::ProtocolHandlerRemoved(const dbus::ObjectPath& object_path) {
+  auto p = protocol_handler_id_map_.find(object_path);
+  if (p == protocol_handler_id_map_.end())
+    return;
+
+  VLOG(1) << "Server-side protocol handler with ID '" << p->second
+          << "' is off-line.";
+
+  ProtocolHandler* registered_handler = GetProtocolHandlerByID(p->second);
+  if (registered_handler) {
+    if (!on_protocol_handler_disconnected_.is_null())
+      on_protocol_handler_disconnected_.Run(registered_handler);
+    registered_handler->Disconnect(object_path);
+    protocol_handlers_ids_.erase(p->second);
+  }
+
+  protocol_handler_id_map_.erase(p);
+}
+
+ProtocolHandler* DBusServer::GetProtocolHandler(const std::string& name) {
+  auto p = protocol_handlers_names_.find(name);
+  if (p == protocol_handlers_names_.end()) {
+    VLOG(1) << "Creating a client-side instance of web server's protocol "
+            << "handler with name '" << name << "'";
+    p = protocol_handlers_names_.emplace(
+        name,
+        std::unique_ptr<ProtocolHandler>{new ProtocolHandler{name, this}})
+            .first;
+  }
+  return p->second.get();
+}
+
+ProtocolHandler* DBusServer::GetDefaultHttpHandler() {
+  return GetProtocolHandler(ProtocolHandler::kHttp);
+}
+
+ProtocolHandler* DBusServer::GetDefaultHttpsHandler() {
+  return GetProtocolHandler(ProtocolHandler::kHttps);
+}
+
+ProtocolHandler* DBusServer::GetProtocolHandlerByID(const std::string& id) const {
+  auto p = protocol_handlers_ids_.find(id);
+  if (p == protocol_handlers_ids_.end()) {
+    LOG(ERROR) << "Unable to locate protocol handler with ID '" << id << "'";
+    return nullptr;
+  }
+  return p->second;
+}
+
+void DBusServer::OnProtocolHandlerConnected(
+    const base::Callback<void(ProtocolHandler*)>& callback) {
+  on_protocol_handler_connected_ = callback;
+}
+
+void DBusServer::OnProtocolHandlerDisconnected(
+    const base::Callback<void(ProtocolHandler*)>& callback) {
+  on_protocol_handler_disconnected_ = callback;
+}
+
+base::TimeDelta DBusServer::GetDefaultRequestTimeout() const {
+  int timeout_seconds = proxy_ ? proxy_->default_request_timeout() : -1;
+  if (timeout_seconds <= 0)
+    return base::TimeDelta::Max();
+  return base::TimeDelta::FromSeconds(timeout_seconds);
+}
+
+}  // namespace libwebserv
diff --git a/libwebserv/dbus_server.h b/libwebserv/dbus_server.h
new file mode 100644
index 0000000..36bcdcb
--- /dev/null
+++ b/libwebserv/dbus_server.h
@@ -0,0 +1,145 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef WEBSERVER_LIBWEBSERV_DBUS_SERVER_H_
+#define WEBSERVER_LIBWEBSERV_DBUS_SERVER_H_
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include <base/macros.h>
+#include <dbus/bus.h>
+#include <brillo/dbus/async_event_sequencer.h>
+#include <brillo/dbus/dbus_object.h>
+
+#include "libwebserv/export.h"
+#include "libwebserv/request_handler_interface.h"
+#include "libwebserv/server.h"
+
+namespace org {
+namespace chromium {
+namespace WebServer {
+
+class ObjectManagerProxy;
+class ProtocolHandlerProxyInterface;
+class RequestHandlerAdaptor;
+class ServerProxyInterface;
+
+}  // namespace WebServer
+}  // namespace chromium
+}  // namespace org
+
+namespace libwebserv {
+
+class LIBWEBSERV_PRIVATE DBusServer : public Server {
+ public:
+  DBusServer();
+  ~DBusServer() override = default;
+
+  // Establish a connection to the system webserver.
+  // |service_name| is the well known D-Bus name of the client's process, used
+  // to expose a callback D-Bus object the web server calls back with incoming
+  // requests.
+  // |on_server_online| and |on_server_offline| will notify the caller when the
+  // server comes up and down.
+  // Note that we can Connect() even before the webserver attaches to D-Bus,
+  // and appropriate state will be built up when the webserver appears on D-Bus.
+  void Connect(
+      const scoped_refptr<dbus::Bus>& bus,
+      const std::string& service_name,
+      const brillo::dbus_utils::AsyncEventSequencer::CompletionAction& cb,
+      const base::Closure& on_server_online,
+      const base::Closure& on_server_offline);
+
+  ProtocolHandler* GetDefaultHttpHandler() override;
+
+  ProtocolHandler* GetDefaultHttpsHandler() override;
+  ProtocolHandler* GetProtocolHandler(const std::string& name) override;
+
+  bool IsConnected() const override;
+
+  void OnProtocolHandlerConnected(
+      const base::Callback<void(ProtocolHandler*)>& callback) override;
+
+  void OnProtocolHandlerDisconnected(
+      const base::Callback<void(ProtocolHandler*)>& callback) override;
+
+  base::TimeDelta GetDefaultRequestTimeout() const override;
+
+ private:
+  friend class ProtocolHandler;
+  class RequestHandler;
+
+  void Disconnect();
+
+  // Handler invoked when a connection is established to web server daemon.
+  void Online(org::chromium::WebServer::ServerProxyInterface* server);
+
+  // Handler invoked when the web server daemon connection is dropped.
+  void Offline(const dbus::ObjectPath& object_path);
+
+  // Handler invoked when a new protocol handler D-Bus proxy object becomes
+  // available.
+  void ProtocolHandlerAdded(
+      org::chromium::WebServer::ProtocolHandlerProxyInterface* handler);
+
+  // Handler invoked when a protocol handler D-Bus proxy object disappears.
+  void ProtocolHandlerRemoved(
+      const dbus::ObjectPath& object_path);
+
+  // Looks up a protocol handler by ID. If not found, returns nullptr.
+  ProtocolHandler* GetProtocolHandlerByID(
+      const std::string& id) const;
+
+  // Private implementation of D-Bus RequestHandlerInterface called by the web
+  // server daemon whenever a new request is available to be processed.
+  std::unique_ptr<RequestHandler> request_handler_;
+  // D-Bus object adaptor for RequestHandlerInterface.
+  std::unique_ptr<org::chromium::WebServer::RequestHandlerAdaptor>
+      dbus_adaptor_;
+  // D-Bus object to handler registration of RequestHandlerInterface.
+  std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object_;
+
+  // A mapping of protocol handler name to the associated object.
+  std::map<std::string, std::unique_ptr<ProtocolHandler>>
+      protocol_handlers_names_;
+  // A mapping of protocol handler IDs to the associated object.
+  std::map<std::string, ProtocolHandler*> protocol_handlers_ids_;
+  // A map between D-Bus object path of protocol handler and remote protocol
+  // handler ID.
+  std::map<dbus::ObjectPath, std::string> protocol_handler_id_map_;
+
+  // User-specified callbacks for server and protocol handler life-time events.
+  base::Closure on_server_online_;
+  base::Closure on_server_offline_;
+  base::Callback<void(ProtocolHandler*)> on_protocol_handler_connected_;
+  base::Callback<void(ProtocolHandler*)> on_protocol_handler_disconnected_;
+
+  // D-Bus object manager proxy that receives notification of web server
+  // daemon's D-Bus object creation and destruction.
+  std::unique_ptr<org::chromium::WebServer::ObjectManagerProxy> object_manager_;
+
+  // D-Bus proxy for the web server main object.
+  org::chromium::WebServer::ServerProxyInterface* proxy_{nullptr};
+
+  // D-Bus service name used by the daemon hosting this object.
+  std::string service_name_;
+
+  DISALLOW_COPY_AND_ASSIGN(DBusServer);
+};
+
+}  // namespace libwebserv
+
+#endif  // WEBSERVER_LIBWEBSERV_DBUS_SERVER_H_
diff --git a/libwebserv/protocol_handler.cc b/libwebserv/protocol_handler.cc
index 76d1606..8c50d47 100644
--- a/libwebserv/protocol_handler.cc
+++ b/libwebserv/protocol_handler.cc
@@ -22,10 +22,10 @@
 #include <brillo/streams/stream_utils.h>
 
 #include "dbus_bindings/org.chromium.WebServer.RequestHandler.h"
+#include "libwebserv/dbus_server.h"
 #include "libwebserv/request.h"
 #include "libwebserv/request_handler_callback.h"
 #include "libwebserv/response_impl.h"
-#include "libwebserv/server.h"
 #include "webservd/dbus-proxies.h"
 
 namespace libwebserv {
@@ -58,7 +58,7 @@
 const char ProtocolHandler::kHttp[] = "http";
 const char ProtocolHandler::kHttps[] = "https";
 
-ProtocolHandler::ProtocolHandler(const std::string& name, Server* server)
+ProtocolHandler::ProtocolHandler(const std::string& name, DBusServer* server)
     : name_{name}, server_{server} {
 }
 
diff --git a/libwebserv/protocol_handler.h b/libwebserv/protocol_handler.h
index 2e1c748..2c2dee5 100644
--- a/libwebserv/protocol_handler.h
+++ b/libwebserv/protocol_handler.h
@@ -44,7 +44,7 @@
 
 namespace libwebserv {
 
-class Server;
+class DBusServer;
 class Request;
 
 // Wrapper around a protocol handler (e.g. HTTP or HTTPs).
@@ -53,7 +53,7 @@
 // information.
 class LIBWEBSERV_EXPORT ProtocolHandler final {
  public:
-  ProtocolHandler(const std::string& name, Server* server);
+  ProtocolHandler(const std::string& name, DBusServer* server);
   ~ProtocolHandler();
 
   // Returns true if the protocol handler object is connected to the web server
@@ -126,7 +126,7 @@
 
  private:
   friend class FileInfo;
-  friend class Server;
+  friend class DBusServer;
   friend class ResponseImpl;
 
   using ProtocolHandlerProxyInterface =
@@ -139,12 +139,12 @@
     std::unique_ptr<RequestHandlerInterface> handler;
   };
 
-  // Called by the Server class when the D-Bus proxy object gets connected
+  // Called by the DBusServer class when the D-Bus proxy object gets connected
   // to the web server daemon.
-
   LIBWEBSERV_PRIVATE void Connect(ProtocolHandlerProxyInterface* proxy);
-  // Called by the Server class when the D-Bus proxy object gets disconnected
-  // from the web server daemon.
+
+  // Called by the DBusServer class when the D-Bus proxy object gets
+  // disconnected from the web server daemon.
   LIBWEBSERV_PRIVATE void Disconnect(const dbus::ObjectPath& object_path);
 
   // Asynchronous callbacks to handle successful or failed request handler
@@ -156,7 +156,7 @@
   LIBWEBSERV_PRIVATE void AddHandlerError(int handler_id,
                                           brillo::Error* error);
 
-  // Called by Server when an incoming request is dispatched.
+  // Called by DBusServer when an incoming request is dispatched.
   LIBWEBSERV_PRIVATE bool ProcessRequest(const std::string& protocol_handler_id,
                                          const std::string& remote_handler_id,
                                          const std::string& request_id,
@@ -187,7 +187,7 @@
   // Protocol Handler name.
   std::string name_;
   // Back reference to the server object.
-  Server* server_{nullptr};
+  DBusServer* server_{nullptr};
   // Handler data map. The key is the client-facing request handler ID returned
   // by AddHandler() when registering the handler.
   std::map<int, HandlerMapEntry> request_handlers_;
diff --git a/libwebserv/request.h b/libwebserv/request.h
index f1f7043..ce8d82b 100644
--- a/libwebserv/request.h
+++ b/libwebserv/request.h
@@ -49,7 +49,7 @@
       const base::Callback<void(brillo::Error*)>& error_callback) const;
 
  private:
-  friend class Server;
+  friend class DBusServer;
 
   LIBWEBSERV_PRIVATE FileInfo(ProtocolHandler* handler,
                               int file_id,
diff --git a/libwebserv/request_impl.h b/libwebserv/request_impl.h
index 4d99873..2c172ec 100644
--- a/libwebserv/request_impl.h
+++ b/libwebserv/request_impl.h
@@ -31,7 +31,7 @@
   brillo::StreamPtr GetDataStream() override;
 
  private:
-  friend class Server;
+  friend class DBusServer;
 
   LIBWEBSERV_PRIVATE RequestImpl(ProtocolHandler* handler,
                                  const std::string& url,
diff --git a/libwebserv/server.cc b/libwebserv/server.cc
index d806eaa..9f567b3 100644
--- a/libwebserv/server.cc
+++ b/libwebserv/server.cc
@@ -14,232 +14,22 @@
 
 #include <libwebserv/server.h>
 
-#include <tuple>
-#include <vector>
+#include <libwebserv/dbus_server.h>
 
-#include <libwebserv/protocol_handler.h>
-#include <libwebserv/request_impl.h>
-
-#include "dbus_bindings/org.chromium.WebServer.RequestHandler.h"
-#include "webservd/dbus-proxies.h"
+using std::unique_ptr;
 
 namespace libwebserv {
 
-class Server::RequestHandler final
-    : public org::chromium::WebServer::RequestHandlerInterface {
- public:
-  explicit RequestHandler(Server* server) : server_{server} {}
-  bool ProcessRequest(
-      brillo::ErrorPtr* error,
-      const std::tuple<std::string, std::string, std::string, std::string,
-                       std::string>& in_request_info,
-      const std::vector<std::tuple<std::string, std::string>>& in_headers,
-      const std::vector<std::tuple<bool, std::string, std::string>>& in_params,
-      const std::vector<std::tuple<int32_t, std::string, std::string,
-                                   std::string, std::string>>& in_files,
-      const dbus::FileDescriptor& in_body) override;
-
- private:
-  Server* server_{nullptr};
-  DISALLOW_COPY_AND_ASSIGN(RequestHandler);
-};
-
-bool Server::RequestHandler::ProcessRequest(
-    brillo::ErrorPtr* error,
-    const std::tuple<std::string, std::string, std::string, std::string,
-                     std::string>& in_request_info,
-    const std::vector<std::tuple<std::string, std::string>>& in_headers,
-    const std::vector<std::tuple<bool, std::string, std::string>>& in_params,
-    const std::vector<std::tuple<int32_t, std::string, std::string, std::string,
-                                 std::string>>& in_files,
-    const dbus::FileDescriptor& in_body) {
-  std::string protocol_handler_id = std::get<0>(in_request_info);
-  std::string request_handler_id = std::get<1>(in_request_info);
-  std::string request_id = std::get<2>(in_request_info);
-  std::string url = std::get<3>(in_request_info);
-  std::string method = std::get<4>(in_request_info);
-  ProtocolHandler* protocol_handler =
-      server_->GetProtocolHandlerByID(protocol_handler_id);
-  if (!protocol_handler) {
-    brillo::Error::AddToPrintf(error, FROM_HERE,
-                               brillo::errors::dbus::kDomain,
-                               DBUS_ERROR_FAILED,
-                               "Unknown protocol handler '%s'",
-                               protocol_handler_id.c_str());
-    return false;
-  }
-  std::unique_ptr<RequestImpl> request{
-    new RequestImpl{protocol_handler, url, method}};
-  // Convert request data into format required by the Request object.
-  for (const auto& tuple : in_params) {
-    if (std::get<0>(tuple))
-      request->post_data_.emplace(std::get<1>(tuple), std::get<2>(tuple));
-    else
-      request->get_data_.emplace(std::get<1>(tuple), std::get<2>(tuple));
-  }
-
-  for (const auto& tuple : in_headers)
-    request->headers_.emplace(std::get<0>(tuple), std::get<1>(tuple));
-
-  for (const auto& tuple : in_files) {
-    request->file_info_.emplace(
-        std::get<1>(tuple),  // field_name
-        std::unique_ptr<FileInfo>{new FileInfo{
-            protocol_handler,
-            std::get<0>(tuple),     // file_id
-            request_id,
-            std::get<2>(tuple),     // file_name
-            std::get<3>(tuple),     // content_type
-            std::get<4>(tuple)}});  // transfer_encoding
-  }
-
-  request->raw_data_fd_ = base::File(dup(in_body.value()));
-  CHECK(request->raw_data_fd_.IsValid());
-
-  return protocol_handler->ProcessRequest(protocol_handler_id,
-                                          request_handler_id,
-                                          request_id,
-                                          std::move(request),
-                                          error);
-}
-
-Server::Server()
-    : request_handler_{new RequestHandler{this}},
-      dbus_adaptor_{new org::chromium::WebServer::RequestHandlerAdaptor{
-          request_handler_.get()}} {}
-
-Server::~Server() {
-}
-
-void Server::Connect(
+unique_ptr<Server> Server::ConnectToServerViaDBus(
     const scoped_refptr<dbus::Bus>& bus,
     const std::string& service_name,
     const brillo::dbus_utils::AsyncEventSequencer::CompletionAction& cb,
     const base::Closure& on_server_online,
     const base::Closure& on_server_offline) {
-  service_name_ = service_name;
-  dbus_object_.reset(new brillo::dbus_utils::DBusObject{
-      nullptr, bus, dbus_adaptor_->GetObjectPath()});
-  dbus_adaptor_->RegisterWithDBusObject(dbus_object_.get());
-  dbus_object_->RegisterAsync(cb);
-  on_server_online_ = on_server_online;
-  on_server_offline_ = on_server_offline;
-  object_manager_.reset(new org::chromium::WebServer::ObjectManagerProxy{bus});
-  object_manager_->SetServerAddedCallback(
-      base::Bind(&Server::Online, base::Unretained(this)));
-  object_manager_->SetServerRemovedCallback(
-      base::Bind(&Server::Offline, base::Unretained(this)));
-  object_manager_->SetProtocolHandlerAddedCallback(
-      base::Bind(&Server::ProtocolHandlerAdded, base::Unretained(this)));
-  object_manager_->SetProtocolHandlerRemovedCallback(
-      base::Bind(&Server::ProtocolHandlerRemoved, base::Unretained(this)));
-}
-
-void Server::Disconnect() {
-  on_server_offline_.Reset();
-  on_server_online_.Reset();
-  protocol_handlers_ids_.clear();
-  protocol_handlers_names_.clear();
-  // Release D-Bus object manager proxy after all the dependent maps are freed
-  // (e.g. |protocol_handlers_names_| contains pointers to ProtocolHandlerProxy,
-  // instances of which are owned by the D-Bus object manager).
-  object_manager_.reset();
-  dbus_object_.reset();
-}
-
-void Server::Online(org::chromium::WebServer::ServerProxyInterface* server) {
-  VLOG(1) << "Web server is on-line.";
-  proxy_ = server;
-  if (!on_server_online_.is_null())
-    on_server_online_.Run();
-}
-
-void Server::Offline(const dbus::ObjectPath& object_path) {
-  if (!on_server_offline_.is_null())
-    on_server_offline_.Run();
-  proxy_ = nullptr;
-  VLOG(1) << "Web server is off-line.";
-}
-
-void Server::ProtocolHandlerAdded(
-    org::chromium::WebServer::ProtocolHandlerProxyInterface* handler) {
-  VLOG(1) << "Server-side protocol handler with ID '" << handler->id()
-          << "' is on-line (" << handler->name() << ")";
-
-  protocol_handler_id_map_.emplace(handler->GetObjectPath(), handler->id());
-  ProtocolHandler* registered_handler = GetProtocolHandler(handler->name());
-  if (registered_handler) {
-    protocol_handlers_ids_.emplace(handler->id(), registered_handler);
-    registered_handler->Connect(handler);
-    if (!on_protocol_handler_connected_.is_null())
-      on_protocol_handler_connected_.Run(registered_handler);
-  }
-}
-
-void Server::ProtocolHandlerRemoved(const dbus::ObjectPath& object_path) {
-  auto p = protocol_handler_id_map_.find(object_path);
-  if (p == protocol_handler_id_map_.end())
-    return;
-
-  VLOG(1) << "Server-side protocol handler with ID '" << p->second
-          << "' is off-line.";
-
-  ProtocolHandler* registered_handler = GetProtocolHandlerByID(p->second);
-  if (registered_handler) {
-    if (!on_protocol_handler_disconnected_.is_null())
-      on_protocol_handler_disconnected_.Run(registered_handler);
-    registered_handler->Disconnect(object_path);
-    protocol_handlers_ids_.erase(p->second);
-  }
-
-  protocol_handler_id_map_.erase(p);
-}
-
-ProtocolHandler* Server::GetProtocolHandler(const std::string& name) {
-  auto p = protocol_handlers_names_.find(name);
-  if (p == protocol_handlers_names_.end()) {
-    VLOG(1) << "Creating a client-side instance of web server's protocol "
-            << "handler with name '" << name << "'";
-    p = protocol_handlers_names_.emplace(
-        name,
-        std::unique_ptr<ProtocolHandler>{new ProtocolHandler{name, this}})
-            .first;
-  }
-  return p->second.get();
-}
-
-ProtocolHandler* Server::GetDefaultHttpHandler() {
-  return GetProtocolHandler(ProtocolHandler::kHttp);
-}
-
-ProtocolHandler* Server::GetDefaultHttpsHandler() {
-  return GetProtocolHandler(ProtocolHandler::kHttps);
-}
-
-ProtocolHandler* Server::GetProtocolHandlerByID(const std::string& id) const {
-  auto p = protocol_handlers_ids_.find(id);
-  if (p == protocol_handlers_ids_.end()) {
-    LOG(ERROR) << "Unable to locate protocol handler with ID '" << id << "'";
-    return nullptr;
-  }
-  return p->second;
-}
-
-void Server::OnProtocolHandlerConnected(
-    const base::Callback<void(ProtocolHandler*)>& callback) {
-  on_protocol_handler_connected_ = callback;
-}
-
-void Server::OnProtocolHandlerDisconnected(
-    const base::Callback<void(ProtocolHandler*)>& callback) {
-  on_protocol_handler_disconnected_ = callback;
-}
-
-base::TimeDelta Server::GetDefaultRequestTimeout() const {
-  int timeout_seconds = proxy_ ? proxy_->default_request_timeout() : -1;
-  if (timeout_seconds <= 0)
-    return base::TimeDelta::Max();
-  return base::TimeDelta::FromSeconds(timeout_seconds);
+  DBusServer* server = new DBusServer;
+  unique_ptr<Server> ret(server);
+  server->Connect(bus, service_name, cb, on_server_online, on_server_offline);
+  return ret;
 }
 
 }  // namespace libwebserv
diff --git a/libwebserv/server.h b/libwebserv/server.h
index ca8a6f1..77bf484 100644
--- a/libwebserv/server.h
+++ b/libwebserv/server.h
@@ -15,38 +15,26 @@
 #ifndef WEBSERVER_LIBWEBSERV_SERVER_H_
 #define WEBSERVER_LIBWEBSERV_SERVER_H_
 
-#include <map>
 #include <memory>
 #include <string>
 
+#include <base/callback.h>
 #include <base/macros.h>
-#include <dbus/bus.h>
+#include <base/memory/ref_counted.h>
 #include <brillo/dbus/async_event_sequencer.h>
-#include <brillo/dbus/dbus_object.h>
+#include <dbus/bus.h>
 #include <libwebserv/export.h>
-#include <libwebserv/request_handler_interface.h>
-
-namespace org {
-namespace chromium {
-namespace WebServer {
-
-class ObjectManagerProxy;
-class ProtocolHandlerProxyInterface;
-class RequestHandlerAdaptor;
-class ServerProxyInterface;
-
-}  // namespace WebServer
-}  // namespace chromium
-}  // namespace org
 
 namespace libwebserv {
 
+class ProtocolHandler;
+
 // Top-level wrapper class around HTTP server and provides an interface to
 // the web server.
-class LIBWEBSERV_EXPORT Server final {
+class LIBWEBSERV_EXPORT Server {
  public:
-  Server();
-  ~Server();
+  Server() = default;
+  virtual ~Server() = default;
 
   // Establish a connection to the system webserver.
   // |service_name| is the well known D-Bus name of the client's process, used
@@ -56,22 +44,18 @@
   // server comes up and down.
   // Note that we can Connect() even before the webserver attaches to D-Bus,
   // and appropriate state will be built up when the webserver appears on D-Bus.
-  void Connect(
+  static std::unique_ptr<Server> ConnectToServerViaDBus(
       const scoped_refptr<dbus::Bus>& bus,
       const std::string& service_name,
       const brillo::dbus_utils::AsyncEventSequencer::CompletionAction& cb,
       const base::Closure& on_server_online,
       const base::Closure& on_server_offline);
 
-  // Disconnects from the web server and removes the library interface from
-  // D-Bus.
-  void Disconnect();
-
   // A helper method that returns the default handler for "http".
-  ProtocolHandler* GetDefaultHttpHandler();
+  virtual ProtocolHandler* GetDefaultHttpHandler() = 0;
 
   // A helper method that returns the default handler for "https".
-  ProtocolHandler* GetDefaultHttpsHandler();
+  virtual ProtocolHandler* GetDefaultHttpsHandler() = 0;
 
   // Returns an existing protocol handler by name.  If the handler with the
   // requested |name| does not exist, a new one will be created.
@@ -80,88 +64,30 @@
   // being configured to open a corresponding handler with the given name.
   // Because clients and the server come up asynchronously, we allow clients
   // to register anticipated handlers before server starts up.
-  ProtocolHandler* GetProtocolHandler(const std::string& name);
+  virtual ProtocolHandler* GetProtocolHandler(const std::string& name) = 0;
 
-  // Returns true if the web server daemon is connected to DBus and our
-  // connection to it has been established.
-  bool IsConnected() const { return proxy_ != nullptr; }
+  // Returns true if |this| is connected to the web server daemon via IPC.
+  virtual bool IsConnected() const = 0;
 
   // Set a user-callback to be invoked when a protocol handler is connect to the
   // server daemon.  Multiple calls to this method will overwrite previously set
   // callbacks.
-  void OnProtocolHandlerConnected(
-      const base::Callback<void(ProtocolHandler*)>& callback);
+  virtual void OnProtocolHandlerConnected(
+      const base::Callback<void(ProtocolHandler*)>& callback) = 0;
 
   // Set a user-callback to be invoked when a protocol handler is disconnected
   // from the server daemon (e.g. on shutdown).  Multiple calls to this method
   // will overwrite previously set callbacks.
-  void OnProtocolHandlerDisconnected(
-      const base::Callback<void(ProtocolHandler*)>& callback);
+  virtual void OnProtocolHandlerDisconnected(
+      const base::Callback<void(ProtocolHandler*)>& callback) = 0;
 
   // Returns the default request timeout used to process incoming requests.
   // The reply to an incoming request should be sent within this timeout or
   // else the web server will automatically abort the connection. If the timeout
   // is not set, the returned value will be base::TimeDelta::Max().
-  base::TimeDelta GetDefaultRequestTimeout() const;
+  virtual base::TimeDelta GetDefaultRequestTimeout() const = 0;
 
  private:
-  friend class ProtocolHandler;
-  class RequestHandler;
-
-  // Handler invoked when a connection is established to web server daemon.
-  LIBWEBSERV_PRIVATE void Online(
-      org::chromium::WebServer::ServerProxyInterface* server);
-
-  // Handler invoked when the web server daemon connection is dropped.
-  LIBWEBSERV_PRIVATE void Offline(const dbus::ObjectPath& object_path);
-
-  // Handler invoked when a new protocol handler D-Bus proxy object becomes
-  // available.
-  LIBWEBSERV_PRIVATE void ProtocolHandlerAdded(
-      org::chromium::WebServer::ProtocolHandlerProxyInterface* handler);
-
-  // Handler invoked when a protocol handler D-Bus proxy object disappears.
-  LIBWEBSERV_PRIVATE void ProtocolHandlerRemoved(
-      const dbus::ObjectPath& object_path);
-
-  // Looks up a protocol handler by ID. If not found, returns nullptr.
-  LIBWEBSERV_PRIVATE ProtocolHandler* GetProtocolHandlerByID(
-      const std::string& id) const;
-
-  // Private implementation of D-Bus RequestHandlerInterface called by the web
-  // server daemon whenever a new request is available to be processed.
-  std::unique_ptr<RequestHandler> request_handler_;
-  // D-Bus object adaptor for RequestHandlerInterface.
-  std::unique_ptr<org::chromium::WebServer::RequestHandlerAdaptor>
-      dbus_adaptor_;
-  // D-Bus object to handler registration of RequestHandlerInterface.
-  std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object_;
-
-  // A mapping of protocol handler name to the associated object.
-  std::map<std::string, std::unique_ptr<ProtocolHandler>>
-      protocol_handlers_names_;
-  // A mapping of protocol handler IDs to the associated object.
-  std::map<std::string, ProtocolHandler*> protocol_handlers_ids_;
-  // A map between D-Bus object path of protocol handler and remote protocol
-  // handler ID.
-  std::map<dbus::ObjectPath, std::string> protocol_handler_id_map_;
-
-  // User-specified callbacks for server and protocol handler life-time events.
-  base::Closure on_server_online_;
-  base::Closure on_server_offline_;
-  base::Callback<void(ProtocolHandler*)> on_protocol_handler_connected_;
-  base::Callback<void(ProtocolHandler*)> on_protocol_handler_disconnected_;
-
-  // D-Bus object manager proxy that receives notification of web server
-  // daemon's D-Bus object creation and destruction.
-  std::unique_ptr<org::chromium::WebServer::ObjectManagerProxy> object_manager_;
-
-  // D-Bus proxy for the web server main object.
-  org::chromium::WebServer::ServerProxyInterface* proxy_{nullptr};
-
-  // D-Bus service name used by the daemon hosting this object.
-  std::string service_name_;
-
   DISALLOW_COPY_AND_ASSIGN(Server);
 };