1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "remoting/host/setup/service_client.h"
7 #include "base/json/json_reader.h"
8 #include "base/json/json_writer.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/values.h"
11 #include "net/http/http_status_code.h"
12 #include "net/url_request/url_fetcher.h"
13 #include "net/url_request/url_fetcher_delegate.h"
14 #include "net/url_request/url_request_context_getter.h"
19 class ServiceClient::Core
20 : public base::RefCountedThreadSafe
<ServiceClient::Core
>,
21 public net::URLFetcherDelegate
{
23 Core(const std::string
& chromoting_hosts_url
,
24 net::URLRequestContextGetter
* request_context_getter
)
25 : request_context_getter_(request_context_getter
),
27 pending_request_type_(PENDING_REQUEST_NONE
),
28 chromoting_hosts_url_(chromoting_hosts_url
) {
31 void RegisterHost(const std::string
& host_id
,
32 const std::string
& host_name
,
33 const std::string
& public_key
,
34 const std::string
& host_client_id
,
35 const std::string
& oauth_access_token
,
36 ServiceClient::Delegate
* delegate
);
38 void UnregisterHost(const std::string
& host_id
,
39 const std::string
& oauth_access_token
,
40 ServiceClient::Delegate
* delegate
);
42 // net::URLFetcherDelegate implementation.
43 void OnURLFetchComplete(const net::URLFetcher
* source
) override
;
46 friend class base::RefCountedThreadSafe
<Core
>;
49 enum PendingRequestType
{
51 PENDING_REQUEST_REGISTER_HOST
,
52 PENDING_REQUEST_UNREGISTER_HOST
55 void MakeChromotingRequest(net::URLFetcher::RequestType request_type
,
56 const std::string
& post_body
,
57 const std::string
& url_suffix
,
58 const std::string
& oauth_access_token
,
59 ServiceClient::Delegate
* delegate
);
60 void HandleResponse(const net::URLFetcher
* source
);
62 scoped_refptr
<net::URLRequestContextGetter
> request_context_getter_
;
63 ServiceClient::Delegate
* delegate_
;
64 scoped_ptr
<net::URLFetcher
> request_
;
65 PendingRequestType pending_request_type_
;
66 std::string chromoting_hosts_url_
;
69 void ServiceClient::Core::RegisterHost(
70 const std::string
& host_id
,
71 const std::string
& host_name
,
72 const std::string
& public_key
,
73 const std::string
& host_client_id
,
74 const std::string
& oauth_access_token
,
76 DCHECK(pending_request_type_
== PENDING_REQUEST_NONE
);
77 pending_request_type_
= PENDING_REQUEST_REGISTER_HOST
;
78 base::DictionaryValue post_body
;
79 post_body
.SetString("data.hostId", host_id
);
80 post_body
.SetString("data.hostName", host_name
);
81 post_body
.SetString("data.publicKey", public_key
);
82 std::string url_suffix
;
83 if (!host_client_id
.empty())
84 url_suffix
= "?hostClientId=" + host_client_id
;
85 std::string post_body_str
;
86 base::JSONWriter::Write(post_body
, &post_body_str
);
87 MakeChromotingRequest(net::URLFetcher::POST
,
94 void ServiceClient::Core::UnregisterHost(
95 const std::string
& host_id
,
96 const std::string
& oauth_access_token
,
98 DCHECK(pending_request_type_
== PENDING_REQUEST_NONE
);
99 pending_request_type_
= PENDING_REQUEST_UNREGISTER_HOST
;
100 MakeChromotingRequest(net::URLFetcher::DELETE_REQUEST
,
107 void ServiceClient::Core::MakeChromotingRequest(
108 net::URLFetcher::RequestType request_type
,
109 const std::string
& url_suffix
,
110 const std::string
& request_body
,
111 const std::string
& oauth_access_token
,
112 ServiceClient::Delegate
* delegate
) {
113 delegate_
= delegate
;
114 request_
= net::URLFetcher::Create(
115 0, GURL(chromoting_hosts_url_
+ url_suffix
), request_type
, this);
116 request_
->SetRequestContext(request_context_getter_
.get());
117 request_
->SetUploadData("application/json; charset=UTF-8", request_body
);
118 request_
->AddExtraRequestHeader("Authorization: OAuth " + oauth_access_token
);
122 // URLFetcher::Delegate implementation.
123 void ServiceClient::Core::OnURLFetchComplete(
124 const net::URLFetcher
* source
) {
125 HandleResponse(source
);
129 void ServiceClient::Core::HandleResponse(const net::URLFetcher
* source
) {
130 DCHECK(pending_request_type_
!= PENDING_REQUEST_NONE
);
131 PendingRequestType old_type
= pending_request_type_
;
132 pending_request_type_
= PENDING_REQUEST_NONE
;
133 if (source
->GetResponseCode() == net::HTTP_BAD_REQUEST
) {
134 delegate_
->OnOAuthError();
138 // Treat codes 2xx as successful; for example, HTTP_NO_CONTENT (204) can be
139 // returned from a DELETE_REQUEST.
140 if (source
->GetResponseCode() / 100 == 2) {
142 case PENDING_REQUEST_NONE
:
144 case PENDING_REQUEST_REGISTER_HOST
:
147 source
->GetResponseAsString(&data
);
148 scoped_ptr
<base::Value
> message_value
= base::JSONReader::Read(data
);
149 base::DictionaryValue
*dict
;
151 if (message_value
.get() &&
152 message_value
->IsType(base::Value::TYPE_DICTIONARY
) &&
153 message_value
->GetAsDictionary(&dict
) &&
154 dict
->GetString("data.authorizationCode", &code
)) {
155 delegate_
->OnHostRegistered(code
);
157 delegate_
->OnHostRegistered(std::string());
161 case PENDING_REQUEST_UNREGISTER_HOST
:
162 delegate_
->OnHostUnregistered();
167 delegate_
->OnNetworkError(source
->GetResponseCode());
170 ServiceClient::ServiceClient(const std::string
& chromoting_hosts_url
,
171 net::URLRequestContextGetter
* context_getter
) {
172 core_
= new Core(chromoting_hosts_url
, context_getter
);
175 ServiceClient::~ServiceClient() {
178 void ServiceClient::RegisterHost(
179 const std::string
& host_id
,
180 const std::string
& host_name
,
181 const std::string
& public_key
,
182 const std::string
& host_client_id
,
183 const std::string
& oauth_access_token
,
184 Delegate
* delegate
) {
185 return core_
->RegisterHost(host_id
, host_name
, public_key
, host_client_id
,
186 oauth_access_token
, delegate
);
189 void ServiceClient::UnregisterHost(
190 const std::string
& host_id
,
191 const std::string
& oauth_access_token
,
192 Delegate
* delegate
) {
193 return core_
->UnregisterHost(host_id
, oauth_access_token
, delegate
);