Home | History | Annotate | Download | only in remoting
      1 // Copyright (c) 2011 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 "chrome/browser/remoting/directory_add_request.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/json/json_reader.h"
     10 #include "base/json/json_writer.h"
     11 #include "base/values.h"
     12 #include "chrome/common/net/http_return.h"
     13 #include "net/http/http_request_headers.h"
     14 #include "net/url_request/url_request_context_getter.h"
     15 #include "net/url_request/url_request_status.h"
     16 
     17 namespace remoting {
     18 
     19 static const char kRemotingDirectoryUrl[] =
     20     "https://www.googleapis.com/chromoting/v1/@me/hosts";
     21 
     22 DirectoryAddRequest::DirectoryAddRequest(net::URLRequestContextGetter* getter)
     23     : getter_(getter) {
     24 }
     25 
     26 DirectoryAddRequest::~DirectoryAddRequest() {
     27   DCHECK(!fetcher_.get()) << "URLFetcher not destroyed.";
     28 }
     29 
     30 void DirectoryAddRequest::AddHost(const remoting::ChromotingHostInfo& host_info,
     31                                   const std::string& auth_token,
     32                                   DoneCallback* done_callback) {
     33   DCHECK(done_callback);
     34   done_callback_.reset(done_callback);
     35 
     36   // Prepare the parameters for the request.
     37   DictionaryValue data;
     38   data.SetString("hostId", host_info.host_id);
     39   data.SetString("hostName", host_info.hostname);
     40   data.SetString("publicKey", host_info.public_key);
     41 
     42   // Generate the final json query.
     43   DictionaryValue args;
     44   args.Set("data", data.DeepCopy());
     45   std::string request_content;
     46   base::JSONWriter::Write(&args, false, &request_content);
     47 
     48   // Prepare the HTTP header for authentication.
     49   net::HttpRequestHeaders headers;
     50   headers.SetHeader("Authorization", "GoogleLogin auth=" + auth_token);
     51   fetcher_.reset(
     52       new URLFetcher(GURL(kRemotingDirectoryUrl), URLFetcher::POST, this));
     53   fetcher_->set_request_context(getter_);
     54   fetcher_->set_upload_data("application/json", request_content);
     55   fetcher_->set_extra_request_headers(headers.ToString());
     56 
     57   // And then start the request.
     58   fetcher_->Start();
     59 }
     60 
     61 void DirectoryAddRequest::OnURLFetchComplete(
     62     const URLFetcher* source,
     63     const GURL& url,
     64     const net::URLRequestStatus& status,
     65     int response_code,
     66     const ResponseCookies& cookies,
     67     const std::string& data) {
     68   DCHECK_EQ(source, fetcher_.get());
     69 
     70   // Destroy the fetcher after the response has been received.
     71   fetcher_.reset();
     72 
     73   Result result;
     74   std::string error_message;
     75 
     76   if (status.is_success()) {
     77     DictionaryValue* response = NULL;
     78     scoped_ptr<Value> response_json(base::JSONReader::Read(data, true));
     79     if (response_json != NULL &&
     80         response_json->IsType(Value::TYPE_DICTIONARY)) {
     81       response = static_cast<DictionaryValue*>(response_json.get());
     82       response->GetString("error.message", &error_message);
     83     }
     84 
     85     switch (response_code) {
     86       case RC_REQUEST_OK:
     87         result = SUCCESS;
     88         break;
     89 
     90       case RC_BAD_REQUEST:
     91         // TODO(sergeyu): Implement duplicate error detection that doesn't
     92         // depend on error message.
     93         if (error_message.find("duplicate") != std::string::npos) {
     94           result = ERROR_EXISTS;
     95         } else {
     96           result = ERROR_INVALID_REQUEST;
     97         }
     98         break;
     99 
    100       case RC_UNAUTHORIZED:
    101         result = ERROR_AUTH;
    102         break;
    103 
    104       case RC_INTERNAL_SERVER_ERROR:
    105         result = ERROR_SERVER;
    106         break;
    107 
    108       default:
    109         result = ERROR_OTHER;
    110     }
    111   } else {
    112     result = ERROR_OTHER;
    113   }
    114 
    115   if (result != SUCCESS) {
    116     LOG(WARNING) << "Received error when trying to register Chromoting host. "
    117                  << "status.is_success(): " << status.is_success()
    118                  << "  response_code: " << response_code
    119                  << "  error_message: " << error_message;
    120   }
    121 
    122   done_callback_->Run(result, error_message);
    123 }
    124 
    125 }  // namespace remoting
    126