14ee2ad04344446e610172a0e73949212923014dfSebastian Redl// Copyright 2012 The Chromium Authors. All rights reserved.
22cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// Use of this source code is governed by a BSD-style license that can be
32cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// found in the LICENSE file.
42cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
52cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#ifndef SYNC_ENGINE_NET_SERVER_CONNECTION_MANAGER_H_
62cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#define SYNC_ENGINE_NET_SERVER_CONNECTION_MANAGER_H_
72cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
82cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <iosfwd>
92cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <string>
10a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl
112cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "base/atomicops.h"
122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "base/memory/scoped_ptr.h"
132cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "base/observer_list.h"
147faa2ec03a7ef120ac165bb45b6c70a8b20c9f1cSebastian Redl#include "base/strings/string_util.h"
150eca89e9890db4d8336ce762a5b359a1d58ca02bArgyrios Kyrtzidis#include "base/synchronization/lock.h"
16e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include "base/threading/non_thread_safe.h"
17e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include "base/threading/thread_checker.h"
182cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "sync/base/sync_export.h"
192cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "sync/internal_api/public/base/cancelation_observer.h"
202cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "sync/syncable/syncable_id.h"
212a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall
2289eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidisnamespace sync_pb {
230b7489194f9f89fac39d57211c1e7953ae50251fDouglas Gregorclass ClientToServerMessage;
247a1fad38256eb4c5129359be85ba1ea1678eb5c9John McCall}
252cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
26a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCallnamespace syncer {
276ab7cd853e9c15cf986a8a7c3db1f8d20e275409Sebastian Redl
28bbf38319edd4eddc55ec273934e990d7e84991deDouglas Gregorclass CancelationSignal;
297c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattner
306a5a23f8e7fb65e028c8092bc1d1a1d9dfe2e9bcDouglas Gregornamespace syncable {
317c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattnerclass Directory;
32a71a7d8a1ce4474e7bdb680658fb58b6caf391d3Douglas Gregor}
3383d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff
3414f79002e58556798e86168c63e48d533287eda5Douglas Gregorstatic const int32 kUnsetResponseCode = -1;
3510e286aa8d39fb51a21412850265d9dae74613eeChris Lattnerstatic const int32 kUnsetContentLength = -1;
363251ceb90b3fec68e86d6dcfa58836e20a7205c3Douglas Gregorstatic const int32 kUnsetPayloadLength = -1;
3714f79002e58556798e86168c63e48d533287eda5Douglas Gregor
38bd94500d3aa60092fb0f1e90f53fb0d03fa502a8Douglas Gregor// HttpResponse gathers the relevant output properties of an HTTP request.
392bec0410d268779f601bd509e0302a500af7ac6aDouglas Gregor// Depending on the value of the server_status code, response_code, and
4057016dda61498294120b1a881d9e6606337b29d9Douglas Gregor// content_length may not be valid.
41ab41e63821dc60ad144d0684df8d79a9eef86b75Douglas Gregorstruct SYNC_EXPORT_PRIVATE HttpResponse {
420a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor  enum ServerConnectionCode {
4317fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor    // For uninitialized state.
4417fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor    NONE,
452596e429a61602312bdd149786045b8a90cd2d10Daniel Dunbar
462cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    // CONNECTION_UNAVAILABLE is returned when InternetConnect() fails.
47fbfd180495e7800975c6d9bdc6d24e706ef70e34Michael J. Spencer    CONNECTION_UNAVAILABLE,
4814f79002e58556798e86168c63e48d533287eda5Douglas Gregor
4903013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer    // IO_ERROR is returned when reading/writing to a buffer has failed.
50f62d43d2afe1960755a1b5813cae1e5983bcac1bDouglas Gregor    IO_ERROR,
513c304bd9ec2b4611572d4cbae9e1727bbecb5dc9Chris Lattner
52cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor    // SYNC_SERVER_ERROR is returned when the HTTP status code indicates that
53f62d43d2afe1960755a1b5813cae1e5983bcac1bDouglas Gregor    // a non-auth error has occured.
542cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    SYNC_SERVER_ERROR,
558538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl
562cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    // SYNC_AUTH_ERROR is returned when the HTTP status code indicates that an
57ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl    // auth error has occured (i.e. a 401 or sync-specific AUTH_INVALID
585f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    // response)
595f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    // TODO(tim): Caring about AUTH_INVALID is a layering violation. But
605f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    // this app-specific logic is being added as a stable branch hotfix so
616e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer    // minimal changes prevail for the moment.  Fix this! Bug 35060.
62ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl    SYNC_AUTH_ERROR,
636e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer
646e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer    // SERVER_CONNECTION_OK is returned when request was handled correctly.
655f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    SERVER_CONNECTION_OK,
665f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner
676e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer    // RETRY is returned when a Commit request fails with a RETRY response from
68ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl    // the server.
69ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl    //
702cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    // TODO(idana): the server no longer returns RETRY so we should remove this
712cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    // value.
722cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    RETRY,
7312b1c7615d4f9a2edc544be499f895f16ac100edChris Lattner  };
742cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
753397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  // The HTTP Status code.
76a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl  int64 response_code;
7789eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis
782cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // The value of the Content-length header.
792cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  int64 content_length;
802cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
818538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  // The size of a download request's payload.
822cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  int64 payload_length;
8389eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis
848538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  // Identifies the type of failure, if any.
852cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  ServerConnectionCode server_status;
862cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
872cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  HttpResponse();
882cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
892cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  static const char* GetServerConnectionCodeString(
902cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      ServerConnectionCode code);
912cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
922cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  static ServerConnectionCode ServerConnectionCodeFromNetError(
932cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      int error_code);
942cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor};
952cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
963397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redlstruct ServerConnectionEvent {
97b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie  HttpResponse::ServerConnectionCode connection_code;
982cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  explicit ServerConnectionEvent(HttpResponse::ServerConnectionCode code) :
992cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      connection_code(code) {}
1003397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl};
1012cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1028538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redlclass SYNC_EXPORT_PRIVATE ServerConnectionEventListener {
1032cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor public:
1042cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  virtual void OnServerConnectionEvent(const ServerConnectionEvent& event) = 0;
1053397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl protected:
1062cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  virtual ~ServerConnectionEventListener() {}
1078538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl};
1082cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1092cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorclass ServerConnectionManager;
1103397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl// A helper class that automatically notifies when the status changes.
1111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// TODO(tim): This class shouldn't be exposed outside of the implementation,
1128538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl// bug 35060.
1132cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorclass SYNC_EXPORT_PRIVATE ScopedServerStatusWatcher
1142cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    : public base::NonThreadSafe {
1153397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl public:
116df1550fc59b51681d37225934fe4e3acac321621Richard Smith  ScopedServerStatusWatcher(ServerConnectionManager* conn_mgr,
117df1550fc59b51681d37225934fe4e3acac321621Richard Smith                            HttpResponse* response);
1188538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  virtual ~ScopedServerStatusWatcher();
1192cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor private:
1202cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  ServerConnectionManager* const conn_mgr_;
1213397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  HttpResponse* const response_;
122df1550fc59b51681d37225934fe4e3acac321621Richard Smith  DISALLOW_COPY_AND_ASSIGN(ScopedServerStatusWatcher);
1238538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl};
1242cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1252cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// Use this class to interact with the sync server.
1263397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl// The ServerConnectionManager currently supports POSTing protocol buffers.
1271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump//
1281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpclass SYNC_EXPORT_PRIVATE ServerConnectionManager : public CancelationObserver {
1298538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl public:
1302cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // buffer_in - will be POSTed
1312cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // buffer_out - string will be overwritten with response
1323397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  struct PostBufferParams {
1332cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    std::string buffer_in;
1342cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    std::string buffer_out;
1350953e767ff7817f97b3ab20896b229891eeff45bJohn McCall    HttpResponse response;
1362cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  };
1372cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1383397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  // Abstract class providing network-layer functionality to the
1392cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // ServerConnectionManager. Subclasses implement this using an HTTP stack of
1402cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // their choice.
1418538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  class Connection {
1422cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor   public:
1432cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    explicit Connection(ServerConnectionManager* scm);
1443397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl    virtual ~Connection();
1452cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1468538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    // Called to initialize and perform an HTTP POST.
1472cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    virtual bool Init(const char* path,
1482cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor                      const std::string& auth_token,
1493397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl                      const std::string& payload,
1502cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor                      HttpResponse* response) = 0;
1517e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor
1527e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor    // Immediately abandons a pending HTTP POST request and unblocks caller
153c9490c000f515c29f200a1215328d8ab9a0f3818Douglas Gregor    // in Init.
1548538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    virtual void Abort() = 0;
1552cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1562cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    bool ReadBufferResponse(std::string* buffer_out, HttpResponse* response,
1573397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl                            bool require_response);
1582cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    bool ReadDownloadResponse(HttpResponse* response, std::string* buffer_out);
1592cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
160e86d78cf4754a6aef2cf9a33d847aa15338e276fBob Wilson   protected:
1618538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    std::string MakeConnectionURL(const std::string& sync_server,
1622cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor                                  const std::string& path,
1632cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor                                  bool use_ssl) const;
1643397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
1652cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    void GetServerParams(std::string* server,
1668538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl                         int* server_port,
1672cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor                         bool* use_ssl) const {
1682cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      server->assign(scm_->sync_server_);
1693397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl      *server_port = scm_->sync_server_port_;
1702cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      *use_ssl = scm_->use_ssl_;
171264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola    }
172264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola
173a49218e17bcbb1acde0245773173e2c0c42f4f19Eli Friedman    std::string buffer_;
174425ef72306d4ff6b3698b744353e5f0e56b4b884Rafael Espindola    ServerConnectionManager* scm_;
175ab8bbf4ebd3e3e6eab913cb044772a62b7581941Douglas Gregor
176264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola   private:
177f85e193739c953358c865005855253af4f68a497John McCall    int ReadResponse(void* buffer, int length);
1782cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    int ReadResponse(std::string* buffer, int length);
1792cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  };
1803397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
1812cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  ServerConnectionManager(const std::string& server,
1828538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl                          int port,
1832cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor                          bool use_ssl,
1842cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor                          CancelationSignal* cancelation_signal);
1853397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
1862cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  virtual ~ServerConnectionManager();
1872cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1882cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // POSTS buffer_in and reads a response into buffer_out. Uses our currently
1892cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // set auth token in our headers.
1902cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  //
191eefb3d5b49c844347f212073a7e975b8118fe8e9Richard Smith  // Returns true if executed successfully.
1922cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  virtual bool PostBufferWithCachedAuth(PostBufferParams* params,
193c938c1668b4fd12af154e965dd935a89e4801a70Douglas Gregor                                        ScopedServerStatusWatcher* watcher);
19460618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl
19560618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl  void AddListener(ServerConnectionEventListener* listener);
19660618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl  void RemoveListener(ServerConnectionEventListener* listener);
19760618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl
19860618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl  inline HttpResponse::ServerConnectionCode server_status() const {
19960618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl    DCHECK(thread_checker_.CalledOnValidThread());
20060618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl    return server_status_;
2017bb698aa054de4c0e0aa23973b2c62dac9611262Richard Smith  }
2027bb698aa054de4c0e0aa23973b2c62dac9611262Richard Smith
2037bb698aa054de4c0e0aa23973b2c62dac9611262Richard Smith  const std::string client_id() const { return client_id_; }
204b9d0b76e42fd2d4cdfd135220302458d03ad09feRichard Smith
205b9d0b76e42fd2d4cdfd135220302458d03ad09feRichard Smith  // Returns the current server parameters in server_url, port and use_ssl.
20660618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl  void GetServerParameters(std::string* server_url,
2078538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl                           int* port,
2082cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor                           bool* use_ssl) const;
2092cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
2103397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  std::string GetServerHost() const;
211ed97649e9574b9d854fa4d6109c9333ae0993554John McCall
2128538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  // Factory method to create an Connection object we can use for
213ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  // communication with the server.
214ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  virtual Connection* MakeConnection();
2153397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
2162cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // Closes any active network connections to the sync server.
2179763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis  // We expect this to get called on a different thread than the valid
2189763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis  // ThreadChecker thread, as we want to kill any pending http traffic without
2198538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  // having to wait for the request to complete.
2202cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  virtual void OnSignalReceived() OVERRIDE FINAL;
2212cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
2223397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  void set_client_id(const std::string& client_id) {
223c9490c000f515c29f200a1215328d8ab9a0f3818Douglas Gregor    DCHECK(thread_checker_.CalledOnValidThread());
2248538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    DCHECK(client_id_.empty());
2252cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    client_id_.assign(client_id);
2262cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  }
2273397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
2282cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // Sets a new auth token and time.
2298538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  bool SetAuthToken(const std::string& auth_token);
2302cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
2312cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  bool HasInvalidAuthToken() {
2323397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl    return auth_token_.empty();
233f8af98286022f72157d84951b48fde5fb369ab29Douglas Gregor  }
234395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson
2358538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  const std::string auth_token() const {
236395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson    DCHECK(thread_checker_.CalledOnValidThread());
237395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson    return auth_token_;
238ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt  }
239ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt
240ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt protected:
241ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt  inline std::string proto_sync_path() const {
242ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt    return proto_sync_path_;
243ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt  }
244ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt
24534b41d939a1328f484511c6002ba2456db879a29Richard Smith  // Updates server_status_ and notifies listeners if server_status_ changed
24634b41d939a1328f484511c6002ba2456db879a29Richard Smith  void SetServerStatus(HttpResponse::ServerConnectionCode server_status);
24734b41d939a1328f484511c6002ba2456db879a29Richard Smith
24834b41d939a1328f484511c6002ba2456db879a29Richard Smith  // NOTE: Tests rely on this protected function being virtual.
24934b41d939a1328f484511c6002ba2456db879a29Richard Smith  //
2503397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  // Internal PostBuffer base function.
251be191100e034b23a3e13053757a57b7f5068c24aArgyrios Kyrtzidis  virtual bool PostBufferToPath(PostBufferParams*,
25256ca8a9c0fabd65418e9b2fd85140f4ed7d3c187Douglas Gregor                                const std::string& path,
2531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                const std::string& auth_token,
2542cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor                                ScopedServerStatusWatcher* watcher);
2552cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
2562cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // An internal helper to clear our auth_token_ and cache the old version
2573397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  // in |previously_invalidated_token_| to shelter us from retrying with a
2582cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // known bad token.
2598538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  void InvalidateAndClearAuthToken();
2602cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
2612cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // Helper to check terminated flags and build a Connection object, installing
2623397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  // it as the |active_connection_|.  If this ServerConnectionManager has been
2632cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // terminated, this will return NULL.
2648538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  Connection* MakeActiveConnection();
2652cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
2662cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // Called by Connection objects as they are destroyed to allow the
2679d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall  // ServerConnectionManager to cleanup active connections.
2689d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall  void OnConnectionDestroyed(Connection* connection);
2699d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall
2709d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall  // The sync_server_ is the server that requests will be made to.
2719d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall  std::string sync_server_;
2729d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall
2739d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall  // The sync_server_port_ is the port that HTTP requests will be made on.
2741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  int sync_server_port_;
2753397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
27649a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall  // The unique id of the user's client.
27749a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall  std::string client_id_;
27849a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall
2798538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  // Indicates whether or not requests should be made using HTTPS.
28049a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall  bool use_ssl_;
28149a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall
28249a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall  // The paths we post to.
283c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor  std::string proto_sync_path_;
284c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor
285c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor  // The auth token to use in authenticated requests.
286c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor  std::string auth_token_;
287c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor
288c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor  // The previous auth token that is invalid now.
289c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor  std::string previously_invalidated_token;
290c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor
2913397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  ObserverList<ServerConnectionEventListener> listeners_;
2922cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
293be191100e034b23a3e13053757a57b7f5068c24aArgyrios Kyrtzidis  HttpResponse::ServerConnectionCode server_status_;
29490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis
29590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  base::ThreadChecker thread_checker_;
29690b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis
29790b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  // Protects all variables below to allow bailing out of active connections.
29890b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  base::Lock terminate_connection_lock_;
2993e4c6c4c79a03f5cb0c4671d7c282d623c6dc35eRichard Smith
3003e4c6c4c79a03f5cb0c4671d7c282d623c6dc35eRichard Smith  // If true, we've been told to terminate IO and expect to be destroyed
3019763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis  // shortly.  No future network requests will be made.
3029763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis  bool terminated_;
3038538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl
30490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  // A non-owning pointer to any active http connection, so that we can abort
30590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  // it if necessary.
30690b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  Connection* active_connection_;
3073397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
308ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidis private:
309ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidis  friend class Connection;
310ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidis  friend class ScopedServerStatusWatcher;
3118538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl
31290b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  // A class to help deal with cleaning up active Connection objects when (for
31390b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  // ex) multiple early-exits are present in some scope. ScopedConnectionHelper
31490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  // informs the ServerConnectionManager before the Connection object it takes
3153397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  // ownership of is destroyed.
31690b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  class ScopedConnectionHelper {
31790b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis   public:
318b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie    // |manager| must outlive this. Takes ownership of |connection|.
31990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis    ScopedConnectionHelper(ServerConnectionManager* manager,
32090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis                           Connection* connection);
32190b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis    ~ScopedConnectionHelper();
3223397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl    Connection* get();
32390b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis   private:
32490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis    ServerConnectionManager* manager_;
32590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis    scoped_ptr<Connection> connection_;
3264fb86f8c4585e53c21c847ad3de9e3b2de123cd9Chandler Carruth    DISALLOW_COPY_AND_ASSIGN(ScopedConnectionHelper);
3278538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  };
32890b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis
32990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  void NotifyStatusChanged();
33090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis
3313397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  CancelationSignal* const cancelation_signal_;
3328dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios Kyrtzidis  bool signal_handler_registered_;
3338dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios Kyrtzidis
3348dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios Kyrtzidis  DISALLOW_COPY_AND_ASSIGN(ServerConnectionManager);
335f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidis};
336f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidis
337f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidisstd::ostream& operator<<(std::ostream& s, const struct HttpResponse& hr);
3388538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl
33990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis}  // namespace syncer
34090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis
34190b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis#endif  // SYNC_ENGINE_NET_SERVER_CONNECTION_MANAGER_H_
3423397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl