diff options
author | chron@google.com <chron@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-17 20:44:52 +0000 |
---|---|---|
committer | chron@google.com <chron@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-17 20:44:52 +0000 |
commit | 7462646e2e740d7d5b1a848a524e6620047a6b34 (patch) | |
tree | 45a7d4366e80dd603077f8c886e10c0eed7957ba /chrome | |
parent | 86b423f4321ba469cf8eb15edd27cc6f2bf29ae2 (diff) | |
download | chromium_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')
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 { |