| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "remoting/host/setup/service_client.h" |
| |
| #include "base/json/json_reader.h" |
| #include "base/json/json_writer.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/values.h" |
| #include "net/http/http_status_code.h" |
| #include "net/url_request/url_fetcher.h" |
| #include "net/url_request/url_fetcher_delegate.h" |
| #include "net/url_request/url_request_context_getter.h" |
| #include "url/gurl.h" |
| |
| namespace remoting { |
| |
| class ServiceClient::Core |
| : public base::RefCountedThreadSafe<ServiceClient::Core>, |
| public net::URLFetcherDelegate { |
| public: |
| Core(const std::string& chromoting_hosts_url, |
| net::URLRequestContextGetter* request_context_getter) |
| : request_context_getter_(request_context_getter), |
| delegate_(NULL), |
| pending_request_type_(PENDING_REQUEST_NONE), |
| chromoting_hosts_url_(chromoting_hosts_url) { |
| } |
| |
| void 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, |
| ServiceClient::Delegate* delegate); |
| |
| void UnregisterHost(const std::string& host_id, |
| const std::string& oauth_access_token, |
| ServiceClient::Delegate* delegate); |
| |
| // net::URLFetcherDelegate implementation. |
| virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; |
| |
| private: |
| friend class base::RefCountedThreadSafe<Core>; |
| virtual ~Core() {} |
| |
| enum PendingRequestType { |
| PENDING_REQUEST_NONE, |
| PENDING_REQUEST_REGISTER_HOST, |
| PENDING_REQUEST_UNREGISTER_HOST |
| }; |
| |
| void MakeChromotingRequest(net::URLFetcher::RequestType request_type, |
| const std::string& post_body, |
| const std::string& url_suffix, |
| const std::string& oauth_access_token, |
| ServiceClient::Delegate* delegate); |
| void HandleResponse(const net::URLFetcher* source); |
| |
| scoped_refptr<net::URLRequestContextGetter> request_context_getter_; |
| ServiceClient::Delegate* delegate_; |
| scoped_ptr<net::URLFetcher> request_; |
| PendingRequestType pending_request_type_; |
| std::string chromoting_hosts_url_; |
| }; |
| |
| void ServiceClient::Core::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) { |
| DCHECK(pending_request_type_ == PENDING_REQUEST_NONE); |
| pending_request_type_ = PENDING_REQUEST_REGISTER_HOST; |
| base::DictionaryValue post_body; |
| post_body.SetString("data.hostId", host_id); |
| post_body.SetString("data.hostName", host_name); |
| post_body.SetString("data.publicKey", public_key); |
| std::string url_suffix; |
| if (!host_client_id.empty()) |
| url_suffix = "?hostClientId=" + host_client_id; |
| std::string post_body_str; |
| base::JSONWriter::Write(&post_body, &post_body_str); |
| MakeChromotingRequest(net::URLFetcher::POST, |
| url_suffix, |
| post_body_str, |
| oauth_access_token, |
| delegate); |
| } |
| |
| void ServiceClient::Core::UnregisterHost( |
| const std::string& host_id, |
| const std::string& oauth_access_token, |
| Delegate* delegate) { |
| DCHECK(pending_request_type_ == PENDING_REQUEST_NONE); |
| pending_request_type_ = PENDING_REQUEST_UNREGISTER_HOST; |
| MakeChromotingRequest(net::URLFetcher::DELETE_REQUEST, |
| host_id, |
| std::string(), |
| oauth_access_token, |
| delegate); |
| } |
| |
| void ServiceClient::Core::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) { |
| delegate_ = delegate; |
| request_.reset(net::URLFetcher::Create( |
| 0, GURL(chromoting_hosts_url_ + url_suffix), request_type, this)); |
| request_->SetRequestContext(request_context_getter_.get()); |
| request_->SetUploadData("application/json; charset=UTF-8", request_body); |
| request_->AddExtraRequestHeader("Authorization: OAuth " + oauth_access_token); |
| request_->Start(); |
| } |
| |
| // URLFetcher::Delegate implementation. |
| void ServiceClient::Core::OnURLFetchComplete( |
| const net::URLFetcher* source) { |
| HandleResponse(source); |
| request_.reset(); |
| } |
| |
| void ServiceClient::Core::HandleResponse(const net::URLFetcher* source) { |
| DCHECK(pending_request_type_ != PENDING_REQUEST_NONE); |
| PendingRequestType old_type = pending_request_type_; |
| pending_request_type_ = PENDING_REQUEST_NONE; |
| if (source->GetResponseCode() == net::HTTP_BAD_REQUEST) { |
| delegate_->OnOAuthError(); |
| return; |
| } |
| |
| // Treat codes 2xx as successful; for example, HTTP_NO_CONTENT (204) can be |
| // returned from a DELETE_REQUEST. |
| if (source->GetResponseCode() / 100 == 2) { |
| switch (old_type) { |
| case PENDING_REQUEST_NONE: |
| break; |
| case PENDING_REQUEST_REGISTER_HOST: |
| { |
| std::string data; |
| source->GetResponseAsString(&data); |
| scoped_ptr<Value> message_value(base::JSONReader::Read(data)); |
| DictionaryValue *dict; |
| std::string code; |
| if (message_value.get() && |
| message_value->IsType(Value::TYPE_DICTIONARY) && |
| message_value->GetAsDictionary(&dict) && |
| dict->GetString("data.authorizationCode", &code)) { |
| delegate_->OnHostRegistered(code); |
| } else { |
| delegate_->OnHostRegistered(std::string()); |
| } |
| } |
| break; |
| case PENDING_REQUEST_UNREGISTER_HOST: |
| delegate_->OnHostUnregistered(); |
| break; |
| } |
| return; |
| } |
| delegate_->OnNetworkError(source->GetResponseCode()); |
| } |
| |
| ServiceClient::ServiceClient(const std::string& chromoting_hosts_url, |
| net::URLRequestContextGetter* context_getter) { |
| core_ = new Core(chromoting_hosts_url, context_getter); |
| } |
| |
| ServiceClient::~ServiceClient() { |
| } |
| |
| void ServiceClient::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) { |
| return core_->RegisterHost(host_id, host_name, public_key, host_client_id, |
| oauth_access_token, delegate); |
| } |
| |
| void ServiceClient::UnregisterHost( |
| const std::string& host_id, |
| const std::string& oauth_access_token, |
| Delegate* delegate) { |
| return core_->UnregisterHost(host_id, oauth_access_token, delegate); |
| } |
| |
| } // namespace gaia |