Add a binder based server implementation
am: d6197ec257

* commit 'd6197ec257b6ae5233e99f775cfeb2f368bb9391':
  Add a binder based server implementation
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