libweave: http::Transport access moved into HttpTransportClient
HttpTransportClient is implementation of HttpClient interface.
HttpTransportClient will be moved out of libweave into buffet.
BUG=brillo:1250
TEST=`FEATURES=test emerge-gizmo libweave buffet`
Change-Id: I9c3db5309318212020bb0348cc9fee4c8856011d
diff --git a/libweave/include/weave/http_client.h b/libweave/include/weave/http_client.h
new file mode 100644
index 0000000..8263d21
--- /dev/null
+++ b/libweave/include/weave/http_client.h
@@ -0,0 +1,56 @@
+// Copyright 2015 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIBWEAVE_INCLUDE_WEAVE_HTTP_CLIENT_H_
+#define LIBWEAVE_INCLUDE_WEAVE_HTTP_CLIENT_H_
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <base/callback.h>
+#include <chromeos/errors/error.h>
+
+namespace weave {
+
+class HttpClient {
+ public:
+ class Response {
+ public:
+ virtual int GetStatusCode() const = 0;
+ virtual std::string GetContentType() const = 0;
+ virtual const std::string& GetData() const = 0;
+
+ // TODO(vitalybuka): Hide when SendRequestAndBlock is removed.
+ virtual ~Response() = default;
+ };
+
+ using Headers = std::vector<std::pair<std::string, std::string>>;
+ using SuccessCallback = base::Callback<void(int, const Response&)>;
+ using ErrorCallback = base::Callback<void(int, const chromeos::Error*)>;
+
+ // TODO(vitalybuka): Remove blocking version.
+ virtual std::unique_ptr<Response> SendRequestAndBlock(
+ const std::string& method,
+ const std::string& url,
+ const std::string& data,
+ const std::string& mime_type,
+ const Headers& headers,
+ chromeos::ErrorPtr* error) = 0;
+
+ virtual int SendRequest(const std::string& method,
+ const std::string& url,
+ const std::string& data,
+ const std::string& mime_type,
+ const Headers& headers,
+ const SuccessCallback& success_callback,
+ const ErrorCallback& error_callback) = 0;
+
+ protected:
+ virtual ~HttpClient() = default;
+};
+
+} // namespace weave
+
+#endif // LIBWEAVE_INCLUDE_WEAVE_HTTP_CLIENT_H_
diff --git a/libweave/libweave.gyp b/libweave/libweave.gyp
index cdc7077..9a1f2b6 100644
--- a/libweave/libweave.gyp
+++ b/libweave/libweave.gyp
@@ -34,6 +34,7 @@
'src/commands/user_role.cc',
'src/device_manager.cc',
'src/device_registration_info.cc',
+ 'src/http_transport_client.cc',
'src/notification/notification_parser.cc',
'src/notification/pull_channel.cc',
'src/notification/xml_node.cc',
diff --git a/libweave/src/device_registration_info.cc b/libweave/src/device_registration_info.cc
index 9c06383..948b485 100644
--- a/libweave/src/device_registration_info.cc
+++ b/libweave/src/device_registration_info.cc
@@ -11,23 +11,25 @@
#include <vector>
#include <base/bind.h>
+#include <base/json/json_reader.h>
#include <base/json/json_writer.h>
#include <base/strings/string_number_conversions.h>
#include <base/values.h>
#include <chromeos/bind_lambda.h>
#include <chromeos/data_encoding.h>
#include <chromeos/errors/error_codes.h>
-#include <chromeos/http/http_utils.h>
#include <chromeos/key_value_store.h>
#include <chromeos/mime_utils.h>
#include <chromeos/strings/string_utils.h>
#include <chromeos/url_utils.h>
+#include <weave/http_client.h>
#include <weave/network.h>
#include "libweave/src/commands/cloud_command_proxy.h"
#include "libweave/src/commands/command_definition.h"
#include "libweave/src/commands/command_manager.h"
#include "libweave/src/commands/schema_constants.h"
+#include "libweave/src/http_transport_client.h"
#include "libweave/src/notification/xmpp_channel.h"
#include "libweave/src/states/state_manager.h"
#include "libweave/src/utils.h"
@@ -40,12 +42,23 @@
namespace {
+const int kHttpStatusContinue = 100;
+const int kHttpStatusBadRequest = 400;
+const int kHttpStatusDenied = 401;
+const int kHttpStatusForbidden = 403;
+const int kHttpStatusInternalServerError = 500;
+
+const char kGet[] = "GET";
+const char kPatch[] = "PATCH";
+const char kPost[] = "POST";
+const char kPut[] = "PUT";
+
std::pair<std::string, std::string> BuildAuthHeader(
const std::string& access_token_type,
const std::string& access_token) {
std::string authorization =
chromeos::string_utils::Join(" ", access_token_type, access_token);
- return {chromeos::http::request_header::kAuthorization, authorization};
+ return {"Authorization", authorization};
}
inline void SetUnexpectedError(chromeos::ErrorPtr* error) {
@@ -105,6 +118,105 @@
cb.Run();
}
+class RequestSender final {
+ public:
+ RequestSender(const std::string& method,
+ const std::string& url,
+ HttpClient* transport)
+ : method_{method}, url_{url}, transport_{transport} {}
+
+ std::unique_ptr<HttpClient::Response> SendAndBlock(
+ chromeos::ErrorPtr* error) {
+ return transport_->SendRequestAndBlock(method_, url_, data_, mime_type_,
+ headers_, error);
+ }
+
+ int Send(const HttpClient::SuccessCallback& success_callback,
+ const HttpClient::ErrorCallback& error_callback) {
+ return transport_->SendRequest(method_, url_, data_, mime_type_, headers_,
+ success_callback, error_callback);
+ }
+
+ void AddAuthHeader(const std::string& access_token) {
+ headers_.emplace_back(BuildAuthHeader("Bearer", access_token));
+ }
+
+ void SetData(const std::string& data, const std::string& mime_type) {
+ data_ = data;
+ mime_type_ = mime_type;
+ }
+
+ void SetFormData(
+ const std::vector<std::pair<std::string, std::string>>& data) {
+ data_ = chromeos::data_encoding::WebParamsEncode(data);
+ mime_type_ = chromeos::mime::application::kWwwFormUrlEncoded;
+ }
+
+ void SetJsonData(const base::Value& json) {
+ std::string data;
+ CHECK(base::JSONWriter::Write(json, &data_));
+ mime_type_ = chromeos::mime::AppendParameter(
+ chromeos::mime::application::kJson,
+ chromeos::mime::parameters::kCharset, "utf-8");
+ }
+
+ private:
+ std::string method_;
+ std::string url_;
+ std::string data_;
+ std::string mime_type_;
+ std::vector<std::pair<std::string, std::string>> headers_;
+ HttpClient* transport_{nullptr};
+
+ DISALLOW_COPY_AND_ASSIGN(RequestSender);
+};
+
+std::unique_ptr<base::DictionaryValue> ParseJsonResponse(
+ const HttpClient::Response& response,
+ chromeos::ErrorPtr* error) {
+ // Make sure we have a correct content type. Do not try to parse
+ // binary files, or HTML output. Limit to application/json and text/plain.
+ auto content_type =
+ chromeos::mime::RemoveParameters(response.GetContentType());
+ if (content_type != chromeos::mime::application::kJson &&
+ content_type != chromeos::mime::text::kPlain) {
+ chromeos::Error::AddTo(error, FROM_HERE, chromeos::errors::json::kDomain,
+ "non_json_content_type",
+ "Unexpected response content type: " + content_type);
+ return std::unique_ptr<base::DictionaryValue>();
+ }
+
+ const std::string& json = response.GetData();
+ std::string error_message;
+ auto value = base::JSONReader::ReadAndReturnError(json, base::JSON_PARSE_RFC,
+ nullptr, &error_message);
+ if (!value) {
+ chromeos::Error::AddToPrintf(error, FROM_HERE,
+ chromeos::errors::json::kDomain,
+ chromeos::errors::json::kParseError,
+ "Error '%s' occurred parsing JSON string '%s'",
+ error_message.c_str(), json.c_str());
+ return std::unique_ptr<base::DictionaryValue>();
+ }
+ base::DictionaryValue* dict_value = nullptr;
+ if (!value->GetAsDictionary(&dict_value)) {
+ chromeos::Error::AddToPrintf(
+ error, FROM_HERE, chromeos::errors::json::kDomain,
+ chromeos::errors::json::kObjectExpected,
+ "Response is not a valid JSON object: '%s'", json.c_str());
+ return std::unique_ptr<base::DictionaryValue>();
+ } else {
+ // |value| is now owned by |dict_value|, so release the scoped_ptr now.
+ base::IgnoreResult(value.release());
+ }
+ return std::unique_ptr<base::DictionaryValue>(dict_value);
+}
+
+bool IsSuccessful(const HttpClient::Response& response) {
+ int code = response.GetStatusCode();
+ return code >= kHttpStatusContinue && code < kHttpStatusBadRequest;
+}
+
} // anonymous namespace
DeviceRegistrationInfo::DeviceRegistrationInfo(
@@ -114,8 +226,9 @@
const std::shared_ptr<chromeos::http::Transport>& transport,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
bool notifications_enabled,
- weave::Network* network)
- : transport_{transport},
+ Network* network)
+ : http_client_owner_{new buffet::HttpTransportClient{transport}},
+ http_client_{http_client_owner_.get()},
task_runner_{task_runner},
command_manager_{command_manager},
state_manager_{state_manager},
@@ -144,11 +257,6 @@
DeviceRegistrationInfo::~DeviceRegistrationInfo() = default;
-std::pair<std::string, std::string>
-DeviceRegistrationInfo::GetAuthorizationHeader() const {
- return BuildAuthHeader("Bearer", access_token_);
-}
-
std::string DeviceRegistrationInfo::GetServiceURL(
const std::string& subpath,
const chromeos::data_encoding::WebParamList& params) const {
@@ -212,11 +320,11 @@
}
std::unique_ptr<base::DictionaryValue>
-DeviceRegistrationInfo::ParseOAuthResponse(chromeos::http::Response* response,
+DeviceRegistrationInfo::ParseOAuthResponse(const HttpClient::Response& response,
chromeos::ErrorPtr* error) {
- int code = 0;
- auto resp = chromeos::http::ParseJsonResponse(response, &code, error);
- if (resp && code >= chromeos::http::status_code::BadRequest) {
+ int code = response.GetStatusCode();
+ auto resp = ParseJsonResponse(response, error);
+ if (resp && code >= kHttpStatusBadRequest) {
std::string error_code, error_message;
if (!resp->GetString("error", &error_code)) {
error_code = "unexpected_response";
@@ -267,15 +375,14 @@
auto shared_error_callback =
std::make_shared<CloudRequestErrorCallback>(error_callback);
- chromeos::http::FormFieldList form_data{
+ RequestSender sender{kPost, GetOAuthURL("token"), http_client_};
+ sender.SetFormData({
{"refresh_token", config_->refresh_token()},
{"client_id", config_->client_id()},
{"client_secret", config_->client_secret()},
{"grant_type", "refresh_token"},
- };
-
- chromeos::http::RequestID request_id = chromeos::http::PostFormData(
- GetOAuthURL("token"), form_data, {}, transport_,
+ });
+ int request_id = sender.Send(
base::Bind(&DeviceRegistrationInfo::OnRefreshAccessTokenSuccess,
weak_factory_.GetWeakPtr(), shared_success_callback,
shared_error_callback),
@@ -289,12 +396,12 @@
void DeviceRegistrationInfo::OnRefreshAccessTokenSuccess(
const std::shared_ptr<base::Closure>& success_callback,
const std::shared_ptr<CloudRequestErrorCallback>& error_callback,
- chromeos::http::RequestID id,
- std::unique_ptr<chromeos::http::Response> response) {
+ int id,
+ const HttpClient::Response& response) {
VLOG(1) << "Refresh access token request with ID " << id << " completed";
oauth2_backoff_entry_->InformOfRequest(true);
chromeos::ErrorPtr error;
- auto json = ParseOAuthResponse(response.get(), &error);
+ auto json = ParseOAuthResponse(response, &error);
if (!json) {
error_callback->Run(error.get());
return;
@@ -328,7 +435,7 @@
void DeviceRegistrationInfo::OnRefreshAccessTokenError(
const std::shared_ptr<base::Closure>& success_callback,
const std::shared_ptr<CloudRequestErrorCallback>& error_callback,
- chromeos::http::RequestID id,
+ int id,
const chromeos::Error* error) {
VLOG(1) << "Refresh access token request with ID " << id << " failed";
oauth2_backoff_entry_->InformOfRequest(false);
@@ -430,8 +537,8 @@
void DeviceRegistrationInfo::GetDeviceInfo(
const CloudRequestCallback& success_callback,
const CloudRequestErrorCallback& error_callback) {
- DoCloudRequest(chromeos::http::request_type::kGet, GetDeviceURL(), nullptr,
- success_callback, error_callback);
+ DoCloudRequest(weave::kGet, GetDeviceURL(), nullptr, success_callback,
+ error_callback);
}
std::string DeviceRegistrationInfo::RegisterDevice(const std::string& ticket_id,
@@ -448,27 +555,30 @@
auto url = GetServiceURL("registrationTickets/" + ticket_id,
{{"key", config_->api_key()}});
- std::unique_ptr<chromeos::http::Response> response =
- chromeos::http::PatchJsonAndBlock(url, &req_json, {}, transport_, error);
- auto json_resp =
- chromeos::http::ParseJsonResponse(response.get(), nullptr, error);
+
+ RequestSender sender{kPatch, url, http_client_};
+ sender.SetJsonData(req_json);
+ auto response = sender.SendAndBlock(error);
+
+ if (!response)
+ return std::string();
+ auto json_resp = ParseJsonResponse(*response, error);
if (!json_resp)
return std::string();
- if (!response->IsSuccessful()) {
+ if (!IsSuccessful(*response)) {
ParseGCDError(json_resp.get(), error);
return std::string();
}
url = GetServiceURL("registrationTickets/" + ticket_id + "/finalize",
{{"key", config_->api_key()}});
- response = chromeos::http::SendRequestWithNoDataAndBlock(
- chromeos::http::request_type::kPost, url, {}, transport_, error);
+ response = RequestSender{kPost, url, http_client_}.SendAndBlock(error);
if (!response)
return std::string();
- json_resp = chromeos::http::ParseJsonResponse(response.get(), nullptr, error);
+ json_resp = ParseJsonResponse(*response, error);
if (!json_resp)
return std::string();
- if (!response->IsSuccessful()) {
+ if (!IsSuccessful(*response)) {
ParseGCDError(json_resp.get(), error);
return std::string();
}
@@ -490,19 +600,20 @@
UpdateDeviceInfoTimestamp(*device_draft_response);
// Now get access_token and refresh_token
- response = chromeos::http::PostFormDataAndBlock(
- GetOAuthURL("token"),
+ RequestSender sender2{kPost, GetOAuthURL("token"), http_client_};
+ sender2.SetFormData(
{{"code", auth_code},
{"client_id", config_->client_id()},
{"client_secret", config_->client_secret()},
{"redirect_uri", "oob"},
{"scope", "https://www.googleapis.com/auth/clouddevices"},
- {"grant_type", "authorization_code"}},
- {}, transport_, error);
+ {"grant_type", "authorization_code"}});
+ response = sender2.SendAndBlock(error);
+
if (!response)
return std::string();
- json_resp = ParseOAuthResponse(response.get(), error);
+ json_resp = ParseOAuthResponse(*response, error);
int expires_in = 0;
std::string refresh_token;
if (!json_resp || !json_resp->GetString("access_token", &access_token_) ||
@@ -582,24 +693,25 @@
const std::string mime_type =
chromeos::mime::AppendParameter(kJson, kCharset, "utf-8");
- chromeos::http::RequestID request_id = chromeos::http::SendRequest(
- data->method, data->url, data->body.c_str(), data->body.size(), mime_type,
- {GetAuthorizationHeader()}, transport_,
- base::Bind(&DeviceRegistrationInfo::OnCloudRequestSuccess, AsWeakPtr(),
- data),
- base::Bind(&DeviceRegistrationInfo::OnCloudRequestError, AsWeakPtr(),
- data));
+ RequestSender sender{data->method, data->url, http_client_};
+ sender.SetData(data->body, mime_type);
+ sender.AddAuthHeader(access_token_);
+ int request_id =
+ sender.Send(base::Bind(&DeviceRegistrationInfo::OnCloudRequestSuccess,
+ AsWeakPtr(), data),
+ base::Bind(&DeviceRegistrationInfo::OnCloudRequestError,
+ AsWeakPtr(), data));
VLOG(1) << "Cloud request with ID " << request_id << " successfully sent";
}
void DeviceRegistrationInfo::OnCloudRequestSuccess(
const std::shared_ptr<const CloudRequestData>& data,
- chromeos::http::RequestID request_id,
- std::unique_ptr<chromeos::http::Response> response) {
- int status_code = response->GetStatusCode();
+ int request_id,
+ const HttpClient::Response& response) {
+ int status_code = response.GetStatusCode();
VLOG(1) << "Response for cloud request with ID " << request_id
<< " received with status code " << status_code;
- if (status_code == chromeos::http::status_code::Denied) {
+ if (status_code == kHttpStatusDenied) {
cloud_backoff_entry_->InformOfRequest(true);
RefreshAccessToken(
base::Bind(&DeviceRegistrationInfo::OnAccessTokenRefreshed, AsWeakPtr(),
@@ -609,7 +721,7 @@
return;
}
- if (status_code >= chromeos::http::status_code::InternalServerError) {
+ if (status_code >= kHttpStatusInternalServerError) {
// Request was valid, but server failed, retry.
// TODO(antonm): Reconsider status codes, maybe only some require
// retry.
@@ -619,17 +731,16 @@
}
chromeos::ErrorPtr error;
- auto json_resp =
- chromeos::http::ParseJsonResponse(response.get(), nullptr, &error);
+ auto json_resp = ParseJsonResponse(response, &error);
if (!json_resp) {
data->error_callback.Run(error.get());
cloud_backoff_entry_->InformOfRequest(true);
return;
}
- if (!response->IsSuccessful()) {
+ if (!IsSuccessful(response)) {
ParseGCDError(json_resp.get(), &error);
- if (status_code == chromeos::http::status_code::Forbidden &&
+ if (status_code == kHttpStatusForbidden &&
error->HasError(kErrorDomainGCDServer, "rateLimitExceeded")) {
// If we exceeded server quota, retry the request later.
RetryCloudRequest(data);
@@ -647,7 +758,7 @@
void DeviceRegistrationInfo::OnCloudRequestError(
const std::shared_ptr<const CloudRequestData>& data,
- chromeos::http::RequestID request_id,
+ int request_id,
const chromeos::Error* error) {
VLOG(1) << "Cloud request with ID " << request_id << " failed";
RetryCloudRequest(data);
@@ -776,8 +887,8 @@
const base::DictionaryValue& command_patch,
const base::Closure& on_success,
const base::Closure& on_error) {
- DoCloudRequest(chromeos::http::request_type::kPatch,
- GetServiceURL("commands/" + command_id), &command_patch,
+ DoCloudRequest(weave::kPatch, GetServiceURL("commands/" + command_id),
+ &command_patch,
base::Bind(&IgnoreCloudResultWithCallback, on_success),
base::Bind(&IgnoreCloudErrorWithCallback, on_error));
}
@@ -853,7 +964,7 @@
{}, {{"lastUpdateTimeMs", last_device_resource_updated_timestamp_}});
DoCloudRequest(
- chromeos::http::request_type::kPut, url, device_resource.get(),
+ weave::kPut, url, device_resource.get(),
base::Bind(&DeviceRegistrationInfo::OnUpdateDeviceResourceSuccess,
AsWeakPtr()),
base::Bind(&DeviceRegistrationInfo::OnUpdateDeviceResourceError,
@@ -934,7 +1045,7 @@
const base::Callback<void(const base::ListValue&)>& on_success,
const CloudRequestErrorCallback& on_failure) {
DoCloudRequest(
- chromeos::http::request_type::kGet,
+ weave::kGet,
GetServiceURL("commands/queue", {{"deviceId", config_->device_id()}}),
nullptr, base::Bind(&HandleFetchCommandsResult, on_success), on_failure);
}
@@ -970,9 +1081,8 @@
std::unique_ptr<base::DictionaryValue> cmd_copy{command_dict->DeepCopy()};
cmd_copy->SetString("state", "aborted");
// TODO(wiley) We could consider handling this error case more gracefully.
- DoCloudRequest(chromeos::http::request_type::kPut,
- GetServiceURL("commands/" + command_id), cmd_copy.get(),
- base::Bind(&IgnoreCloudResult),
+ DoCloudRequest(weave::kPut, GetServiceURL("commands/" + command_id),
+ cmd_copy.get(), base::Bind(&IgnoreCloudResult),
base::Bind(&IgnoreCloudError));
} else {
// Normal command, publish it to local clients.
@@ -1015,8 +1125,8 @@
std::unique_ptr<CloudCommandProxy> cloud_proxy{new CloudCommandProxy{
command_instance.get(), this, state_manager_->GetStateChangeQueue(),
std::move(backoff_entry), task_runner_}};
- // CloudCommandProxy::CloudCommandProxy() subscribe itself to weave::Command
- // notifications. When weave::Command is being destroyed it sends
+ // CloudCommandProxy::CloudCommandProxy() subscribe itself to Command
+ // notifications. When Command is being destroyed it sends
// ::OnCommandDestroyed() and CloudCommandProxy deletes itself.
cloud_proxy.release();
command_manager_->AddCommand(std::move(command_instance));
@@ -1063,7 +1173,7 @@
device_state_update_pending_ = true;
DoCloudRequest(
- chromeos::http::request_type::kPost, GetDeviceURL("patchState"), &body,
+ weave::kPost, GetDeviceURL("patchState"), &body,
base::Bind(&DeviceRegistrationInfo::OnPublishStateSuccess, AsWeakPtr(),
update_id),
base::Bind(&DeviceRegistrationInfo::OnPublishStateError, AsWeakPtr()));
diff --git a/libweave/src/device_registration_info.h b/libweave/src/device_registration_info.h
index 2cf3e91..dccb6dd 100644
--- a/libweave/src/device_registration_info.h
+++ b/libweave/src/device_registration_info.h
@@ -24,6 +24,7 @@
#include <chromeos/http/http_transport.h>
#include <weave/cloud.h>
#include <weave/config.h>
+#include <weave/http_client.h>
#include "libweave/src/buffet_config.h"
#include "libweave/src/commands/cloud_command_update_interface.h"
@@ -42,10 +43,14 @@
class KeyValueStore;
} // namespace chromeos
+namespace buffet {
+class HttpTransportClient;
+} // namespace buffet
+
namespace weave {
-class StateManager;
class Network;
+class StateManager;
extern const char kErrorDomainOAuth2[];
extern const char kErrorDomainGCD[];
@@ -98,11 +103,6 @@
// Add callback to listen for changes in config.
void AddOnConfigChangedCallback(const Config::OnChangedCallback& callback);
- // Returns the authorization HTTP header that can be used to talk
- // to GCD server for authenticated device communication.
- // Make sure ValidateAndRefreshAccessToken() is called before this call.
- std::pair<std::string, std::string> GetAuthorizationHeader() const;
-
// Returns the GCD service request URL. If |subpath| is specified, it is
// appended to the base URL which is normally
// https://www.googleapis.com/clouddevices/v1/".
@@ -175,18 +175,18 @@
void OnRefreshAccessTokenSuccess(
const std::shared_ptr<base::Closure>& success_callback,
const std::shared_ptr<CloudRequestErrorCallback>& error_callback,
- chromeos::http::RequestID id,
- std::unique_ptr<chromeos::http::Response> response);
+ int id,
+ const HttpClient::Response& response);
void OnRefreshAccessTokenError(
const std::shared_ptr<base::Closure>& success_callback,
const std::shared_ptr<CloudRequestErrorCallback>& error_callback,
- chromeos::http::RequestID id,
+ int id,
const chromeos::Error* error);
// Parse the OAuth response, and sets registration status to
// kInvalidCredentials if our registration is no longer valid.
std::unique_ptr<base::DictionaryValue> ParseOAuthResponse(
- chromeos::http::Response* response,
+ const HttpClient::Response& response,
chromeos::ErrorPtr* error);
// This attempts to open a notification channel. The channel needs to be
@@ -215,10 +215,10 @@
void SendCloudRequest(const std::shared_ptr<const CloudRequestData>& data);
void OnCloudRequestSuccess(
const std::shared_ptr<const CloudRequestData>& data,
- chromeos::http::RequestID request_id,
- std::unique_ptr<chromeos::http::Response> response);
+ int request_id,
+ const HttpClient::Response& response);
void OnCloudRequestError(const std::shared_ptr<const CloudRequestData>& data,
- chromeos::http::RequestID request_id,
+ int request_id,
const chromeos::Error* error);
void RetryCloudRequest(const std::shared_ptr<const CloudRequestData>& data);
void OnAccessTokenRefreshed(
@@ -305,7 +305,10 @@
bool connected_to_cloud_{false};
// HTTP transport used for communications.
- std::shared_ptr<chromeos::http::Transport> transport_;
+ // TODO(vitalybuka): Move to buffet.
+ std::unique_ptr<buffet::HttpTransportClient> http_client_owner_;
+ HttpClient* http_client_;
+
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
// Global command manager.
std::shared_ptr<CommandManager> command_manager_;
diff --git a/libweave/src/http_transport_client.cc b/libweave/src/http_transport_client.cc
new file mode 100644
index 0000000..dbe0ffc
--- /dev/null
+++ b/libweave/src/http_transport_client.cc
@@ -0,0 +1,85 @@
+// Copyright 2015 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libweave/src/http_transport_client.h"
+
+#include <base/bind.h>
+#include <chromeos/errors/error.h>
+#include <chromeos/http/http_request.h>
+#include <chromeos/http/http_utils.h>
+
+namespace buffet {
+
+namespace {
+
+class ResponseImpl : public weave::HttpClient::Response {
+ public:
+ ~ResponseImpl() override = default;
+ explicit ResponseImpl(std::unique_ptr<chromeos::http::Response> response)
+ : response_{std::move(response)},
+ data_{response_->ExtractDataAsString()} {}
+
+ // weave::HttpClient::Response implementation
+ int GetStatusCode() const override { return response_->GetStatusCode(); }
+
+ std::string GetContentType() const override {
+ return response_->GetContentType();
+ }
+
+ const std::string& GetData() const override { return data_; }
+
+ private:
+ std::unique_ptr<chromeos::http::Response> response_;
+ std::string data_;
+ DISALLOW_COPY_AND_ASSIGN(ResponseImpl);
+};
+
+void OnSuccessCallback(
+ const weave::HttpClient::SuccessCallback& success_callback,
+ int id,
+ std::unique_ptr<chromeos::http::Response> response) {
+ success_callback.Run(id, ResponseImpl{std::move(response)});
+}
+
+void OnErrorCallback(const weave::HttpClient::ErrorCallback& error_callback,
+ int id,
+ const chromeos::Error* error) {
+ error_callback.Run(id, error);
+}
+
+} // anonymous namespace
+
+HttpTransportClient::HttpTransportClient(
+ const std::shared_ptr<chromeos::http::Transport>& transport)
+ : transport_{transport} {}
+
+HttpTransportClient::~HttpTransportClient() {}
+
+std::unique_ptr<weave::HttpClient::Response>
+HttpTransportClient::SendRequestAndBlock(const std::string& method,
+ const std::string& url,
+ const std::string& data,
+ const std::string& mime_type,
+ const Headers& headers,
+ chromeos::ErrorPtr* error) {
+ return std::unique_ptr<weave::HttpClient::Response>{
+ new ResponseImpl{chromeos::http::SendRequestAndBlock(
+ method, url, data.data(), data.size(), mime_type, headers, transport_,
+ error)}};
+}
+
+int HttpTransportClient::SendRequest(const std::string& method,
+ const std::string& url,
+ const std::string& data,
+ const std::string& mime_type,
+ const Headers& headers,
+ const SuccessCallback& success_callback,
+ const ErrorCallback& error_callback) {
+ return chromeos::http::SendRequest(
+ method, url, data.data(), data.size(), mime_type, headers, transport_,
+ base::Bind(&OnSuccessCallback, success_callback),
+ base::Bind(&OnErrorCallback, error_callback));
+}
+
+} // namespace buffet
diff --git a/libweave/src/http_transport_client.h b/libweave/src/http_transport_client.h
new file mode 100644
index 0000000..0eb5579
--- /dev/null
+++ b/libweave/src/http_transport_client.h
@@ -0,0 +1,52 @@
+// Copyright 2015 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIBWEAVE_SRC_HTTP_TRANSPORT_CLIENT_H_
+#define LIBWEAVE_SRC_HTTP_TRANSPORT_CLIENT_H_
+
+#include <memory>
+#include <string>
+
+#include <weave/http_client.h>
+
+namespace chromeos {
+namespace http {
+class Transport;
+}
+}
+
+namespace buffet {
+
+class HttpTransportClient : public weave::HttpClient {
+ public:
+ explicit HttpTransportClient(
+ const std::shared_ptr<chromeos::http::Transport>& transport);
+
+ ~HttpTransportClient() override;
+
+ // weave::HttpClient implementation.
+ std::unique_ptr<Response> SendRequestAndBlock(
+ const std::string& method,
+ const std::string& url,
+ const std::string& data,
+ const std::string& mime_type,
+ const Headers& headers,
+ chromeos::ErrorPtr* error) override;
+
+ int SendRequest(const std::string& method,
+ const std::string& url,
+ const std::string& data,
+ const std::string& mime_type,
+ const Headers& headers,
+ const SuccessCallback& success_callback,
+ const ErrorCallback& error_callback) override;
+
+ private:
+ std::shared_ptr<chromeos::http::Transport> transport_;
+ DISALLOW_COPY_AND_ASSIGN(HttpTransportClient);
+};
+
+} // namespace buffet
+
+#endif // LIBWEAVE_SRC_HTTP_TRANSPORT_CLIENT_H_