summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorchron@google.com <chron@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-17 20:44:52 +0000
committerchron@google.com <chron@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-17 20:44:52 +0000
commit7462646e2e740d7d5b1a848a524e6620047a6b34 (patch)
tree45a7d4366e80dd603077f8c886e10c0eed7957ba /chrome
parent86b423f4321ba469cf8eb15edd27cc6f2bf29ae2 (diff)
downloadchromium_src-7462646e2e740d7d5b1a848a524e6620047a6b34.zip
chromium_src-7462646e2e740d7d5b1a848a524e6620047a6b34.tar.gz
chromium_src-7462646e2e740d7d5b1a848a524e6620047a6b34.tar.bz2
Add support for the Update-Client-Auth header to sync. Add a mutex to the auth token in ServerConnectionManager.
TEST=manually tested using fiddler2 script. BUG=35321 Review URL: http://codereview.chromium.org/605010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@39259 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/net/url_fetcher.h2
-rwxr-xr-x[-rw-r--r--]chrome/browser/sync/engine/auth_watcher.cc24
-rwxr-xr-x[-rw-r--r--]chrome/browser/sync/engine/auth_watcher.h5
-rwxr-xr-x[-rw-r--r--]chrome/browser/sync/engine/auth_watcher_unittest.cc22
-rwxr-xr-x[-rw-r--r--]chrome/browser/sync/engine/net/gaia_authenticator.cc5
-rwxr-xr-x[-rw-r--r--]chrome/browser/sync/engine/net/gaia_authenticator.h2
-rwxr-xr-x[-rw-r--r--]chrome/browser/sync/engine/net/server_connection_manager.cc2
-rwxr-xr-x[-rw-r--r--]chrome/browser/sync/engine/net/server_connection_manager.h9
-rwxr-xr-x[-rw-r--r--]chrome/browser/sync/engine/net/syncapi_server_connection_manager.cc3
-rwxr-xr-xchrome/browser/sync/engine/syncapi.cc5
-rwxr-xr-xchrome/browser/sync/engine/syncapi.h7
-rwxr-xr-xchrome/browser/sync/engine/syncer_proto_util.cc15
-rwxr-xr-xchrome/browser/sync/engine/syncer_proto_util.h2
-rwxr-xr-xchrome/browser/sync/engine/syncer_proto_util_unittest.cc9
-rw-r--r--chrome/browser/sync/engine/syncer_thread_unittest.cc10
-rwxr-xr-xchrome/browser/sync/engine/syncer_unittest.cc4
-rwxr-xr-x[-rw-r--r--]chrome/browser/sync/glue/http_bridge.cc12
-rwxr-xr-x[-rw-r--r--]chrome/browser/sync/glue/http_bridge.h3
-rwxr-xr-x[-rw-r--r--]chrome/browser/sync/glue/http_bridge_unittest.cc37
-rwxr-xr-x[-rw-r--r--]chrome/browser/sync/sessions/sync_session_context.h7
-rwxr-xr-x[-rw-r--r--]chrome/browser/sync/sessions/sync_session_unittest.cc4
-rwxr-xr-xchrome/test/sync/engine/syncer_command_test.h4
-rwxr-xr-x[-rw-r--r--]chrome/test/sync/test_http_bridge_factory.h4
23 files changed, 175 insertions, 22 deletions
diff --git a/chrome/browser/net/url_fetcher.h b/chrome/browser/net/url_fetcher.h
index 35fc37d..695f808 100644
--- a/chrome/browser/net/url_fetcher.h
+++ b/chrome/browser/net/url_fetcher.h
@@ -137,7 +137,7 @@ class URLFetcher {
// Retrieve the response headers from the request. Must only be called after
// the OnURLFetchComplete callback has run.
- net::HttpResponseHeaders* response_headers() const;
+ virtual net::HttpResponseHeaders* response_headers() const;
// Start the request. After this is called, you may not change any other
// settings.
diff --git a/chrome/browser/sync/engine/auth_watcher.cc b/chrome/browser/sync/engine/auth_watcher.cc
index 8d6c189..57fcec1 100644..100755
--- a/chrome/browser/sync/engine/auth_watcher.cc
+++ b/chrome/browser/sync/engine/auth_watcher.cc
@@ -92,6 +92,30 @@ void AuthWatcher::PersistCredentials() {
}
}
+// TODO(chron): Full integration test suite needed. http://crbug.com/35429
+void AuthWatcher::RenewAuthToken(const std::string& updated_token) {
+ message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this,
+ &AuthWatcher::DoRenewAuthToken, updated_token));
+}
+
+void AuthWatcher::DoRenewAuthToken(const std::string& updated_token) {
+ DCHECK_EQ(MessageLoop::current(), message_loop());
+ // TODO(chron): We should probably only store auth token in one place.
+ if (scm_->auth_token() == updated_token) {
+ return; // This thread is the only one writing to the SCM's auth token.
+ }
+ LOG(INFO) << "Updating auth token:" << updated_token;
+ scm_->set_auth_token(updated_token);
+ gaia_->RenewAuthToken(updated_token); // Must be on AuthWatcher thread
+ talk_mediator_->SetAuthToken(user_settings_->email(), updated_token);
+ user_settings_->SetAuthTokenForService(user_settings_->email(),
+ SYNC_SERVICE_NAME,
+ updated_token);
+
+ AuthWatcherEvent event = { AuthWatcherEvent::AUTH_RENEWED };
+ NotifyListeners(&event);
+}
+
void AuthWatcher::AuthenticateWithLsid(const std::string& lsid) {
message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this,
&AuthWatcher::DoAuthenticateWithLsid, lsid));
diff --git a/chrome/browser/sync/engine/auth_watcher.h b/chrome/browser/sync/engine/auth_watcher.h
index 0a17d95..6119401 100644..100755
--- a/chrome/browser/sync/engine/auth_watcher.h
+++ b/chrome/browser/sync/engine/auth_watcher.h
@@ -40,6 +40,7 @@ struct AuthWatcherEvent {
enum WhatHappened {
AUTHENTICATION_ATTEMPT_START,
AUTHWATCHER_DESTROYED,
+ AUTH_RENEWED, // Currently only used in testing.
AUTH_SUCCEEDED,
GAIA_AUTH_FAILED,
SERVICE_USER_NOT_SIGNED_UP,
@@ -119,6 +120,10 @@ class AuthWatcher : public base::RefCountedThreadSafe<AuthWatcher> {
Authenticate(email, password, "", "", persist_creds_to_disk);
}
+ // Use this to update only the token of the current email address.
+ void RenewAuthToken(const std::string& updated_token);
+ void DoRenewAuthToken(const std::string& updated_token);
+
// Use this version when you don't need the gaia authentication step because
// you already have a valid LSID cookie for |gaia_email|.
void AuthenticateWithLsid(const std::string& lsid);
diff --git a/chrome/browser/sync/engine/auth_watcher_unittest.cc b/chrome/browser/sync/engine/auth_watcher_unittest.cc
index 8de43e0..f2adaa5 100644..100755
--- a/chrome/browser/sync/engine/auth_watcher_unittest.cc
+++ b/chrome/browser/sync/engine/auth_watcher_unittest.cc
@@ -43,6 +43,10 @@ class GaiaAuthMockForAuthWatcher : public browser_sync::GaiaAuthenticator {
void SendBadAuthTokenForNextRequest() { use_bad_auth_token_ = true; }
+ std::string renewed_token() {
+ return renewed_token_;
+ }
+
protected:
bool PerformGaiaRequest(const AuthParams& params, AuthResults* results) {
if (params.password == kWrongPassword) {
@@ -66,9 +70,14 @@ class GaiaAuthMockForAuthWatcher : public browser_sync::GaiaAuthenticator {
return true;
}
+ void RenewAuthToken(const std::string& auth_token) {
+ renewed_token_ = auth_token;
+ }
+
private:
// Whether we should send an invalid auth token on the next request.
bool use_bad_auth_token_;
+ std::string renewed_token_;
};
class AuthWatcherTest : public testing::Test {
@@ -209,4 +218,17 @@ TEST_F(AuthWatcherTest, AuthenticateWithTokenSuccess) {
EXPECT_EQ(kUserDisplayEmail, user_email());
}
+// Just check that the thread task was properly issued.
+TEST_F(AuthWatcherTest, RenewAuthToken) {
+ auth_watcher()->Authenticate(kTestEmail, kCorrectPassword, std::string(),
+ std::string(), false);
+ EXPECT_EQ(AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START, ConsumeNextEvent());
+ EXPECT_EQ(AuthWatcherEvent::AUTH_SUCCEEDED, ConsumeNextEvent());
+
+ auth_watcher()->RenewAuthToken("updated_token");
+ EXPECT_EQ(AuthWatcherEvent::AUTH_RENEWED, ConsumeNextEvent());
+ EXPECT_EQ(gaia_auth()->renewed_token(), "updated_token");
+ EXPECT_EQ(connection()->auth_token(), "updated_token");
+}
+
} // namespace browser_sync
diff --git a/chrome/browser/sync/engine/net/gaia_authenticator.cc b/chrome/browser/sync/engine/net/gaia_authenticator.cc
index da263a9..b399220 100644..100755
--- a/chrome/browser/sync/engine/net/gaia_authenticator.cc
+++ b/chrome/browser/sync/engine/net/gaia_authenticator.cc
@@ -374,6 +374,11 @@ void GaiaAuthenticator::SetUsername(const string& username) {
auth_results_.email = username;
}
+void GaiaAuthenticator::RenewAuthToken(const string& auth_token) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ DCHECK(!this->auth_token().empty());
+ auth_results_.auth_token = auth_token;
+}
void GaiaAuthenticator::SetAuthToken(const string& auth_token,
SaveCredentials save) {
DCHECK_EQ(MessageLoop::current(), message_loop_);
diff --git a/chrome/browser/sync/engine/net/gaia_authenticator.h b/chrome/browser/sync/engine/net/gaia_authenticator.h
index 32f06de..277354c 100644..100755
--- a/chrome/browser/sync/engine/net/gaia_authenticator.h
+++ b/chrome/browser/sync/engine/net/gaia_authenticator.h
@@ -136,6 +136,8 @@ class GaiaAuthenticator {
void SetUsername(const std::string& username);
+ // Virtual for testing
+ virtual void RenewAuthToken(const std::string& auth_token);
void SetAuthToken(const std::string& auth_token, SaveCredentials);
struct AuthResults {
diff --git a/chrome/browser/sync/engine/net/server_connection_manager.cc b/chrome/browser/sync/engine/net/server_connection_manager.cc
index e89e104..f61622e 100644..100755
--- a/chrome/browser/sync/engine/net/server_connection_manager.cc
+++ b/chrome/browser/sync/engine/net/server_connection_manager.cc
@@ -169,7 +169,7 @@ bool ServerConnectionManager::PostBufferWithCachedAuth(
const PostBufferParams* params, ScopedServerStatusWatcher* watcher) {
string path =
MakeSyncServerPath(proto_sync_path(), MakeSyncQueryString(client_id_));
- return PostBufferToPath(params, path, auth_token_, watcher);
+ return PostBufferToPath(params, path, auth_token(), watcher);
}
bool ServerConnectionManager::PostBufferWithAuth(const PostBufferParams* params,
diff --git a/chrome/browser/sync/engine/net/server_connection_manager.h b/chrome/browser/sync/engine/net/server_connection_manager.h
index 200fa2e..064c64b 100644..100755
--- a/chrome/browser/sync/engine/net/server_connection_manager.h
+++ b/chrome/browser/sync/engine/net/server_connection_manager.h
@@ -89,6 +89,9 @@ struct HttpResponse {
// The size of a download request's payload.
int64 payload_length;
+ // Value of the Update-Client-Auth header.
+ std::string update_client_auth_header;
+
// Identifies the type of failure, if any.
ServerConnectionCode server_status;
};
@@ -285,10 +288,13 @@ class ServerConnectionManager {
};
void set_auth_token(const std::string& auth_token) {
+ // TODO(chron): Consider adding a message loop check here.
+ AutoLock lock(auth_token_mutex_);
auth_token_.assign(auth_token);
}
- const std::string& auth_token() const {
+ const std::string auth_token() const {
+ AutoLock lock(auth_token_mutex_);
return auth_token_;
}
@@ -338,6 +344,7 @@ class ServerConnectionManager {
std::string proto_sync_path_;
std::string get_time_path_;
+ mutable Lock auth_token_mutex_;
// The auth token to use in authenticated requests. Set by the AuthWatcher.
std::string auth_token_;
diff --git a/chrome/browser/sync/engine/net/syncapi_server_connection_manager.cc b/chrome/browser/sync/engine/net/syncapi_server_connection_manager.cc
index 84c7237..d5b387e 100644..100755
--- a/chrome/browser/sync/engine/net/syncapi_server_connection_manager.cc
+++ b/chrome/browser/sync/engine/net/syncapi_server_connection_manager.cc
@@ -55,6 +55,9 @@ bool SyncAPIBridgedPost::Init(const char* path, const string& auth_token,
else
response->server_status = HttpResponse::SYNC_SERVER_ERROR;
+ response->update_client_auth_header =
+ http->GetResponseHeaderValue("Update-Client-Auth");
+
// Write the content into our buffer.
buffer_.assign(http->GetResponseContent(), http->GetResponseContentLength());
diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc
index 82d5a21..069adf2 100755
--- a/chrome/browser/sync/engine/syncapi.cc
+++ b/chrome/browser/sync/engine/syncapi.cc
@@ -1070,7 +1070,7 @@ class SyncManager::SyncInternal {
return true;
return false;
}
-
+
bool ChangeBuffersAreEmpty() {
for (int i = 0; i < syncable::MODEL_TYPE_COUNT; ++i) {
if (!change_buffers_[i].IsEmpty())
@@ -1290,7 +1290,8 @@ bool SyncManager::SyncInternal::Init(
// Build a SyncSessionContext and store the worker in it.
SyncSessionContext* context = new SyncSessionContext(
- connection_manager_.get(), dir_manager(), model_safe_worker_registrar);
+ connection_manager_.get(), auth_watcher(),
+ dir_manager(), model_safe_worker_registrar);
// The SyncerThread takes ownership of |context|.
syncer_thread_ = new SyncerThread(context, &allstatus_);
diff --git a/chrome/browser/sync/engine/syncapi.h b/chrome/browser/sync/engine/syncapi.h
index c53ad47..3656c0c 100755
--- a/chrome/browser/sync/engine/syncapi.h
+++ b/chrome/browser/sync/engine/syncapi.h
@@ -507,7 +507,7 @@ class SyncManager {
// ID of each individual item that was changed. |changes| exists only for
// the duration of the call. If items of multiple data types change at
// the same time, this method is invoked once per data type and |changes|
- // is restricted to items of the ModelType indicated by |model_type|.
+ // is restricted to items of the ModelType indicated by |model_type|.
// Because the observer is passed a |trans|, the observer can assume a
// read lock on the sync model that will be released after the function
// returns.
@@ -705,6 +705,11 @@ class HttpPostProviderInterface {
// Value should be copied.
virtual const char* GetResponseContent() const = 0;
+ // Get the value of a header returned in the HTTP response.
+ // If the header is not present, returns the empty string.
+ virtual const std::string GetResponseHeaderValue(
+ const std::string& name) const = 0;
+
private:
DISALLOW_COPY_AND_ASSIGN(HttpPostProviderInterface);
};
diff --git a/chrome/browser/sync/engine/syncer_proto_util.cc b/chrome/browser/sync/engine/syncer_proto_util.cc
index 290fe17..513b471 100755
--- a/chrome/browser/sync/engine/syncer_proto_util.cc
+++ b/chrome/browser/sync/engine/syncer_proto_util.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/sync/engine/syncer_proto_util.h"
+#include "chrome/browser/sync/engine/auth_watcher.h"
#include "chrome/browser/sync/engine/net/server_connection_manager.h"
#include "chrome/browser/sync/engine/syncer.h"
#include "chrome/browser/sync/engine/syncer_util.h"
@@ -33,7 +34,6 @@ namespace {
// Time to backoff syncing after receiving a throttled response.
static const int kSyncDelayAfterThrottled = 2 * 60 * 60; // 2 hours
-
void LogResponseProfilingData(const ClientToServerResponse& response) {
if (response.has_profiling_data()) {
stringstream response_trace;
@@ -116,6 +116,7 @@ void SyncerProtoUtil::AddRequestBirthday(syncable::Directory* dir,
// static
bool SyncerProtoUtil::PostAndProcessHeaders(ServerConnectionManager* scm,
+ AuthWatcher* auth_watcher,
ClientToServerMessage* msg,
ClientToServerResponse* response) {
@@ -132,6 +133,17 @@ bool SyncerProtoUtil::PostAndProcessHeaders(ServerConnectionManager* scm,
LOG(WARNING) << "Error posting from syncer:" << http_response;
return false;
} else {
+ std::string new_token =
+ http_response.update_client_auth_header;
+ if (!new_token.empty()) {
+ // We could also do this in the SCM's PostBufferWithAuth.
+ // But then we could be in the middle of authentication, which seems
+ // like a bad time to update the token. A consequence of this is that
+ // we can't reset the cookie in response to auth attempts, but this
+ // should be OK.
+ auth_watcher->RenewAuthToken(new_token);
+ }
+
if (response->ParseFromString(rx)) {
// TODO(tim): This is an egregious layering violation (bug 35060).
switch (response->error_code()) {
@@ -165,6 +177,7 @@ bool SyncerProtoUtil::PostClientToServerMessage(ClientToServerMessage* msg,
AddRequestBirthday(dir, msg);
if (!PostAndProcessHeaders(session->context()->connection_manager(),
+ session->context()->auth_watcher(),
msg,
response)) {
return false;
diff --git a/chrome/browser/sync/engine/syncer_proto_util.h b/chrome/browser/sync/engine/syncer_proto_util.h
index 5bf7931..9a5e363 100755
--- a/chrome/browser/sync/engine/syncer_proto_util.h
+++ b/chrome/browser/sync/engine/syncer_proto_util.h
@@ -30,6 +30,7 @@ namespace sessions {
class SyncSession;
}
+class AuthWatcher;
class ClientToServerMessage;
class ServerConnectionManager;
class SyncEntity;
@@ -95,6 +96,7 @@ class SyncerProtoUtil {
// Post the message using the scm, and do some processing on the returned
// headers. Decode the server response.
static bool PostAndProcessHeaders(browser_sync::ServerConnectionManager* scm,
+ browser_sync::AuthWatcher* authwatcher,
ClientToServerMessage* msg,
sync_pb::ClientToServerResponse* response);
diff --git a/chrome/browser/sync/engine/syncer_proto_util_unittest.cc b/chrome/browser/sync/engine/syncer_proto_util_unittest.cc
index a856e6b..56ee0f0 100755
--- a/chrome/browser/sync/engine/syncer_proto_util_unittest.cc
+++ b/chrome/browser/sync/engine/syncer_proto_util_unittest.cc
@@ -236,13 +236,16 @@ TEST_F(SyncerProtoUtilTest, PostAndProcessHeaders) {
ClientToServerResponse response;
dcm.set_send_error(true);
- EXPECT_FALSE(SyncerProtoUtil::PostAndProcessHeaders(&dcm, &msg, &response));
+ EXPECT_FALSE(SyncerProtoUtil::PostAndProcessHeaders(&dcm, NULL,
+ &msg, &response));
dcm.set_send_error(false);
- EXPECT_TRUE(SyncerProtoUtil::PostAndProcessHeaders(&dcm, &msg, &response));
+ EXPECT_TRUE(SyncerProtoUtil::PostAndProcessHeaders(&dcm, NULL,
+ &msg, &response));
dcm.set_access_denied(true);
- EXPECT_FALSE(SyncerProtoUtil::PostAndProcessHeaders(&dcm, &msg, &response));
+ EXPECT_FALSE(SyncerProtoUtil::PostAndProcessHeaders(&dcm, NULL,
+ &msg, &response));
}
} // namespace browser_sync
diff --git a/chrome/browser/sync/engine/syncer_thread_unittest.cc b/chrome/browser/sync/engine/syncer_thread_unittest.cc
index 5487e07..2f9c9b6 100644
--- a/chrome/browser/sync/engine/syncer_thread_unittest.cc
+++ b/chrome/browser/sync/engine/syncer_thread_unittest.cc
@@ -36,7 +36,7 @@ class SyncerThreadWithSyncerTest : public testing::Test,
allstatus_.reset(new AllStatus());
worker_ = new ModelSafeWorker();
SyncSessionContext* context = new SyncSessionContext(connection_.get(),
- metadb_.manager(), this);
+ NULL, metadb_.manager(), this);
syncer_thread_ = new SyncerThread(context, allstatus_.get());
syncer_event_hookup_.reset(
NewEventListenerHookup(syncer_thread_->relay_channel(), this,
@@ -150,12 +150,12 @@ class SyncShareIntercept
};
TEST_F(SyncerThreadTest, Construction) {
- SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL);
+ SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL, NULL);
scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context, NULL));
}
TEST_F(SyncerThreadTest, StartStop) {
- SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL);
+ SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL, NULL);
scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context, NULL));
EXPECT_TRUE(syncer_thread->Start());
EXPECT_TRUE(syncer_thread->Stop(2000));
@@ -167,7 +167,7 @@ TEST_F(SyncerThreadTest, StartStop) {
}
TEST_F(SyncerThreadTest, CalculateSyncWaitTime) {
- SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL);
+ SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL, NULL);
scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context, NULL));
syncer_thread->DisableIdleDetection();
@@ -227,7 +227,7 @@ TEST_F(SyncerThreadTest, CalculateSyncWaitTime) {
TEST_F(SyncerThreadTest, CalculatePollingWaitTime) {
// Set up the environment.
int user_idle_milliseconds_param = 0;
- SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL);
+ SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL, NULL);
scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context, NULL));
syncer_thread->DisableIdleDetection();
// Hold the lock to appease asserts in code.
diff --git a/chrome/browser/sync/engine/syncer_unittest.cc b/chrome/browser/sync/engine/syncer_unittest.cc
index 7805dae..80c909b 100755
--- a/chrome/browser/sync/engine/syncer_unittest.cc
+++ b/chrome/browser/sync/engine/syncer_unittest.cc
@@ -174,8 +174,8 @@ class SyncerTest : public testing::Test,
new MockConnectionManager(syncdb_.manager(), syncdb_.name()));
EnableDatatype(syncable::BOOKMARKS);
worker_ = new ModelSafeWorker();
- context_.reset(new SyncSessionContext(mock_server_.get(), syncdb_.manager(),
- this));
+ context_.reset(new SyncSessionContext(mock_server_.get(), NULL,
+ syncdb_.manager(), this));
context_->set_account_name(syncdb_.name());
ASSERT_FALSE(context_->syncer_event_channel());
ASSERT_FALSE(context_->resolver());
diff --git a/chrome/browser/sync/glue/http_bridge.cc b/chrome/browser/sync/glue/http_bridge.cc
index bf54eeb..37ae729 100644..100755
--- a/chrome/browser/sync/glue/http_bridge.cc
+++ b/chrome/browser/sync/glue/http_bridge.cc
@@ -13,6 +13,7 @@
#include "net/base/load_flags.h"
#include "net/http/http_cache.h"
#include "net/http/http_network_layer.h"
+#include "net/http/http_response_headers.h"
#include "net/proxy/proxy_service.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_status.h"
@@ -198,6 +199,16 @@ const char* HttpBridge::GetResponseContent() const {
return response_content_.data();
}
+const std::string HttpBridge::GetResponseHeaderValue(
+ const std::string& name) const {
+
+ DCHECK_EQ(MessageLoop::current(), created_on_loop_);
+ DCHECK(request_completed_);
+ std::string value;
+ response_headers_->EnumerateHeader(NULL, name, &value);
+ return value;
+}
+
void HttpBridge::OnURLFetchComplete(const URLFetcher *source, const GURL &url,
const URLRequestStatus &status,
int response_code,
@@ -211,6 +222,7 @@ void HttpBridge::OnURLFetchComplete(const URLFetcher *source, const GURL &url,
os_error_code_ = status.os_error();
response_content_ = data;
+ response_headers_ = source->response_headers();
// End of the line for url_poster_. It lives only on the IO loop.
// We defer deletion because we're inside a callback from a component of the
diff --git a/chrome/browser/sync/glue/http_bridge.h b/chrome/browser/sync/glue/http_bridge.h
index 5287344..216544d 100644..100755
--- a/chrome/browser/sync/glue/http_bridge.h
+++ b/chrome/browser/sync/glue/http_bridge.h
@@ -114,6 +114,8 @@ class HttpBridge : public base::RefCountedThreadSafe<HttpBridge>,
// string r(b->GetResponseContent(), b->GetResponseContentLength()).
virtual int GetResponseContentLength() const;
virtual const char* GetResponseContent() const;
+ virtual const std::string GetResponseHeaderValue(
+ const std::string& name) const;
// URLFetcher::Delegate implementation.
virtual void OnURLFetchComplete(const URLFetcher* source, const GURL& url,
@@ -169,6 +171,7 @@ class HttpBridge : public base::RefCountedThreadSafe<HttpBridge>,
std::string content_type_;
std::string request_content_;
std::string extra_headers_;
+ scoped_refptr<net::HttpResponseHeaders> response_headers_;
// Cached response data.
bool request_completed_;
diff --git a/chrome/browser/sync/glue/http_bridge_unittest.cc b/chrome/browser/sync/glue/http_bridge_unittest.cc
index e11e830..1f30c38 100644..100755
--- a/chrome/browser/sync/glue/http_bridge_unittest.cc
+++ b/chrome/browser/sync/glue/http_bridge_unittest.cc
@@ -4,6 +4,7 @@
#include "base/thread.h"
#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/net/test_url_fetcher_factory.h"
#include "chrome/browser/sync/glue/http_bridge.h"
#include "net/url_request/url_request_unittest.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -77,6 +78,15 @@ class HttpBridgeTest : public testing::Test {
};
+class DummyURLFetcher : public TestURLFetcher {
+ public:
+ DummyURLFetcher() : TestURLFetcher(GURL(), POST, NULL) {}
+
+ net::HttpResponseHeaders* response_headers() const {
+ return NULL;
+ }
+};
+
// An HttpBridge that doesn't actually make network requests and just calls
// back with dummy response info.
class ShuntedHttpBridge : public HttpBridge {
@@ -103,7 +113,8 @@ class ShuntedHttpBridge : public HttpBridge {
ResponseCookies cookies;
std::string response_content = "success!";
- OnURLFetchComplete(NULL, GURL("www.google.com"), URLRequestStatus(),
+ DummyURLFetcher fetcher;
+ OnURLFetchComplete(&fetcher, GURL("www.google.com"), URLRequestStatus(),
200, cookies, response_content);
}
HttpBridgeTest* test_;
@@ -226,3 +237,27 @@ TEST_F(HttpBridgeTest, TestExtraRequestHeaders) {
EXPECT_NE(std::string::npos, response.find("fnord"));
EXPECT_NE(std::string::npos, response.find(test_payload.c_str()));
}
+
+TEST_F(HttpBridgeTest, TestResponseHeader) {
+ scoped_refptr<HTTPTestServer> server =
+ HTTPTestServer::CreateServer(kDocRoot, NULL);
+ ASSERT_TRUE(NULL != server.get());
+ scoped_refptr<HttpBridge> http_bridge(BuildBridge());
+
+ GURL echo_header = server->TestServerPage("echoall");
+ http_bridge->SetURL(echo_header.spec().c_str(), echo_header.IntPort());
+
+ std::string test_payload = "###TEST PAYLOAD###";
+ http_bridge->SetPostPayload("text/html", test_payload.length() + 1,
+ test_payload.c_str());
+
+ int os_error = 0;
+ int response_code = 0;
+ bool success = http_bridge->MakeSynchronousPost(&os_error, &response_code);
+ EXPECT_TRUE(success);
+ EXPECT_EQ(200, response_code);
+ EXPECT_EQ(0, os_error);
+
+ EXPECT_EQ(http_bridge->GetResponseHeaderValue("Content-type"), "text/html");
+ EXPECT_TRUE(http_bridge->GetResponseHeaderValue("invalid-header").empty());
+}
diff --git a/chrome/browser/sync/sessions/sync_session_context.h b/chrome/browser/sync/sessions/sync_session_context.h
index 3565ec6..494fbdc 100644..100755
--- a/chrome/browser/sync/sessions/sync_session_context.h
+++ b/chrome/browser/sync/sessions/sync_session_context.h
@@ -30,6 +30,7 @@ class DirectoryManager;
namespace browser_sync {
+class AuthWatcher;
class ConflictResolver;
class ModelSafeWorkerRegistrar;
class ServerConnectionManager;
@@ -41,11 +42,13 @@ class ScopedSessionContextSyncerEventChannel;
class SyncSessionContext {
public:
SyncSessionContext(ServerConnectionManager* connection_manager,
+ AuthWatcher* auth_watcher,
syncable::DirectoryManager* directory_manager,
ModelSafeWorkerRegistrar* model_safe_worker_registrar)
: resolver_(NULL),
syncer_event_channel_(NULL),
connection_manager_(connection_manager),
+ auth_watcher_(auth_watcher),
directory_manager_(directory_manager),
registrar_(model_safe_worker_registrar),
extensions_activity_monitor_(new ExtensionsActivityMonitor()),
@@ -64,6 +67,9 @@ class SyncSessionContext {
ServerConnectionManager* connection_manager() {
return connection_manager_;
}
+ AuthWatcher* auth_watcher() {
+ return auth_watcher_;
+ }
syncable::DirectoryManager* directory_manager() {
return directory_manager_;
}
@@ -102,6 +108,7 @@ class SyncSessionContext {
SyncerEventChannel* syncer_event_channel_;
ServerConnectionManager* const connection_manager_;
+ AuthWatcher* const auth_watcher_;
syncable::DirectoryManager* const directory_manager_;
// A registrar of workers capable of processing work closures on a thread
diff --git a/chrome/browser/sync/sessions/sync_session_unittest.cc b/chrome/browser/sync/sessions/sync_session_unittest.cc
index a50a06b..7e82f83 100644..100755
--- a/chrome/browser/sync/sessions/sync_session_unittest.cc
+++ b/chrome/browser/sync/sessions/sync_session_unittest.cc
@@ -26,7 +26,7 @@ class SyncSessionTest : public testing::Test,
GetModelSafeRoutingInfo(&routes_);
}
virtual void SetUp() {
- context_.reset(new SyncSessionContext(NULL, NULL, this));
+ context_.reset(new SyncSessionContext(NULL, NULL, NULL, this));
session_.reset(new SyncSession(context_.get(), this));
}
virtual void TearDown() {
@@ -89,7 +89,7 @@ TEST_F(SyncSessionTest, SetWriteTransaction) {
TestDirectorySetterUpper db;
db.SetUp();
session_.reset(NULL);
- context_.reset(new SyncSessionContext(NULL, db.manager(), this));
+ context_.reset(new SyncSessionContext(NULL, NULL, db.manager(), this));
session_.reset(new SyncSession(context_.get(), this));
context_->set_account_name(db.name());
syncable::ScopedDirLookup dir(context_->directory_manager(),
diff --git a/chrome/test/sync/engine/syncer_command_test.h b/chrome/test/sync/engine/syncer_command_test.h
index 1e3e799..a8814ac 100755
--- a/chrome/test/sync/engine/syncer_command_test.h
+++ b/chrome/test/sync/engine/syncer_command_test.h
@@ -55,8 +55,8 @@ class SyncerCommandTest : public testing::Test,
virtual ~SyncerCommandTest() {}
virtual void SetUp() {
syncdb_.SetUp();
- context_.reset(new sessions::SyncSessionContext(NULL, syncdb_.manager(),
- registrar()));
+ context_.reset(new sessions::SyncSessionContext(NULL, NULL,
+ syncdb_.manager(), registrar()));
context_->set_account_name(syncdb_.name());
}
virtual void TearDown() {
diff --git a/chrome/test/sync/test_http_bridge_factory.h b/chrome/test/sync/test_http_bridge_factory.h
index 21f24d7..a9fc0b4 100644..100755
--- a/chrome/test/sync/test_http_bridge_factory.h
+++ b/chrome/test/sync/test_http_bridge_factory.h
@@ -46,6 +46,10 @@ class TestHttpBridge : public sync_api::HttpPostProviderInterface {
virtual const char* GetResponseContent() const {
return 0;
}
+
+ virtual const std::string GetResponseHeaderValue(const std::string &) const {
+ return std::string();
+ }
};
class TestHttpBridgeFactory : public sync_api::HttpPostProviderFactory {