Home | History | Annotate | Download | only in setup
      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:
     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>;
     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 
     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 
     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 
    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.
    123 void ServiceClient::Core::OnURLFetchComplete(
    124     const net::URLFetcher* source) {
    125   HandleResponse(source);
    126   request_.reset();
    127 }
    128 
    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<base::Value> message_value(base::JSONReader::Read(data));
    149           base::DictionaryValue *dict;
    150           std::string code;
    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);
    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 
    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 
    175 ServiceClient::~ServiceClient() {
    176 }
    177 
    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 
    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