Chromium Code Reviews| Index: chrome/browser/sync/engine/net/server_connection_manager.cc |
| diff --git a/chrome/browser/sync/engine/net/server_connection_manager.cc b/chrome/browser/sync/engine/net/server_connection_manager.cc |
| index 8f00369cdb3e1fa6bfcf11af6004d8b81b216abe..d4e01386e3184990611135cd058bd9a1e8076fc9 100644 |
| --- a/chrome/browser/sync/engine/net/server_connection_manager.cc |
| +++ b/chrome/browser/sync/engine/net/server_connection_manager.cc |
| @@ -10,6 +10,7 @@ |
| #include <string> |
| #include <vector> |
| +#include "base/auto_reset.h" |
| #include "base/command_line.h" |
| #include "build/build_config.h" |
| #include "chrome/browser/sync/engine/net/url_translator.h" |
| @@ -58,7 +59,14 @@ const char* HttpResponse::GetServerConnectionCodeString( |
| #undef ENUM_CASE |
| -bool ServerConnectionManager::Post::ReadBufferResponse( |
| +ServerConnectionManager::Connection::Connection( |
| + ServerConnectionManager* scm) : scm_(scm), timing_info_(0) { |
| +} |
| + |
| +ServerConnectionManager::Connection::~Connection() { |
| +} |
| + |
| +bool ServerConnectionManager::Connection::ReadBufferResponse( |
| string* buffer_out, |
| HttpResponse* response, |
| bool require_response) { |
| @@ -79,7 +87,7 @@ bool ServerConnectionManager::Post::ReadBufferResponse( |
| return true; |
| } |
| -bool ServerConnectionManager::Post::ReadDownloadResponse( |
| +bool ServerConnectionManager::Connection::ReadDownloadResponse( |
| HttpResponse* response, |
| string* buffer_out) { |
| const int64 bytes_read = ReadResponse(buffer_out, |
| @@ -108,7 +116,7 @@ string StripTrailingSlash(const string& s) { |
| } // namespace |
| // TODO(chron): Use a GURL instead of string concatenation. |
| -string ServerConnectionManager::Post::MakeConnectionURL( |
| +string ServerConnectionManager::Connection::MakeConnectionURL( |
| const string& sync_server, |
| const string& path, |
| bool use_ssl) const { |
| @@ -120,8 +128,8 @@ string ServerConnectionManager::Post::MakeConnectionURL( |
| return connection_url; |
| } |
| -int ServerConnectionManager::Post::ReadResponse(string* out_buffer, |
| - int length) { |
| +int ServerConnectionManager::Connection::ReadResponse(string* out_buffer, |
| + int length) { |
| int bytes_read = buffer_.length(); |
| CHECK(length <= bytes_read); |
| out_buffer->assign(buffer_); |
| @@ -160,14 +168,16 @@ ServerConnectionManager::ServerConnectionManager( |
| get_time_path_(kSyncServerGetTimePath), |
| error_count_(0), |
| server_status_(HttpResponse::NONE), |
| - server_reachable_(false) { |
| + server_reachable_(false), |
| + terminated_(false), |
| + active_connection_(false) { |
| } |
| ServerConnectionManager::~ServerConnectionManager() { |
| } |
| void ServerConnectionManager::NotifyStatusChanged() { |
| - DCHECK(CalledOnValidThread()); |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| FOR_EACH_OBSERVER(ServerConnectionEventListener, listeners_, |
| OnServerConnectionEvent( |
| ServerConnectionEvent(server_status_, server_reachable_))); |
| @@ -175,7 +185,7 @@ void ServerConnectionManager::NotifyStatusChanged() { |
| bool ServerConnectionManager::PostBufferWithCachedAuth( |
| const PostBufferParams* params, ScopedServerStatusWatcher* watcher) { |
| - DCHECK(CalledOnValidThread()); |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| string path = |
| MakeSyncServerPath(proto_sync_path(), MakeSyncQueryString(client_id_)); |
| return PostBufferToPath(params, path, auth_token(), watcher); |
| @@ -184,7 +194,7 @@ bool ServerConnectionManager::PostBufferWithCachedAuth( |
| bool ServerConnectionManager::PostBufferToPath(const PostBufferParams* params, |
| const string& path, const string& auth_token, |
| ScopedServerStatusWatcher* watcher) { |
| - DCHECK(CalledOnValidThread()); |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| DCHECK(watcher != NULL); |
| if (auth_token.empty()) { |
| @@ -192,10 +202,29 @@ bool ServerConnectionManager::PostBufferToPath(const PostBufferParams* params, |
| return false; |
| } |
| - scoped_ptr<Post> post(MakePost()); |
| - post->set_timing_info(params->timing_info); |
| - bool ok = post->Init(path.c_str(), auth_token, params->buffer_in, |
| - params->response); |
| + // The AutoReset is to temporarily bind active_connection_ to the local |
| + // |post|. It's done this way to protect against a race between a call |
| + // to Abort and assignment of active_connection_. |
|
akalin
2011/08/31 07:20:39
I don't get it. What race? This still seems racy
tim (not reviewing)
2011/08/31 14:46:17
We have to make sure that if terminate is called,
|
| + scoped_ptr<Connection> post; |
| + scoped_ptr<AutoReset<Connection*> > active_connection_resetter; |
| + { |
|
akalin
2011/08/31 07:20:39
I suggest making MakeConnection() (or some non-vir
|
| + base::AutoLock lock(terminate_connection_lock_); |
| + if (terminated_) { |
| + params->response->server_status = HttpResponse::CONNECTION_UNAVAILABLE; |
| + return false; |
| + } |
| + |
| + DCHECK(!active_connection_); |
| + post.reset(MakeConnection()); |
| + active_connection_resetter.reset( |
| + new AutoReset<Connection*>(&active_connection_, post.get())); |
| + post->set_timing_info(params->timing_info); |
| + } |
| + |
| + // Note that |post| may be aborted by now, which will just cause Init to fail |
| + // with CONNECTION_UNAVAILABLE. |
| + bool ok = active_connection_->Init( |
|
akalin
2011/08/31 07:20:39
clearer to do post->Init() here, I think
|
| + path.c_str(), auth_token, params->buffer_in, params->response); |
| if (params->response->server_status == HttpResponse::SYNC_AUTH_ERROR) { |
| InvalidateAndClearAuthToken(); |
| @@ -215,7 +244,8 @@ bool ServerConnectionManager::PostBufferToPath(const PostBufferParams* params, |
| } |
| bool ServerConnectionManager::CheckTime(int32* out_time) { |
| - DCHECK(CalledOnValidThread()); |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| // Verify that the server really is reachable by checking the time. We need |
| // to do this because of wifi interstitials that intercept messages from the |
| // client and return HTTP OK instead of a redirect. |
| @@ -224,7 +254,17 @@ bool ServerConnectionManager::CheckTime(int32* out_time) { |
| string post_body = "command=get_time"; |
| for (int i = 0 ; i < 3; i++) { |
| - scoped_ptr<Post> post(MakePost()); |
| + scoped_ptr<Connection> post; |
|
akalin
2011/08/31 07:20:39
similarly as above, you can just do:
scoped_ptr<C
|
| + scoped_ptr<AutoReset<Connection*> > active_connection_resetter; |
| + { |
| + base::AutoLock lock(terminate_connection_lock_); |
| + if (terminated_) |
| + break; |
| + DCHECK(!active_connection_); |
| + post.reset(MakeConnection()); |
| + active_connection_resetter.reset( |
| + new AutoReset<Connection*>(&active_connection_, post.get())); |
| + } |
| // Note that the server's get_time path doesn't require authentication. |
| string get_time_path = |
| @@ -257,18 +297,18 @@ bool ServerConnectionManager::CheckTime(int32* out_time) { |
| } |
| bool ServerConnectionManager::IsServerReachable() { |
| - DCHECK(CalledOnValidThread()); |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| int32 time; |
| return CheckTime(&time); |
| } |
| bool ServerConnectionManager::IsUserAuthenticated() { |
| - DCHECK(CalledOnValidThread()); |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| return IsGoodReplyFromServer(server_status_); |
| } |
| bool ServerConnectionManager::CheckServerReachable() { |
| - DCHECK(CalledOnValidThread()); |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| const bool server_is_reachable = IsServerReachable(); |
| if (server_reachable_ != server_is_reachable) { |
| server_reachable_ = server_is_reachable; |
| @@ -278,7 +318,7 @@ bool ServerConnectionManager::CheckServerReachable() { |
| } |
| bool ServerConnectionManager::IncrementErrorCount() { |
| - DCHECK(CalledOnValidThread()); |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| error_count_++; |
| if (error_count_ > kMaxConnectionErrorsBeforeReset) { |
| @@ -299,7 +339,7 @@ bool ServerConnectionManager::IncrementErrorCount() { |
| void ServerConnectionManager::SetServerParameters(const string& server_url, |
| int port, |
| bool use_ssl) { |
| - DCHECK(CalledOnValidThread()); |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| sync_server_ = server_url; |
| sync_server_port_ = port; |
| use_ssl_ = use_ssl; |
| @@ -334,20 +374,32 @@ std::string ServerConnectionManager::GetServerHost() const { |
| void ServerConnectionManager::AddListener( |
| ServerConnectionEventListener* listener) { |
| - DCHECK(CalledOnValidThread()); |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| listeners_.AddObserver(listener); |
| } |
| void ServerConnectionManager::RemoveListener( |
| ServerConnectionEventListener* listener) { |
| - DCHECK(CalledOnValidThread()); |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| listeners_.RemoveObserver(listener); |
| } |
| -ServerConnectionManager::Post* ServerConnectionManager::MakePost() { |
| +ServerConnectionManager::Connection* ServerConnectionManager::MakeConnection() |
| +{ |
| return NULL; // For testing. |
| } |
| +void ServerConnectionManager::TerminateAllIO() { |
| + base::AutoLock lock(terminate_connection_lock_); |
| + terminated_ = true; |
| + if (active_connection_) |
| + active_connection_->Abort(); |
| + |
| + // Sever our ties to this connection object. Note that it still may exist, |
| + // since we don't own it, but it has been neutered. |
| + active_connection_ = NULL; |
| +} |
| + |
| bool FillMessageWithShareDetails(sync_pb::ClientToServerMessage* csm, |
| syncable::DirectoryManager* manager, |
| const std::string& share) { |