Add webservd client for testing purposes

Right now, this client only answers ping requests.  We'll enable more
interesting functionality later.  With this patch and a corresponding
selinux policy modification, we can:

$ adb forward tcp:8080 tcp:80
$ adb shell start webservd_tclient
$ curl http://localhost:8080/webservd-test-client/ping
  Still alive, still alive.

Refactor a little of the build logic to make it easier later on to do
DBus/Binder specific implementations.

Bug: 26385135
Test: compiles, and above shell commands work on emulator

Change-Id: I225793a455972d99e97804d07f9ab7d15ca2b716
diff --git a/Android.mk b/Android.mk
index 3a694d0..999d6b4 100644
--- a/Android.mk
+++ b/Android.mk
@@ -16,10 +16,19 @@
 
 webservd_root := $(my-dir)
 
+system_webservd_use_dbus := true
+system_webservd_use_binder :=
+
 # Definitions applying to all targets. $(eval) this last.
 define webservd_common
   LOCAL_CPP_EXTENSION := .cc
   LOCAL_CFLAGS += -Wall -Werror
+  ifeq ($(system_webservd_use_dbus),true)
+    LOCAL_CFLAGS += -DWEBSERV_USE_DBUS
+  endif
+  ifeq ($(system_webservd_use_binder),true)
+    LOCAL_CFLAGS += -DWEBSERV_USE_BINDER
+  endif
 
   # libbrillo's secure_blob.h calls "using Blob::vector" to expose its base
   # class's constructors. This causes a "conflicts with version inherited from
@@ -30,16 +39,32 @@
     $(webservd_root) \
     external/gtest/include \
 
+endef  # webserv_common
+
+define webservd_common_libraries
   LOCAL_SHARED_LIBRARIES += \
       libbrillo \
-      libbrillo-dbus \
       libbrillo-http \
       libbrillo-stream \
       libchrome \
-      libchrome-dbus \
-      libdbus \
-      libmicrohttpd \
+      libmicrohttpd
 
-endef
+  # TODO(wiley) Uncomment these guards once firewalld moves to binder
+  #             b/25932807
+  # ifeq ($(system_webservd_use_dbus),true)
+    LOCAL_SHARED_LIBRARIES += \
+        libbrillo-dbus \
+        libchrome-dbus \
+        libdbus
+  # endif
+  ifeq ($(system_webservd_use_binder),true)
+    LOCAL_SHARED_LIBRARIES += \
+        libbrillo-binder \
+        libcutils \
+        libutils \
+        libbinder
+  endif
+
+endef  # webserv_common_libraries
 
 include $(call all-subdir-makefiles)
diff --git a/libwebserv/Android.mk b/libwebserv/Android.mk
index bffcd7a..fd3840b 100644
--- a/libwebserv/Android.mk
+++ b/libwebserv/Android.mk
@@ -35,6 +35,7 @@
     server.cc \
 
 $(eval $(webservd_common))
+$(eval $(webservd_common_libraries))
 include $(BUILD_SHARED_LIBRARY)
 
 # libwebserv-proxies-internal shared library
