194b5036ee6ba866e1702848855b6d687d1e70afaAlexey Samsonov// Copyright 2014 The Chromium Authors. All rights reserved. 29aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany// Use of this source code is governed by a BSD-style license that can be 39aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany// found in the LICENSE file. 49aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany 59aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany#include "components/copresence/rpc/http_post.h" 69aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany 79aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany// TODO(ckehoe): Support third-party protobufs too. 89aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany#include <google/protobuf/message_lite.h> 99aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany 109aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany#include "base/bind.h" 110a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov#include "google_apis/google_api_keys.h" 129aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany#include "net/base/load_flags.h" 139aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany#include "net/base/net_errors.h" 149aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany#include "net/base/url_util.h" 159aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany#include "net/http/http_status_code.h" 16d865fecddccebf898ceed24d096fc58fb29a6e57Chandler Carruth#include "net/url_request/url_fetcher.h" 170a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov#include "net/url_request/url_request_context_getter.h" 189aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany#include "url/gurl.h" 199aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany 209aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryanynamespace copresence { 210a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov 220a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovconst char HttpPost::kApiKeyField[] = "key"; 230a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovconst char HttpPost::kTracingField[] = "trace"; 240a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov 250a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey SamsonovHttpPost::HttpPost(net::URLRequestContextGetter* url_context_getter, 260a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov const std::string& server_host, 27bfa45e11e52081c55294355f36fa547f163dcc67Dmitry Vyukov const std::string& rpc_name, 280a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov const std::string& tracing_token, 29d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov std::string api_key, 300a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov const google::protobuf::MessageLite& request_proto) { 310a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov // Create the base URL to call. 320a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov GURL url(server_host + "/" + rpc_name); 3315503b0a4331c7f27f9cebc25e25c2e494f61cb9Alexey Samsonov 340a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov // Add the tracing token, if specified. 350a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov if (!tracing_token.empty()) { 360a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov url = net::AppendQueryParameter( 37d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov url, kTracingField, "token:" + tracing_token); 38bfa45e11e52081c55294355f36fa547f163dcc67Dmitry Vyukov } 39d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov 400a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov // If no API key is specified, use the Chrome API key. 410a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov if (api_key.empty()) { 4215503b0a4331c7f27f9cebc25e25c2e494f61cb9Alexey Samsonov#ifdef GOOGLE_CHROME_BUILD 430a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov DCHECK(google_apis::HasKeysConfigured()); 440a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov api_key = google_apis::GetAPIKey(); 450a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov#else 4697daee89b35f6141db09aee612f0f377f754092fDmitry Vyukov LOG(ERROR) << "No Copresence API key provided"; 47d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov#endif 48bfa45e11e52081c55294355f36fa547f163dcc67Dmitry Vyukov } 490a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov url = net::AppendQueryParameter(url, kApiKeyField, api_key); 500a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov 510a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov // Serialize the proto for transmission. 520a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov std::string request_data; 530a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov bool serialize_success = request_proto.SerializeToString(&request_data); 542ea978704a794e536d2801affcc7f301092d75daAlexey Samsonov DCHECK(serialize_success); 550a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov 569aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany // Configure and send the request. 579aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany url_fetcher_.reset(net::URLFetcher::Create( 58dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov kUrlFetcherId, url, net::URLFetcher::POST, this)); 59dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov url_fetcher_->SetRequestContext(url_context_getter); 60dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov url_fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE | 61dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov net::LOAD_DISABLE_CACHE | 62dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov net::LOAD_DO_NOT_SAVE_COOKIES | 63dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov net::LOAD_DO_NOT_SEND_COOKIES | 64dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov net::LOAD_DO_NOT_SEND_AUTH_DATA); 65dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov url_fetcher_->SetUploadData("application/x-protobuf", request_data); 66dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov} 670a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov 680a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey SamsonovHttpPost::~HttpPost() {} 690a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov 700a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovvoid HttpPost::Start(const ResponseCallback& response_callback) { 710a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov response_callback_ = response_callback; 720a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov DVLOG(3) << "Sending Copresence request to " 730a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov << url_fetcher_->GetOriginalURL().spec(); 740a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov url_fetcher_->Start(); 750a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov} 769aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany 7715a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonovvoid HttpPost::OnURLFetchComplete(const net::URLFetcher* source) { 7815a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov DCHECK_EQ(url_fetcher_.get(), source); 7915a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov 8015a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov // Gather response info. 8115a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov std::string response; 8215a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov source->GetResponseAsString(&response); 8315a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov int response_code = source->GetResponseCode(); 8415a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov 85230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov // Log any errors. 86230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov if (response_code < 0) { 87230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov net::URLRequestStatus status = source->GetStatus(); 88230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov LOG(WARNING) << "Couldn't contact the Copresence server at " 89230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov << source->GetURL() << ". Status code " << status.status(); 90230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov LOG_IF(WARNING, status.error()) 91230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov << "Network error: " << net::ErrorToString(status.error()); 92230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov LOG_IF(WARNING, !response.empty()) << "HTTP response: " << response; 93230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov } else if (response_code != net::HTTP_OK) { 9415a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov LOG(WARNING) << "Copresence request got HTTP response code " 9515a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov << response_code << ". Response:\n" << response; 9615a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov } 9715a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov 9815a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov // Return the response. 9915a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov response_callback_.Run(response_code, response); 10015a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov} 10115a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov 10215a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov} // namespace copresence 10315a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov