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