diff --git a/test-client/Android.mk b/test-client/Android.mk
new file mode 100644
index 0000000..8c7924d
--- /dev/null
+++ b/test-client/Android.mk
@@ -0,0 +1,58 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(my-dir)
+
+# executable run in tests to validate that the webserver is
+# working correctly
+include $(CLEAR_VARS)
+LOCAL_MODULE := webservd_test_client
+
+# We want this executable installed for testing purposes, but only on brillo
+# images.
+ifdef BRILLO
+  LOCAL_MODULE_TAGS := debug
+endif
+
+LOCAL_INIT_RC := webservd_test_client.rc
+LOCAL_SRC_FILES := \
+    main.cc
+
+# Contrary to our own instructions, we're not going to include this last.
+# We're going define our own libraries and include paths as if we were actually
+# a client.
+$(eval $(webservd_common))
+
+LOCAL_C_INCLUDES :=
+LOCAL_SHARED_LIBRARIES := \
+    libbrillo \
+    libchrome \
+    libwebserv
+
+ifeq ($(system_webservd_use_dbus),true)
+LOCAL_SHARED_LIBRARIES += \
+    libdbus \
+    libbrillo-dbus \
+    libchrome-dbus
+endif
+
+ifeq ($(system_webservd_use_binder),true)
+LOCAL_SHARED_LIBRARIES += \
+    libbinder \
+    libbrillo-binder
+endif
+
+include $(BUILD_EXECUTABLE)
diff --git a/test-client/main.cc b/test-client/main.cc
new file mode 100644
index 0000000..609018a
--- /dev/null
+++ b/test-client/main.cc
@@ -0,0 +1,116 @@
+// 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 <base/bind.h>
+#include <base/macros.h>
+#include <brillo/mime_utils.h>
+#include <brillo/syslog_logging.h>
+#include <libwebserv/protocol_handler.h>
+#include <libwebserv/request_handler_interface.h>
+#include <libwebserv/server.h>
+#include <sysexits.h>
+
+#if defined(WEBSERV_USE_DBUS)
+
+#include <brillo/daemons/dbus_daemon.h>
+#include <brillo/dbus/async_event_sequencer.h>
+
+// If we're using DBus, pick a base class that does DBus related init.
+using WebservTestClientBaseClass = brillo::DBusDaemon;
+using brillo::dbus_utils::AsyncEventSequencer;
+
+#elif defined(WEBSERV_USE_BINDER)
+
+#include <brillo/daemons/daemon.h>
+using WebservTestClientBaseClass = brillo::Daemon;
+
+#else
+#error "You must select one of Binder or DBus as an RPC mechanism."
+#endif  // defined(WEBSERV_USE_DBUS)
+
+using libwebserv::Server;
+using libwebserv::ProtocolHandler;
+using libwebserv::RequestHandlerInterface;
+using libwebserv::Request;
+using libwebserv::Response;
+
+namespace {
+
+void LogServerOnlineStatus(bool online) {
+  LOG(INFO) << "Webserver is "
+            << ((online) ? "online" : "offline");
+}
+
+class PingRequestHandler : public RequestHandlerInterface {
+ public:
+  static const char kMethods[];
+  static const char kResponse[];
+  static const char kUrl[];
+
+  ~PingRequestHandler() override = default;
+  void HandleRequest(std::unique_ptr<Request> /* request */,
+                     std::unique_ptr<Response> response) override {
+    response->ReplyWithText(200, kResponse, brillo::mime::text::kPlain);
+  }
+};  // class PingRequestHandler
+
+const char PingRequestHandler::kMethods[] = "";  // all methods
+const char PingRequestHandler::kResponse[] = "Still alive, still alive!\n";
+const char PingRequestHandler::kUrl[] = "/webservd-test-client/ping";
+
+class WebservTestClient : public WebservTestClientBaseClass {
+ public:
+  WebservTestClient() = default;
+  ~WebservTestClient() override = default;
+
+ protected:
+  int OnInit() override {
+    int exit_code = WebservTestClientBaseClass::OnInit();
+    if (exit_code != EX_OK)
+      return exit_code;
+
+#ifdef WEBSERV_USE_DBUS
+    webserver_ = Server::ConnectToServerViaDBus(
+        bus_, bus_->GetConnectionName(),
+        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
+
+    // Note that adding this handler is only local, and we won't receive
+    // requests until the library does some async book keeping.
+    ProtocolHandler* http_handler = webserver_->GetDefaultHttpHandler();
+    http_handler->AddHandler(
+        PingRequestHandler::kUrl,
+        PingRequestHandler::kMethods,
+        std::unique_ptr<RequestHandlerInterface>(new PingRequestHandler()));
+
+    return exit_code;
+  }
+
+ private:
+  std::unique_ptr<Server> webserver_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebservTestClient);
+};  // class WebservTestClient
+
+}  // namespace
+
+int main(int /* argc */, char* /* argv */[]) {
+  brillo::InitLog(brillo::kLogToSyslog | brillo::kLogHeader);
+  WebservTestClient client;
+  return client.Run();
+}
diff --git a/test-client/webservd_test_client.rc b/test-client/webservd_test_client.rc
new file mode 100644
index 0000000..be7bdad
--- /dev/null
+++ b/test-client/webservd_test_client.rc
@@ -0,0 +1,6 @@
+service webservd_tclient /system/bin/webservd_test_client
+    class late_start
+    oneshot
+    disabled
+    user system
+    group system dbus
diff --git a/webservd/Android.mk b/webservd/Android.mk
index 1cde80c..06b5978 100644
--- a/webservd/Android.mk
+++ b/webservd/Android.mk
@@ -63,6 +63,7 @@
 LOCAL_INIT_RC := webservd.rc
 
 $(eval $(webservd_common))
+$(eval $(webservd_common_libraries))
 include $(BUILD_EXECUTABLE)
 
 # libwebservd-client-internal shared library