Update weaved to reflect the latest changes in libweave

A number of APIs have changed in libweave and weaved is updated to
work with the latest version of the library. Some public D-Bus APIs
have changed as well to reflect the underlying libweave interfaces:

- Command::Done/SetProgress are replaced with Command::Complete
- Command::Abort now takes error code and error messages
- Command::category is removed
- Command::status is renamed to Command::state
- Manager::GetCommand is removed (since weave::Command::ToJson is
  no longer available)

Change-Id: Iebf0565467756e8a21be37163d750ff22c419672
diff --git a/buffet/dbus_bindings/com.android.Weave.Command.dbus-xml b/buffet/dbus_bindings/com.android.Weave.Command.dbus-xml
index 5fb2940..46913b3 100644
--- a/buffet/dbus_bindings/com.android.Weave.Command.dbus-xml
+++ b/buffet/dbus_bindings/com.android.Weave.Command.dbus-xml
@@ -6,15 +6,22 @@
       <arg name="progress" type="a{sv}" direction="in"/>
       <annotation name="org.chromium.DBus.Method.Kind" value="normal"/>
     </method>
-    <method name="SetResults">
+    <method name="Complete">
+      <tp:docstring>
+        Mark the command as successfully completed and specifies the command
+        results to be returned to the caller.
+      </tp:docstring>
       <arg name="results" type="a{sv}" direction="in"/>
       <annotation name="org.chromium.DBus.Method.Kind" value="normal"/>
     </method>
     <method name="Abort">
       <tp:docstring>
         Mark the command as aborted. This tells the cloud that the device did
-        not successfully complete executing the command.
+        not successfully complete executing the command. The error information
+        is provided in |code| and |message| parameters.
       </tp:docstring>
+      <arg name="code" type="s" direction="in"/>
+      <arg name="message" type="s" direction="in"/>
       <annotation name="org.chromium.DBus.Method.Kind" value="normal"/>
     </method>
     <method name="Cancel">
@@ -24,16 +31,9 @@
       </tp:docstring>
       <annotation name="org.chromium.DBus.Method.Kind" value="normal"/>
     </method>
-    <method name="Done">
-      <tp:docstring>
-        Mark the command as successfully completed.
-      </tp:docstring>
-      <annotation name="org.chromium.DBus.Method.Kind" value="normal"/>
-    </method>
     <property name="Name" type="s" access="read"/>
-    <property name="Category" type="s" access="read"/>
     <property name="Id" type="s" access="read"/>
-    <property name="Status" type="s" access="read"/>
+    <property name="State" type="s" access="read"/>
     <property name="Parameters" type="a{sv}" access="read"/>
     <property name="Progress" type="a{sv}" access="read"/>
     <property name="Results" type="a{sv}" access="read"/>
diff --git a/buffet/dbus_bindings/com.android.Weave.Manager.dbus-xml b/buffet/dbus_bindings/com.android.Weave.Manager.dbus-xml
index c93d893..a922491 100644
--- a/buffet/dbus_bindings/com.android.Weave.Manager.dbus-xml
+++ b/buffet/dbus_bindings/com.android.Weave.Manager.dbus-xml
@@ -26,11 +26,6 @@
       <arg name="id" type="s" direction="out"/>
       <annotation name="org.chromium.DBus.Method.Kind" value="async"/>
     </method>
-    <method name="GetCommand">
-      <arg name="id" type="s" direction="in"/>
-      <arg name="json_command" type="s" direction="out"/>
-      <annotation name="org.chromium.DBus.Method.Kind" value="async"/>
-    </method>
     <method name="TestMethod">
       <arg name="message" type="s" direction="in"/>
       <arg name="echoed_message" type="s" direction="out"/>
diff --git a/buffet/dbus_command_proxy.cc b/buffet/dbus_command_proxy.cc
index 71196e8..8c5c99f 100644
--- a/buffet/dbus_command_proxy.cc
+++ b/buffet/dbus_command_proxy.cc
@@ -52,7 +52,7 @@
   // Set the initial property values before registering the DBus object.
   dbus_adaptor_.SetName(command->GetName());
   dbus_adaptor_.SetId(command->GetID());
