Add a binder based server implementation

Add the rough outlines of the client library.  The binder based server
is not implmented by the webservd side of the interface, in addition to
being non-functional in pretty much every other way.

Bug: 26385135
Test: test client and libwebservd compile, sanity integration test
      continues to pass

Change-Id: I036b97128e18033ead36e0af135a5a1729bacb3d
diff --git a/aidl/android/webservd/IProtocolHandler.aidl b/aidl/android/webservd/IProtocolHandler.aidl
new file mode 100644
index 0000000..fc0732a
--- /dev/null
+++ b/aidl/android/webservd/IProtocolHandler.aidl
@@ -0,0 +1,19 @@
+// Copyright 2016 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.
+
+package android.webservd;
+
+interface IProtocolHandler {
+  String GetName();
+}
diff --git a/aidl/android/webservd/IServer.aidl b/aidl/android/webservd/IServer.aidl
new file mode 100644
index 0000000..e03c62c
--- /dev/null
+++ b/aidl/android/webservd/IServer.aidl
@@ -0,0 +1,22 @@
+// Copyright 2016 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.
+
+package android.webservd;
+
+import android.webservd.IProtocolHandler;
+
+interface IServer {
+  List<IBinder> GetProtocolHandlers();
+}
+
diff --git a/libwebserv/Android.mk b/libwebserv/Android.mk
index fd3840b..96bdf1a 100644
--- a/libwebserv/Android.mk
+++ b/libwebserv/Android.mk
@@ -22,11 +22,9 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := libwebserv
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/..
-LOCAL_SHARED_LIBRARIES := libwebservd-client-internal
+LOCAL_SHARED_LIBRARIES :=
 LOCAL_SRC_FILES := \
     dbus_bindings/org.chromium.WebServer.RequestHandler.dbus-xml \
-    dbus_protocol_handler.cc \
-    dbus_server.cc \
     protocol_handler.cc \
     request.cc \
     request_handler_callback.cc \
@@ -34,6 +32,19 @@
     response.cc \
     server.cc \
 
+ifeq ($(system_webservd_use_dbus),true)
+LOCAL_SHARED_LIBRARIES += libwebservd-client-internal
+LOCAL_SRC_FILES += \
+    dbus_protocol_handler.cc \
+    dbus_server.cc
+endif
+
+ifeq ($(system_webservd_use_binder),true)
+LOCAL_SHARED_LIBRARIES += libwebserv-binder-internal
+LOCAL_SRC_FILES += \
+    binder_server.cc
+endif
+
 $(eval $(webservd_common))
 $(eval $(webservd_common_libraries))
 include $(BUILD_SHARED_LIBRARY)
@@ -42,11 +53,41 @@
 # ========================================================
 # You do not want to depend on this.  Depend on libwebserv instead.
 # libwebserv abstracts and helps you consume this interface.
-
+#
+# This library builds the proxies which webservd will use to communicate back
+# to libwebservd over DBus.
+ifeq ($(system_webservd_use_dbus),true)
 include $(CLEAR_VARS)
 LOCAL_MODULE := libwebserv-proxies-internal
+
 LOCAL_SRC_FILES := \
     dbus_bindings/org.chromium.WebServer.RequestHandler.dbus-xml \
 
 LOCAL_DBUS_PROXY_PREFIX := libwebserv
+
+$(eval $(webservd_common))
+$(eval $(webservd_common_libraries))
 include $(BUILD_SHARED_LIBRARY)
