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
DirectoryAddRequest(net::URLRequestContextGetter * getter)22 DirectoryAddRequest::DirectoryAddRequest(net::URLRequestContextGetter* getter)
23 : getter_(getter) {
24 }
25
~DirectoryAddRequest()26 DirectoryAddRequest::~DirectoryAddRequest() {
27 DCHECK(!fetcher_.get()) << "URLFetcher not destroyed.";
28 }
29
AddHost(const remoting::ChromotingHostInfo & host_info,const std::string & auth_token,DoneCallback * done_callback)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
OnURLFetchComplete(const URLFetcher * source,const GURL & url,const net::URLRequestStatus & status,int response_code,const ResponseCookies & cookies,const std::string & data)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