-  dbus_adaptor_.SetStatus(EnumToString(command->GetStatus()));
+  dbus_adaptor_.SetState(EnumToString(command->GetState()));
   dbus_adaptor_.SetProgress(
       DictionaryToDBusVariantDictionary(*command->GetProgress()));
   dbus_adaptor_.SetOrigin(EnumToString(command->GetOrigin()));
@@ -84,40 +84,49 @@
   }
   dbus_adaptor_.SetProgress(
       DictionaryToDBusVariantDictionary(*command->GetProgress()));
-  dbus_adaptor_.SetStatus(EnumToString(command->GetStatus()));
+  dbus_adaptor_.SetState(EnumToString(command->GetState()));
   return true;
 }
 
-bool DBusCommandProxy::SetResults(chromeos::ErrorPtr* error,
-                                  const chromeos::VariantDictionary& results) {
+bool DBusCommandProxy::Complete(chromeos::ErrorPtr* error,
+                                const chromeos::VariantDictionary& results) {
   auto command = command_.lock();
   if (!command)
     return ReportDestroyedError(error);
 
   LOG(INFO) << "Received call to Command<" << command->GetName()
-            << ">::SetResults()";
+            << ">::Complete()";
   auto dictionary = DictionaryFromDBusVariantDictionary(results, error);
   if (!dictionary)
     return false;
   weave::ErrorPtr weave_error;
-  if (!command->SetResults(*dictionary, &weave_error)) {
+  if (!command->Complete(*dictionary, &weave_error)) {
     ConvertError(*weave_error, error);
     return false;
   }
   dbus_adaptor_.SetProgress(
       DictionaryToDBusVariantDictionary(*command->GetProgress()));
+  dbus_adaptor_.SetState(EnumToString(command->GetState()));
   return true;
 }
 
-bool DBusCommandProxy::Abort(chromeos::ErrorPtr* error) {
+bool DBusCommandProxy::Abort(chromeos::ErrorPtr* error,
+                             const std::string& code,
+                             const std::string& message) {
   auto command = command_.lock();
   if (!command)
     return ReportDestroyedError(error);
 
   LOG(INFO) << "Received call to Command<" << command->GetName()
             << ">::Abort()";
-  command->Abort();
-  dbus_adaptor_.SetStatus(EnumToString(command->GetStatus()));
+  weave::ErrorPtr cmd_error;
+  weave::Error::AddTo(&cmd_error, FROM_HERE, "command_error", code, message);
+  weave::ErrorPtr weave_error;
+  if (!command->Abort(cmd_error.get(), &weave_error)) {
+    ConvertError(*weave_error, error);
+    return false;
+  }
+  dbus_adaptor_.SetState(EnumToString(command->GetState()));
   return true;
 }
 
@@ -128,22 +137,12 @@
 
   LOG(INFO) << "Received call to Command<" << command->GetName()
             << ">::Cancel()";
-  command->Cancel();
-  dbus_adaptor_.SetStatus(EnumToString(command->GetStatus()));
-  return true;
-}
-
-bool DBusCommandProxy::Done(chromeos::ErrorPtr* error) {
-  auto command = command_.lock();
-  if (!command)
-    return ReportDestroyedError(error);
-
-  LOG(INFO) << "Received call to Command<" << command->GetName()
-            << ">::Done()";
-  command->Done();
-  dbus_adaptor_.SetProgress(
-      DictionaryToDBusVariantDictionary(*command->GetProgress()));
-  dbus_adaptor_.SetStatus(EnumToString(command->GetStatus()));
+  weave::ErrorPtr weave_error;
+  if (!command->Cancel(&weave_error)) {
+    ConvertError(*weave_error, error);
+    return false;
+  }
+  dbus_adaptor_.SetState(EnumToString(command->GetState()));
   return true;
 }
 
diff --git a/buffet/dbus_command_proxy.h b/buffet/dbus_command_proxy.h
index bf2868d..68f2055 100644
--- a/buffet/dbus_command_proxy.h
+++ b/buffet/dbus_command_proxy.h
@@ -39,15 +39,15 @@
   // Handles calls to com.android.Weave.Command.SetProgress(progress).
   bool SetProgress(chromeos::ErrorPtr* error,
                    const chromeos::VariantDictionary& progress) override;
-  // Handles calls to com.android.Weave.Command.SetResults(results).
-  bool SetResults(chromeos::ErrorPtr* error,
-                  const chromeos::VariantDictionary& results) override;
+  // Handles calls to com.android.Weave.Command.Complete(results).
+  bool Complete(chromeos::ErrorPtr* error,
+                const chromeos::VariantDictionary& results) override;
   // Handles calls to com.android.Weave.Command.Abort().
-  bool Abort(chromeos::ErrorPtr* error) override;
+  bool Abort(chromeos::ErrorPtr* error,
+             const std::string& code,
+             const std::string& message) override;
   // Handles calls to com.android.Weave.Command.Cancel().
   bool Cancel(chromeos::ErrorPtr* error) override;
-  // Handles calls to com.android.Weave.Command.Done().
-  bool Done(chromeos::ErrorPtr* error) override;
 
   std::weak_ptr<weave::Command> command_;
   com::android::Weave::CommandAdaptor dbus_adaptor_{this};
diff --git a/buffet/dbus_command_proxy_unittest.cc b/buffet/dbus_command_proxy_unittest.cc
index 1e156e4..5988d98 100644
--- a/buffet/dbus_command_proxy_unittest.cc
+++ b/buffet/dbus_command_proxy_unittest.cc
@@ -43,6 +43,10 @@
   return IsEqualValue(*json_value, arg);
 }
 
+MATCHER_P2(ExpectError, code, message, "") {
+  return arg->GetCode() == code && arg->GetMessage() == message;
+}
+
 }  // namespace
 
 class DBusCommandProxyTest : public ::testing::Test {
@@ -62,10 +66,10 @@
     // Use WillRepeatedly because GetName is used for logging.
     EXPECT_CALL(*command_, GetName())
         .WillRepeatedly(ReturnRefOfCopy<std::string>("robot.jump"));
-    EXPECT_CALL(*command_, GetStatus())
-        .WillRepeatedly(Return(weave::CommandStatus::kQueued));
+    EXPECT_CALL(*command_, GetState())
+        .WillRepeatedly(Return(weave::Command::State::kQueued));
     EXPECT_CALL(*command_, GetOrigin())
-        .WillOnce(Return(weave::CommandOrigin::kLocal));
+        .WillOnce(Return(weave::Command::Origin::kLocal));
     EXPECT_CALL(*command_, MockGetParameters())
         .WillOnce(ReturnRefOfCopy<std::string>(R"({
           'height': 53,
@@ -111,10 +115,10 @@
     return GetCommandProxy();
   }
 
-  weave::CommandStatus GetCommandStatus() const {
-    weave::CommandStatus status;
-    EXPECT_TRUE(StringToEnum(GetCommandAdaptor()->GetStatus(), &status));
-    return status;
+  weave::Command::State GetCommandState() const {
+    weave::Command::State state;
+    EXPECT_TRUE(StringToEnum(GetCommandAdaptor()->GetState(), &state));
+    return state;
   }
 
   scoped_refptr<dbus::MockExportedObject> mock_exported_object_command_;
@@ -128,7 +132,7 @@
   VariantDictionary params = {
       {"height", int32_t{53}}, {"_jumpType", std::string{"_withKick"}},
   };
-  EXPECT_EQ(weave::CommandStatus::kQueued, GetCommandStatus());
+  EXPECT_EQ(weave::Command::State::kQueued, GetCommandState());
   EXPECT_EQ(params, GetCommandAdaptor()->GetParameters());
   EXPECT_EQ(VariantDictionary{}, GetCommandAdaptor()->GetProgress());
   EXPECT_EQ(VariantDictionary{}, GetCommandAdaptor()->GetResults());
@@ -143,32 +147,28 @@
       GetCommandInterface()->SetProgress(nullptr, {{"progress", int32_t{10}}}));
 }
 
-TEST_F(DBusCommandProxyTest, SetResults) {
+TEST_F(DBusCommandProxyTest, Complete) {
   EXPECT_CALL(
       *command_,
-      SetResults(
+      Complete(
           EqualToJson("{'foo': 42, 'bar': 'foobar', 'resultList': [1, 2, 3]}"),
           _))
       .WillOnce(Return(true));
-  EXPECT_TRUE(GetCommandInterface()->SetResults(
+  EXPECT_TRUE(GetCommandInterface()->Complete(
       nullptr, VariantDictionary{{"foo", int32_t{42}},
                                  {"bar", std::string{"foobar"}},
                                  {"resultList", std::vector<int>{1, 2, 3}}}));
 }
 
 TEST_F(DBusCommandProxyTest, Abort) {
-  EXPECT_CALL(*command_, Abort());
-  EXPECT_TRUE(GetCommandInterface()->Abort(nullptr));
+  EXPECT_CALL(*command_, Abort(ExpectError("foo", "bar"), _))
+      .WillOnce(Return(true));
+  EXPECT_TRUE(GetCommandInterface()->Abort(nullptr, "foo", "bar"));
 }
 
 TEST_F(DBusCommandProxyTest, Cancel) {
-  EXPECT_CALL(*command_, Cancel());
+  EXPECT_CALL(*command_, Cancel(_)).WillOnce(Return(true));
   EXPECT_TRUE(GetCommandInterface()->Cancel(nullptr));
 }
 
-TEST_F(DBusCommandProxyTest, Done) {
-  EXPECT_CALL(*command_, Done());
-  EXPECT_TRUE(GetCommandInterface()->Done(nullptr));
-}
-
 }  // namespace buffet
diff --git a/buffet/manager.cc b/buffet/manager.cc
index c3cbc87..3f3f4c1 100644
--- a/buffet/manager.cc
+++ b/buffet/manager.cc
@@ -41,6 +41,7 @@
 #include "buffet/webserv_client.h"
 
 using chromeos::dbus_utils::AsyncEventSequencer;
+using chromeos::dbus_utils::DBusMethodResponse;
 using chromeos::dbus_utils::ExportedObjectManager;
 
 namespace buffet {
@@ -121,6 +122,21 @@
   }
 }
 
+void RegisterDeviceSuccess(
+    const std::shared_ptr<DBusMethodResponse<std::string>>& response,
+    weave::Device* device) {
+  LOG(INFO) << "Device registered: " << device->GetSettings().cloud_id;
+  response->Return(device->GetSettings().cloud_id);
+}
+
+void RegisterDeviceError(
+    const std::shared_ptr<DBusMethodResponse<std::string>>& response,
+    const weave::Error* weave_error) {
+  chromeos::ErrorPtr error;
+  ConvertError(*weave_error, &error);
+  response->ReplyWithError(error.get());
+}
+
 }  // anonymous namespace
 
 class Manager::TaskRunner : public weave::provider::TaskRunner {
@@ -163,23 +179,32 @@
 #ifdef BUFFET_USE_WIFI_BOOTSTRAPPING
   if (!options_.disable_privet) {
     mdns_client_ = MdnsClient::CreateInstance(dbus_object_.GetBus());
-    web_serv_client_.reset(new WebServClient{dbus_object_.GetBus(), sequencer});
+    web_serv_client_.reset(new WebServClient{
+        dbus_object_.GetBus(), sequencer,
+        base::Bind(&Manager::CreateDevice, weak_ptr_factory_.GetWeakPtr())});
     bluetooth_client_ = BluetoothClient::CreateInstance();
     http_server = web_serv_client_.get();
 
     if (options_.enable_ping) {
-      http_server->AddRequestHandler(
-          "/privet/ping",
-          base::Bind(
-              [](const weave::provider::HttpServer::Request& request,
-                 const weave::provider::HttpServer::OnReplyCallback& callback) {
-                callback.Run(chromeos::http::status_code::Ok, "Hello, world!",
-                             chromeos::mime::text::kPlain);
-              }));
+      auto ping_handler = base::Bind(
+          [](std::unique_ptr<weave::provider::HttpServer::Request> request) {
+        request->SendReply(chromeos::http::status_code::Ok, "Hello, world!",
+                           chromeos::mime::text::kPlain);
+      });
+      http_server->AddHttpRequestHandler("/privet/ping", ping_handler);
+      http_server->AddHttpsRequestHandler("/privet/ping", ping_handler);
     }
   }
 #endif  // BUFFET_USE_WIFI_BOOTSTRAPPING
 
+  if (!http_server)
+    CreateDevice();
+}
+
+void Manager::CreateDevice() {
+  if (device_)
+    return;
+
   device_ = weave::Device::Create(config_.get(), task_runner_.get(),
                                   http_client_.get(), shill_client_.get(),
                                   mdns_client_.get(), web_serv_client_.get(),
@@ -223,15 +248,13 @@
                              const std::string& ticket_id) {
   LOG(INFO) << "Received call to Manager.RegisterDevice()";
 
-  weave::ErrorPtr error;
-  std::string device_id = device_->Register(ticket_id, &error);
-  if (!device_id.empty()) {
-    response->Return(device_id);
-    return;
-  }
-  chromeos::ErrorPtr chromeos_error;
-  ConvertError(*error, &chromeos_error);
-  response->ReplyWithError(chromeos_error.get());
+  std::shared_ptr<DBusMethodResponse<std::string>> shared_response =
+      std::move(response);
+
+  device_->Register(
+      ticket_id,
+      base::Bind(&RegisterDeviceSuccess, shared_response, device_.get()),
+      base::Bind(&RegisterDeviceError, shared_response));
 }
 
 void Manager::UpdateState(DBusMethodResponsePtr<> response,
@@ -283,20 +306,6 @@
   response->Return(id);
 }
 
-void Manager::GetCommand(DBusMethodResponsePtr<std::string> response,
-                         const std::string& id) {
-  const weave::Command* command = device_->FindCommand(id);
-  if (!command) {
-    response->ReplyWithError(FROM_HERE, kErrorDomain, "unknown_command",
-                             "Can't find command with id: " + id);
-    return;
-  }
-  std::string command_str;
-  base::JSONWriter::WriteWithOptions(
-      *command->ToJson(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &command_str);
-  response->Return(command_str);
-}
-
 std::string Manager::TestMethod(const std::string& message) {
   LOG(INFO) << "Received call to test method: " << message;
   return message;
diff --git a/buffet/manager.h b/buffet/manager.h
index 9ae5b17..a90925d 100644
--- a/buffet/manager.h
+++ b/buffet/manager.h
@@ -72,6 +72,7 @@
 
  private:
   void RestartWeave(chromeos::dbus_utils::AsyncEventSequencer* sequencer);
+  void CreateDevice();
 
   // DBus methods:
   void RegisterDevice(DBusMethodResponsePtr<std::string> response,
@@ -81,8 +82,6 @@
   bool GetState(chromeos::ErrorPtr* error, std::string* state) override;
   void AddCommand(DBusMethodResponsePtr<std::string> response,
                   const std::string& json_command) override;
-  void GetCommand(DBusMethodResponsePtr<std::string> response,
-                  const std::string& id) override;
   std::string TestMethod(const std::string& message) override;
 
   void StartPrivet(const Options& options,
diff --git a/buffet/shill_client.cc b/buffet/shill_client.cc
index ed80af2..e0babfc 100644
--- a/buffet/shill_client.cc
+++ b/buffet/shill_client.cc
@@ -65,7 +65,7 @@
   if ((state.compare(shill::kStateReady) == 0) ||
       (state.compare(shill::kStatePortal) == 0) ||
       (state.compare(shill::kStateOnline) == 0)) {
-    return Network::State::kConnected;
+    return Network::State::kOnline;
   }
   if ((state.compare(shill::kStateAssociation) == 0) ||
       (state.compare(shill::kStateConfiguration) == 0)) {
@@ -74,7 +74,7 @@
   if ((state.compare(shill::kStateFailure) == 0) ||
       (state.compare(shill::kStateActivationFailure) == 0)) {
     // TODO(wiley) Get error information off the service object.
-    return Network::State::kFailure;
+    return Network::State::kError;
   }
   if ((state.compare(shill::kStateIdle) == 0) ||
       (state.compare(shill::kStateOffline) == 0) ||
@@ -451,7 +451,7 @@
 
 void ShillClient::OnStateChangeForConnectingService(const string& state) {
   switch (ShillServiceStateToNetworkState(state)) {
-    case Network::State::kConnected: {
+    case Network::State::kOnline: {
       auto callback = connect_success_callback_;
       CleanupConnectingService();
 
@@ -459,7 +459,7 @@
         callback.Run();
       break;
     }
-    case Network::State::kFailure: {
+    case Network::State::kError: {
       ConnectToServiceError(connecting_service_);
       break;
     }
@@ -538,7 +538,7 @@
       FROM_HERE,
       base::Bind(&ShillClient::NotifyConnectivityListeners,
                  weak_factory_.GetWeakPtr(),
-                 GetConnectionState() == Network::State::kConnected));
+                 GetConnectionState() == Network::State::kOnline));
 }
 
 void ShillClient::NotifyConnectivityListeners(bool am_online) {
diff --git a/buffet/webserv_client.cc b/buffet/webserv_client.cc
index e79a6a4..4b464c8 100644
--- a/buffet/webserv_client.cc
+++ b/buffet/webserv_client.cc
@@ -23,12 +23,13 @@
 
 class RequestImpl : public HttpServer::Request {
  public:
-  explicit RequestImpl(std::unique_ptr<libwebserv::Request> request)
-      : request_{std::move(request)} {}
+  explicit RequestImpl(std::unique_ptr<libwebserv::Request> request,
+                       std::unique_ptr<libwebserv::Response> response)
+      : request_{std::move(request)}, response_{std::move(response)} {}
   ~RequestImpl() override {}
 
   // HttpServer::Request implementation.
-  const std::string& GetPath() const override { return request_->GetPath(); }
+  std::string GetPath() const override { return request_->GetPath(); }
 
   std::string GetFirstHeader(const std::string& name) const override {
     return request_->GetFirstHeader(name);
@@ -36,27 +37,32 @@
 
   // TODO(avakulenko): Remove this method and rewrite all call sites in libweave
   // to use GetDataStream() instead.
-  const std::vector<uint8_t>& GetData() const override {
+  std::string GetData() override {
     if (request_data_)
       return *request_data_;
 
-    request_data_.reset(new std::vector<uint8_t>);
+    request_data_.reset(new std::string);
     auto stream = request_->GetDataStream();
     if (stream) {
       if (stream->CanGetSize())
         request_data_->reserve(stream->GetRemainingSize());
-      std::vector<uint8_t> buffer(16 * 1024);  // 16K seems to be good enough.
+      std::vector<char> buffer(16 * 1024);  // 16K seems to be good enough.
       size_t sz = 0;
       while (stream->ReadBlocking(buffer.data(), buffer.size(), &sz, nullptr) &&
              sz > 0) {
-        request_data_->insert(request_data_->end(),
-                              buffer.data(), buffer.data() + sz);
+        request_data_->append(buffer.data(), buffer.data() + sz);
       }
     }
     return *request_data_;
   }
 
-  std::unique_ptr<weave::Stream> GetDataStream() const override {
+  void SendReply(int status_code,
+                 const std::string& data,
+                 const std::string& mime_type) override {
+    response_->ReplyWithText(status_code, data, mime_type);
+  }
+
+  std::unique_ptr<weave::Stream> GetDataStream() const {
     auto stream = std::unique_ptr<weave::Stream>{
         new SocketStream{request_->GetDataStream()}};
     return stream;
@@ -64,48 +70,19 @@
 
  private:
   std::unique_ptr<libwebserv::Request> request_;
-  mutable std::unique_ptr<std::vector<uint8_t>> request_data_;
+  std::unique_ptr<libwebserv::Response> response_;
+  mutable std::unique_ptr<std::string> request_data_;
 
   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) {
+    chromeos::dbus_utils::AsyncEventSequencer* sequencer,
+    const base::Closure& server_available_callback)
+    : server_available_callback_{server_available_callback} {
   web_server_.reset(new libwebserv::Server);
   web_server_->OnProtocolHandlerConnected(
       base::Bind(&WebServClient::OnProtocolHandlerConnected,
@@ -120,20 +97,44 @@
                        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)));
+WebServClient::~WebServClient() {
+  web_server_->Disconnect();
 }
 
-void WebServClient::OnResponse(std::unique_ptr<libwebserv::Response> response,
-                               int status_code,
-                               const std::string& data,
-                               const std::string& mime_type) {
-  response->ReplyWithText(status_code, data, mime_type);
+void WebServClient::AddHttpRequestHandler(
+    const std::string& path,
+    const RequestHandlerCallback& callback) {
+  web_server_->GetDefaultHttpHandler()->AddHandlerCallback(
+      path, "", base::Bind(&WebServClient::OnRequest,
+                           weak_ptr_factory_.GetWeakPtr(), callback));
+}
+
+void WebServClient::AddHttpsRequestHandler(
+    const std::string& path,
+    const RequestHandlerCallback& callback) {
+  web_server_->GetDefaultHttpsHandler()->AddHandlerCallback(
+      path, "", 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_;
+}
+
+chromeos::Blob WebServClient::GetHttpsCertificateFingerprint() const {
+  return certificate_;
+}
+
+void WebServClient::OnRequest(const RequestHandlerCallback& callback,
+                              std::unique_ptr<libwebserv::Request> request,
+                              std::unique_ptr<libwebserv::Response> response) {
+  std::unique_ptr<Request> weave_request{
+      new RequestImpl{std::move(request), std::move(response)}};
+  callback.Run(std::move(weave_request));
 }
 
 void WebServClient::OnProtocolHandlerConnected(
@@ -145,8 +146,8 @@
     https_port_ = *protocol_handler->GetPorts().begin();
     certificate_ = protocol_handler->GetCertificateFingerprint();
   }
-  for (const auto& cb : on_state_changed_callbacks_)
-    cb.Run(*this);
+  if (https_port_ && https_port_)
+    server_available_callback_.Run();
 }
 
 void WebServClient::OnProtocolHandlerDisconnected(
@@ -158,8 +159,6 @@
     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
index 0b47527..cf3b397 100644
--- a/buffet/webserv_client.h
+++ b/buffet/webserv_client.h
@@ -35,20 +35,22 @@
 class WebServClient : public weave::provider::HttpServer {
  public:
   WebServClient(const scoped_refptr<dbus::Bus>& bus,
-                chromeos::dbus_utils::AsyncEventSequencer* sequencer);
+                chromeos::dbus_utils::AsyncEventSequencer* sequencer,
+                const base::Closure& server_available_callback);
   ~WebServClient() override;
 
   // HttpServer implementation.
-  void AddOnStateChangedCallback(
-      const OnStateChangedCallback& callback) override;
-  void AddRequestHandler(const std::string& path_prefix,
-                         const OnRequestCallback& callback) override;
+  void AddHttpRequestHandler(const std::string& path,
+                             const RequestHandlerCallback& callback) override;
+  void AddHttpsRequestHandler(const std::string& path,
+                              const RequestHandlerCallback& callback) override;
+
   uint16_t GetHttpPort() const override;
   uint16_t GetHttpsPort() const override;
-  const std::vector<uint8_t>& GetHttpsCertificateFingerprint() const override;
+  std::vector<uint8_t> GetHttpsCertificateFingerprint() const override;
 
  private:
-  void OnRequest(const OnRequestCallback& callback,
+  void OnRequest(const RequestHandlerCallback& callback,
                  std::unique_ptr<libwebserv::Request> request,
                  std::unique_ptr<libwebserv::Response> response);
 
@@ -67,9 +69,8 @@
   uint16_t https_port_{0};
   std::vector<uint8_t> certificate_;
 
-  std::vector<OnStateChangedCallback> on_state_changed_callbacks_;
-
   std::unique_ptr<libwebserv::Server> web_server_;
+  base::Closure server_available_callback_;
 
   base::WeakPtrFactory<WebServClient> weak_ptr_factory_{this};
   DISALLOW_COPY_AND_ASSIGN(WebServClient);