172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Use of this source code is governed by a BSD-style license that can be
321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// found in the LICENSE file.
421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/remoting/directory_add_request.h"
621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <vector>
821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/json/json_reader.h"
1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/json/json_writer.h"
1121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/values.h"
1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/common/net/http_return.h"
1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/http/http_request_headers.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/url_request/url_request_context_getter.h"
1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/url_request/url_request_status.h"
1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace remoting {
1821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstatic const char kRemotingDirectoryUrl[] =
2021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    "https://www.googleapis.com/chromoting/v1/@me/hosts";
2121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenDirectoryAddRequest::DirectoryAddRequest(net::URLRequestContextGetter* getter)
2321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    : getter_(getter) {
2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
2521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
2621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenDirectoryAddRequest::~DirectoryAddRequest() {
2721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(!fetcher_.get()) << "URLFetcher not destroyed.";
2821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
2921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
3021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid DirectoryAddRequest::AddHost(const remoting::ChromotingHostInfo& host_info,
3121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                  const std::string& auth_token,
3221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                  DoneCallback* done_callback) {
3321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(done_callback);
3421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  done_callback_.reset(done_callback);
3521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
3621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Prepare the parameters for the request.
3721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DictionaryValue data;
3821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  data.SetString("hostId", host_info.host_id);
3921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  data.SetString("hostName", host_info.hostname);
4021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  data.SetString("publicKey", host_info.public_key);
4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
4221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Generate the final json query.
4321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DictionaryValue args;
4421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  args.Set("data", data.DeepCopy());
4521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::string request_content;
4621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  base::JSONWriter::Write(&args, false, &request_content);
4721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
4821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Prepare the HTTP header for authentication.
4921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  net::HttpRequestHeaders headers;
5021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  headers.SetHeader("Authorization", "GoogleLogin auth=" + auth_token);
5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  fetcher_.reset(
5221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      new URLFetcher(GURL(kRemotingDirectoryUrl), URLFetcher::POST, this));
5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  fetcher_->set_request_context(getter_);
5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  fetcher_->set_upload_data("application/json", request_content);
5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  fetcher_->set_extra_request_headers(headers.ToString());
5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
5721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // And then start the request.
5821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  fetcher_->Start();
5921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
6021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
6121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid DirectoryAddRequest::OnURLFetchComplete(
6221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const URLFetcher* source,
6321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const GURL& url,
6472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const net::URLRequestStatus& status,
6521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    int response_code,
6621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const ResponseCookies& cookies,
6721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const std::string& data) {
6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK_EQ(source, fetcher_.get());
6921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
7021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Destroy the fetcher after the response has been received.
7121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  fetcher_.reset();
7221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
7321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  Result result;
7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::string error_message;
7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (status.is_success()) {
7721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    DictionaryValue* response = NULL;
7821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    scoped_ptr<Value> response_json(base::JSONReader::Read(data, true));
7921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (response_json != NULL &&
8021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        response_json->IsType(Value::TYPE_DICTIONARY)) {
8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      response = static_cast<DictionaryValue*>(response_json.get());
8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      response->GetString("error.message", &error_message);
8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
8421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    switch (response_code) {
8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      case RC_REQUEST_OK:
8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        result = SUCCESS;
8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        break;
8921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      case RC_BAD_REQUEST:
9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        // TODO(sergeyu): Implement duplicate error detection that doesn't
9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        // depend on error message.
9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        if (error_message.find("duplicate") != std::string::npos) {
9421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          result = ERROR_EXISTS;
9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        } else {
9621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          result = ERROR_INVALID_REQUEST;
9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        }
9821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        break;
9921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
10021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      case RC_UNAUTHORIZED:
10121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        result = ERROR_AUTH;
10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        break;
10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      case RC_INTERNAL_SERVER_ERROR:
10521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        result = ERROR_SERVER;
10621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        break;
10721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
10821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      default:
10921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        result = ERROR_OTHER;
11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  } else {
11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    result = ERROR_OTHER;
11321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
11421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (result != SUCCESS) {
11621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LOG(WARNING) << "Received error when trying to register Chromoting host. "
11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                 << "status.is_success(): " << status.is_success()
11821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                 << "  response_code: " << response_code
11921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                 << "  error_message: " << error_message;
12021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
12121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  done_callback_->Run(result, error_message);
12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}  // namespace remoting
126