1// Copyright (c) 2012 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 "sync/internal_api/syncapi_server_connection_manager.h"
6
7#include "net/base/net_errors.h"
8#include "net/http/http_status_code.h"
9#include "sync/internal_api/public/http_post_provider_factory.h"
10#include "sync/internal_api/public/http_post_provider_interface.h"
11
12namespace syncer {
13
14SyncAPIBridgedConnection::SyncAPIBridgedConnection(
15    ServerConnectionManager* scm,
16    HttpPostProviderFactory* factory)
17    : Connection(scm), factory_(factory) {
18  post_provider_ = factory_->Create();
19}
20
21SyncAPIBridgedConnection::~SyncAPIBridgedConnection() {
22  DCHECK(post_provider_);
23  factory_->Destroy(post_provider_);
24  post_provider_ = NULL;
25}
26
27bool SyncAPIBridgedConnection::Init(const char* path,
28                                    const std::string& auth_token,
29                                    const std::string& payload,
30                                    HttpResponse* response) {
31  std::string sync_server;
32  int sync_server_port = 0;
33  bool use_ssl = false;
34  bool use_oauth2_token = false;
35  GetServerParams(&sync_server, &sync_server_port, &use_ssl, &use_oauth2_token);
36  std::string connection_url = MakeConnectionURL(sync_server, path, use_ssl);
37
38  HttpPostProviderInterface* http = post_provider_;
39  http->SetURL(connection_url.c_str(), sync_server_port);
40
41  if (!auth_token.empty()) {
42    std::string headers;
43    if (use_oauth2_token)
44      headers = "Authorization: Bearer " + auth_token;
45    else
46      headers = "Authorization: GoogleLogin auth=" + auth_token;
47    http->SetExtraRequestHeaders(headers.c_str());
48  }
49
50  // Must be octet-stream, or the payload may be parsed for a cookie.
51  http->SetPostPayload("application/octet-stream", payload.length(),
52                       payload.data());
53
54  // Issue the POST, blocking until it finishes.
55  int error_code = 0;
56  int response_code = 0;
57  if (!http->MakeSynchronousPost(&error_code, &response_code)) {
58    DVLOG(1) << "Http POST failed, error returns: " << error_code;
59    response->server_status = HttpResponse::ServerConnectionCodeFromNetError(
60        error_code);
61    return false;
62  }
63
64  // We got a server response, copy over response codes and content.
65  response->response_code = response_code;
66  response->content_length =
67      static_cast<int64>(http->GetResponseContentLength());
68  response->payload_length =
69      static_cast<int64>(http->GetResponseContentLength());
70  if (response->response_code < 400)
71    response->server_status = HttpResponse::SERVER_CONNECTION_OK;
72  else if (response->response_code == net::HTTP_UNAUTHORIZED)
73    response->server_status = HttpResponse::SYNC_AUTH_ERROR;
74  else
75    response->server_status = HttpResponse::SYNC_SERVER_ERROR;
76
77  response->update_client_auth_header =
78      http->GetResponseHeaderValue("Update-Client-Auth");
79
80  // Write the content into our buffer.
81  buffer_.assign(http->GetResponseContent(), http->GetResponseContentLength());
82  return true;
83}
84
85void SyncAPIBridgedConnection::Abort() {
86  DCHECK(post_provider_);
87  post_provider_->Abort();
88}
89
90SyncAPIServerConnectionManager::SyncAPIServerConnectionManager(
91    const std::string& server,
92    int port,
93    bool use_ssl,
94    bool use_oauth2_token,
95    HttpPostProviderFactory* factory)
96    : ServerConnectionManager(server, port, use_ssl, use_oauth2_token),
97      post_provider_factory_(factory) {
98  DCHECK(post_provider_factory_.get());
99}
100
101SyncAPIServerConnectionManager::~SyncAPIServerConnectionManager() {}
102
103ServerConnectionManager::Connection*
104SyncAPIServerConnectionManager::MakeConnection() {
105  return new SyncAPIBridgedConnection(this, post_provider_factory_.get());
106}
107
108}  // namespace syncer
109