• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "remoting/host/setup/service_client.h"
6 
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"
15 #include "url/gurl.h"
16 
17 namespace remoting {
18 
19 class ServiceClient::Core
20     : public base::RefCountedThreadSafe<ServiceClient::Core>,
21       public net::URLFetcherDelegate {
22  public:
Core(const std::string & chromoting_hosts_url,net::URLRequestContextGetter * request_context_getter)23   Core(const std::string& chromoting_hosts_url,
24        net::URLRequestContextGetter* request_context_getter)
25            : request_context_getter_(request_context_getter),
26              delegate_(NULL),
27              pending_request_type_(PENDING_REQUEST_NONE),
28              chromoting_hosts_url_(chromoting_hosts_url) {
29   }
30 
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);
37 
38   void UnregisterHost(const std::string& host_id,
39                       const std::string& oauth_access_token,
40                       ServiceClient::Delegate* delegate);
41 
42   // net::URLFetcherDelegate implementation.
43   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
44 
45  private:
46   friend class base::RefCountedThreadSafe<Core>;
~Core()47   virtual ~Core() {}
48 
49   enum PendingRequestType {
50     PENDING_REQUEST_NONE,
51     PENDING_REQUEST_REGISTER_HOST,
52     PENDING_REQUEST_UNREGISTER_HOST
53   };
54 
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);
61 
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_;
67 };
68 
RegisterHost(const std::string & host_id,const std::string & host_name,const std::string & public_key,const std::string & host_client_id,const std::string & oauth_access_token,Delegate * delegate)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,
75     Delegate* delegate) {
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,
88                         url_suffix,
89                         post_body_str,
90                         oauth_access_token,
91                         delegate);
92 }
93 
UnregisterHost(const std::string & host_id,const std::string & oauth_access_token,Delegate * delegate)94 void ServiceClient::Core::UnregisterHost(
95     const std::string& host_id,
96     const std::string& oauth_access_token,
97     Delegate* delegate) {
98   DCHECK(pending_request_type_ == PENDING_REQUEST_NONE);
99   pending_request_type_ = PENDING_REQUEST_UNREGISTER_HOST;
100   MakeChromotingRequest(net::URLFetcher::DELETE_REQUEST,
101                         host_id,
102                         std::string(),
103                         oauth_access_token,
104                         delegate);
105 }
106 
MakeChromotingRequest(net::URLFetcher::RequestType request_type,const std::string & url_suffix,const std::string & request_body,const std::string & oauth_access_token,ServiceClient::Delegate * delegate)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_.reset(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);
119   request_->Start();
120 }
121 
122 // URLFetcher::Delegate implementation.
OnURLFetchComplete(const net::URLFetcher * source)123 void ServiceClient::Core::OnURLFetchComplete(
124     const net::URLFetcher* source) {
125   HandleResponse(source);
126   request_.reset();
127 }
128 
HandleResponse(const net::URLFetcher * 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();
135     return;
136   }
137 
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) {
141     switch (old_type) {
142       case PENDING_REQUEST_NONE:
143         break;
144       case PENDING_REQUEST_REGISTER_HOST:
145         {
146           std::string data;
147           source->GetResponseAsString(&data);
148           scoped_ptr<Value> message_value(base::JSONReader::Read(data));
149           DictionaryValue *dict;
150           std::string code;
151           if (message_value.get() &&
152               message_value->IsType(Value::TYPE_DICTIONARY) &&
153               message_value->GetAsDictionary(&dict) &&
154               dict->GetString("data.authorizationCode", &code)) {
155             delegate_->OnHostRegistered(code);
156           } else {
157             delegate_->OnHostRegistered(std::string());
158           }
159         }
160         break;
161       case PENDING_REQUEST_UNREGISTER_HOST:
162         delegate_->OnHostUnregistered();
163         break;
164     }
165     return;
166   }
167   delegate_->OnNetworkError(source->GetResponseCode());
168 }
169 
ServiceClient(const std::string & chromoting_hosts_url,net::URLRequestContextGetter * context_getter)170 ServiceClient::ServiceClient(const std::string& chromoting_hosts_url,
171                              net::URLRequestContextGetter* context_getter) {
172   core_ = new Core(chromoting_hosts_url, context_getter);
173 }
174 
~ServiceClient()175 ServiceClient::~ServiceClient() {
176 }
177 
RegisterHost(const std::string & host_id,const std::string & host_name,const std::string & public_key,const std::string & host_client_id,const std::string & oauth_access_token,Delegate * delegate)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);
187 }
188 
UnregisterHost(const std::string & host_id,const std::string & oauth_access_token,Delegate * 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);
194 }
195 
196 }  // namespace gaia
197