+endif
+
+
+# libwebserv-binder-internal shared library
+# ========================================================
+# You do not want to depend on this.  Depend on libwebserv instead.
+# libwebserv abstracts and helps you consume this interface.
+#
+# This library builds the binder interfaces used between webservd and libwebserv
+ifeq ($(system_webservd_use_binder),true)
+include $(CLEAR_VARS)
+LOCAL_MODULE := libwebserv-binder-internal
+
+LOCAL_SRC_FILES += \
+    ../aidl/android/webservd/IServer.aidl \
+    ../aidl/android/webservd/IProtocolHandler.aidl \
+    binder_constants.cc
+
+LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/../aidl
+$(eval $(webservd_common))
+$(eval $(webservd_common_libraries))
+include $(BUILD_SHARED_LIBRARY)
+endif
diff --git a/libwebserv/binder_constants.cc b/libwebserv/binder_constants.cc
new file mode 100644
index 0000000..53685c2
--- /dev/null
+++ b/libwebserv/binder_constants.cc
@@ -0,0 +1,22 @@
+// Copyright 2016 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/binder_constants.h"
+
+namespace libwebserv {
+
+const char kWebserverBinderServiceName[] = "android.webservd.Server";
+
+}  // namespace libwebserv
+
diff --git a/libwebserv/binder_constants.h b/libwebserv/binder_constants.h
new file mode 100644
index 0000000..6a2e66a
--- /dev/null
+++ b/libwebserv/binder_constants.h
@@ -0,0 +1,24 @@
+// Copyright 2016 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_BINDER_CONSTANTS_H_
+#define WEBSERVER_LIBWEBSERV_BINDER_CONSTANTS_H_
+
+namespace libwebserv {
+
+extern const char kWebserverBinderServiceName[];
+
+}  // namespace libwebserv
+
+#endif  // WEBSERVER_LIBWEBSERV_BINDER_CONSTANTS_H_
diff --git a/libwebserv/binder_server.cc b/libwebserv/binder_server.cc
new file mode 100644
index 0000000..758e10a
--- /dev/null
+++ b/libwebserv/binder_server.cc
@@ -0,0 +1,102 @@
+// Copyright 2016 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/binder_server.h"
+
+#include <utils/String16.h>
+
+#include "libwebserv/binder_constants.h"
+
+#include <string>
+#include <vector>
+
+using android::String16;
+using android::sp;
+using android::IBinder;
+using std::string;
+using std::vector;
+
+namespace libwebserv {
+
+BinderServer::BinderServer(brillo::MessageLoop* message_loop,
+                           const base::Closure& on_server_online,
+                           const base::Closure& on_server_offline,
+                           android::BinderWrapper* binder_wrapper)
+    : message_loop_{message_loop},
+      on_server_online_{on_server_online},
+      on_server_offline_{on_server_offline},
+      binder_wrapper_{binder_wrapper} {
+  message_loop_->PostTask(FROM_HERE,
+                          base::Bind(&BinderServer::TryConnecting,
+                                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void BinderServer::TryConnecting() {
+  ClearLocalState();
+  android::sp<android::IBinder> binder = binder_wrapper_->GetService(
+      libwebserv::kWebserverBinderServiceName);
+  if (!binder.get()) {
+    LOG(INFO) << "Webservd has not registered with service manager.";
+  } else if (!BuildLocalState(binder)) {
+    ClearLocalState();
+  } else {
+    // Got a binder, built up appropriate local state, our job is done.
+    return;
+  }
+  message_loop_->PostDelayedTask(FROM_HERE,
+                                 base::Bind(&BinderServer::TryConnecting,
+                                            weak_ptr_factory_.GetWeakPtr()),
+                                 base::TimeDelta::FromSeconds(1));
+}
+
+
+void BinderServer::ClearLocalState() {
+  // Remove all references to remote protocol handlers from our local wrappers.
+
+  // TODO(wiley) Define this method
+  //for (auto& local_handler: local_protocol_handlers_) {
+  //  local_handler.second->ResetRemoteProtocolHandlers();
+  //}
+
+  remote_server_.clear();
+}
+
+bool BinderServer::BuildLocalState(android::sp<android::IBinder> server) {
+  remote_server_ = android::interface_cast<RemoteServer>(server);
+  vector<sp<IBinder>> remote_raw_binders;
+  if (!remote_server_->GetProtocolHandlers(&remote_raw_binders).isOk()) {
+    // Possibly the server died, this is not necessarily an error.
+    LOG(INFO) << "Webservd failed to tell us about protocol handlers.";
+    return false;
+  }
+
+  // Tell the local wrappers about the remote handlers that exist now.
+  for (auto& raw_binder: remote_raw_binders) {
+    sp<RemoteProtocolHandler> remote_handler =
+        android::interface_cast<RemoteProtocolHandler>(raw_binder);
+    String16 name;
+    if (!remote_handler->GetName(&name).isOk()) {
+      LOG(INFO) << "Remote handler could not report its name.";
+      return false;
+    }
+    // TODO(wiley) Look for a BinderPHGroup by that name in local_handlers_
+    //             Create a new BinderPHGroup if necessary
+    //             Add it to the map under |name|
+    //             Update |it| appropriately
+    //             Tell |it| about |remote_handler|
+  }
+  return true;
+}
+
+}  // namespace libwebserv
diff --git a/libwebserv/binder_server.h b/libwebserv/binder_server.h
new file mode 100644
index 0000000..ac37a31
--- /dev/null
+++ b/libwebserv/binder_server.h
@@ -0,0 +1,86 @@
+// Copyright 2016 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_BINDER_SERVER_H_
+#define WEBSERVER_LIBWEBSERV_BINDER_SERVER_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <brillo/message_loops/message_loop.h>
+#include <base/bind.h>
+#include <base/macros.h>
+#include <base/memory/weak_ptr.h>
+
+#include <binderwrapper/binder_wrapper.h>
+#include <utils/StrongPointer.h>
+#include <binder/IBinder.h>
+
+#include "android/webservd/IProtocolHandler.h"
+#include "android/webservd/IServer.h"
+#include "libwebserv/server.h"
+
+namespace libwebserv {
+
+class ProtocolHandler;
+class BinderPHGroup;
+
+class LIBWEBSERV_PRIVATE BinderServer : public Server {
+ public:
+  BinderServer(brillo::MessageLoop* message_loop,
+               const base::Closure& on_server_online,
+               const base::Closure& on_server_offline,
+               android::BinderWrapper* binder_wrapper);
+  ~BinderServer() override = default;
+
+  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:
+  using RemoteServer = android::webservd::IServer;
+  using RemoteProtocolHandler = android::webservd::IProtocolHandler;
+
+  void TryConnecting();
+  void ClearLocalState();
+  bool BuildLocalState(android::sp<android::IBinder> server);
+
+  // Used to poll for webservd availability and notify the user of changes
+  brillo::MessageLoop* message_loop_;
+  base::Closure on_server_online_;
+  base::Closure on_server_offline_;
+  android::BinderWrapper* binder_wrapper_;
+
+  android::sp<RemoteServer> remote_server_;
+  //std::map<std::string, std::unique_ptr<BinderPHGroup>>
+  //    local_protocol_handlers_;
+
+  base::WeakPtrFactory<BinderServer> weak_ptr_factory_{this};
+  DISALLOW_COPY_AND_ASSIGN(BinderServer);
+};
+
+}  // namespace libwebserv
+
+#endif  // WEBSERVER_LIBWEBSERV_BINDER_SERVER_H_
diff --git a/libwebserv/server.cc b/libwebserv/server.cc
index 9f567b3..3dc48ba 100644
--- a/libwebserv/server.cc
+++ b/libwebserv/server.cc
@@ -14,12 +14,19 @@
 
 #include <libwebserv/server.h>
 
-#include <libwebserv/dbus_server.h>
+#if defined(WEBSERV_USE_DBUS)
+#include "libwebserv/dbus_server.h"
+#endif  // defined(WEBSERV_USE_DBUS)
+
+#if defined(WEBSERV_USE_BINDER)
+#include "libwebserv/binder_server.h"
+#endif  // defined(WEBSERV_USE_BINDER)
 
 using std::unique_ptr;
 
 namespace libwebserv {
 
+#if defined(WEBSERV_USE_DBUS)
 unique_ptr<Server> Server::ConnectToServerViaDBus(
     const scoped_refptr<dbus::Bus>& bus,
     const std::string& service_name,
@@ -31,5 +38,17 @@
   server->Connect(bus, service_name, cb, on_server_online, on_server_offline);
   return ret;
 }
+#endif  // defined(WEBSERV_USE_DBUS)
+
+#if defined(WEBSERV_USE_BINDER)
+std::unique_ptr<Server> ConnectToServerViaBinder(
+    brillo::MessageLoop* message_loop,
+    const base::Closure& on_server_online,
+    const base::Closure& on_server_offline) {
+  return unique_ptr<Server>(new BinderServer(
+      message_loop, on_server_online, on_server_offline,
+      android::BinderWrapper::GetOrCreateInstance()));
+}
+#endif  // defined(WEBSERV_USE_BINDER)
 
 }  // namespace libwebserv
diff --git a/libwebserv/server.h b/libwebserv/server.h
index 77bf484..6eb8c07 100644
--- a/libwebserv/server.h
+++ b/libwebserv/server.h
@@ -15,15 +15,29 @@
 #ifndef WEBSERVER_LIBWEBSERV_SERVER_H_
 #define WEBSERVER_LIBWEBSERV_SERVER_H_
 
+// In our own Android.mk, we set these flags for ourselves.  However, for
+// libraries consuming libwebserv, they don't have any of that logic.  Leave us
+// with DBus bindings until the Binder interface is ready.
+#if !defined(WEBSERV_USE_DBUS) && !defined(WEBSERV_USE_BINDER)
+#define WEBSERV_USE_DBUS
+#endif
+
 #include <memory>
 #include <string>
 
 #include <base/callback.h>
 #include <base/macros.h>
+#include <libwebserv/export.h>
+
+#if defined(WEBSERV_USE_DBUS)
 #include <base/memory/ref_counted.h>
 #include <brillo/dbus/async_event_sequencer.h>
 #include <dbus/bus.h>
-#include <libwebserv/export.h>
+#endif  // defined(WEBSERV_USE_DBUS)
+
+#if defined(WEBSERV_USE_BINDER)
+#include <brillo/message_loops/message_loop.h>
+#endif  // defined(WEBSERV_USE_BINDER)
 
 namespace libwebserv {
 
@@ -36,20 +50,42 @@
   Server() = default;
   virtual ~Server() = default;
 
+#if defined(WEBSERV_USE_DBUS)
   // 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.
+  //
+  // Note that you can use the returned Server instance as if the webserver
+  // process is actually running (ignoring webserver crashes and restarts).
+  // All registered request handlers will simply be re-registered when the
+  // webserver appears again.
   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);
+#endif  // defined(WEBSERV_USE_DBUS)
+
+#if defined(WEBSERV_USE_BINDER)
+  // Establish a connection to the system webserver.
+  //
+  // |on_server_online| and |on_server_offline| will notify the caller when the
+  // server comes up and down.
+  //
+  // Note that you can use the returned Server instance as if the webserver
+  // process is actually running (ignoring webserver crashes and restarts).
+  // All registered request handlers will simply be re-registered when the
+  // webserver appears again.
+  static std::unique_ptr<Server> ConnectToServerViaBinder(
+      brillo::MessageLoop* message_loop,
+      const base::Closure& on_server_online,
+      const base::Closure& on_server_offline);
+#endif  // defined(WEBSERV_USE_BINDER)
 
   // A helper method that returns the default handler for "http".
   virtual ProtocolHandler* GetDefaultHttpHandler() = 0;
diff --git a/test-client/main.cc b/test-client/main.cc
index 609018a..d205670 100644
--- a/test-client/main.cc
+++ b/test-client/main.cc
@@ -86,9 +86,12 @@
         AsyncEventSequencer::GetDefaultCompletionAction(),
         base::Bind(&LogServerOnlineStatus, true /* online */),
         base::Bind(&LogServerOnlineStatus, false /* offline */));
-#else
-  #error "No alteratives to DBus are currently implemented!"
-#endif  // WEBSERV_USE_DBUS
+#elif WEBSERV_USE_BINDER
+    webserver_ = Server::ConnectToServerViaBinder(
+        message_loop(),
+        base::Bind(&LogServerOnlineStatus, true /* online */),
+        base::Bind(&LogServerOnlineStatus, false /* offline */));
+#endif  // WEBSERV_USE_DBUS || WEBSERV_USE_BINDER
 
     // Note that adding this handler is only local, and we won't receive
     // requests until the library does some async book keeping.
diff --git a/webservd/Android.mk b/webservd/Android.mk
index 06b5978..5086529 100644
--- a/webservd/Android.mk
+++ b/webservd/Android.mk
@@ -71,6 +71,7 @@
 # You do not want to depend on this.  Depend on libwebserv instead.
 # libwebserv abstracts and helps you consume this interface.
 
+ifeq ($(system_webservd_use_dbus),true)
 include $(CLEAR_VARS)
 LOCAL_MODULE := libwebservd-client-internal
 LOCAL_SRC_FILES := \
@@ -80,3 +81,4 @@
 
 LOCAL_DBUS_PROXY_PREFIX := webservd
 include $(BUILD_SHARED_LIBRARY)
+endif