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 17namespace remoting { 18 19static const char kRemotingDirectoryUrl[] = 20 "https://www.googleapis.com/chromoting/v1/@me/hosts"; 21 22DirectoryAddRequest::DirectoryAddRequest(net::URLRequestContextGetter* getter) 23 : getter_(getter) { 24} 25 26DirectoryAddRequest::~DirectoryAddRequest() { 27 DCHECK(!fetcher_.get()) << "URLFetcher not destroyed."; 28} 29 30void 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 61void 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