1558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "remoting/host/setup/service_client.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/json/json_reader.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_status_code.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ServiceClient::Core 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public base::RefCountedThreadSafe<ServiceClient::Core>, 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public net::URLFetcherDelegate { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Core(const std::string& chromoting_hosts_url, 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::URLRequestContextGetter* request_context_getter) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : request_context_getter_(request_context_getter), 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_(NULL), 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_request_type_(PENDING_REQUEST_NONE), 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chromoting_hosts_url_(chromoting_hosts_url) { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RegisterHost(const std::string& host_id, 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& host_name, 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& public_key, 343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& host_client_id, 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& oauth_access_token, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceClient::Delegate* delegate); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void UnregisterHost(const std::string& host_id, 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& oauth_access_token, 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceClient::Delegate* delegate); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // net::URLFetcherDelegate implementation. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCountedThreadSafe<Core>; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~Core() {} 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum PendingRequestType { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PENDING_REQUEST_NONE, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PENDING_REQUEST_REGISTER_HOST, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PENDING_REQUEST_UNREGISTER_HOST 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) void MakeChromotingRequest(net::URLFetcher::RequestType request_type, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& post_body, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& url_suffix, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& oauth_access_token, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceClient::Delegate* delegate); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void HandleResponse(const net::URLFetcher* source); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<net::URLRequestContextGetter> request_context_getter_; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceClient::Delegate* delegate_; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<net::URLFetcher> request_; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PendingRequestType pending_request_type_; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string chromoting_hosts_url_; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceClient::Core::RegisterHost( 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& host_id, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& host_name, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& public_key, 733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& host_client_id, 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& oauth_access_token, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(pending_request_type_ == PENDING_REQUEST_NONE); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_request_type_ = PENDING_REQUEST_REGISTER_HOST; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DictionaryValue post_body; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) post_body.SetString("data.hostId", host_id); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) post_body.SetString("data.hostName", host_name); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) post_body.SetString("data.publicKey", public_key); 823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string url_suffix; 833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!host_client_id.empty()) 843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) url_suffix = "?hostClientId=" + host_client_id; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string post_body_str; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::JSONWriter::Write(&post_body, &post_body_str); 873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) MakeChromotingRequest(net::URLFetcher::POST, 883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) url_suffix, 893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) post_body_str, 903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) oauth_access_token, 913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) delegate); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceClient::Core::UnregisterHost( 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& host_id, 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& oauth_access_token, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(pending_request_type_ == PENDING_REQUEST_NONE); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_request_type_ = PENDING_REQUEST_UNREGISTER_HOST; 1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) MakeChromotingRequest(net::URLFetcher::DELETE_REQUEST, 1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) host_id, 1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string(), 1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) oauth_access_token, 1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) delegate); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ServiceClient::Core::MakeChromotingRequest( 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLFetcher::RequestType request_type, 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& url_suffix, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& request_body, 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& oauth_access_token, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceClient::Delegate* delegate) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_ = delegate; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.reset(net::URLFetcher::Create( 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0, GURL(chromoting_hosts_url_ + url_suffix), request_type, this)); 116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) request_->SetRequestContext(request_context_getter_.get()); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_->SetUploadData("application/json; charset=UTF-8", request_body); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_->AddExtraRequestHeader("Authorization: OAuth " + oauth_access_token); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_->Start(); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// URLFetcher::Delegate implementation. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceClient::Core::OnURLFetchComplete( 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLFetcher* source) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleResponse(source); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.reset(); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceClient::Core::HandleResponse(const net::URLFetcher* source) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(pending_request_type_ != PENDING_REQUEST_NONE); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PendingRequestType old_type = pending_request_type_; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_request_type_ = PENDING_REQUEST_NONE; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (source->GetResponseCode() == net::HTTP_BAD_REQUEST) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnOAuthError(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 137424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 138424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Treat codes 2xx as successful; for example, HTTP_NO_CONTENT (204) can be 139424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // returned from a DELETE_REQUEST. 140424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (source->GetResponseCode() / 100 == 2) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (old_type) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PENDING_REQUEST_NONE: 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PENDING_REQUEST_REGISTER_HOST: 1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) { 1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string data; 1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) source->GetResponseAsString(&data); 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::Value> message_value(base::JSONReader::Read(data)); 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue *dict; 1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string code; 1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (message_value.get() && 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_value->IsType(base::Value::TYPE_DICTIONARY) && 1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) message_value->GetAsDictionary(&dict) && 1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) dict->GetString("data.authorizationCode", &code)) { 1553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) delegate_->OnHostRegistered(code); 1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else { 1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) delegate_->OnHostRegistered(std::string()); 1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PENDING_REQUEST_UNREGISTER_HOST: 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnHostUnregistered(); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnNetworkError(source->GetResponseCode()); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ServiceClient::ServiceClient(const std::string& chromoting_hosts_url, 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::URLRequestContextGetter* context_getter) { 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) core_ = new Core(chromoting_hosts_url, context_getter); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ServiceClient::~ServiceClient() { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceClient::RegisterHost( 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& host_id, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& host_name, 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& public_key, 1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& host_client_id, 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& oauth_access_token, 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate) { 1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return core_->RegisterHost(host_id, host_name, public_key, host_client_id, 1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) oauth_access_token, delegate); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceClient::UnregisterHost( 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& host_id, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& oauth_access_token, 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return core_->UnregisterHost(host_id, oauth_access_token, delegate); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gaia 197