summaryrefslogtreecommitdiffstats
path: root/sync
diff options
context:
space:
mode:
authorakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-22 12:11:37 +0000
committerakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-22 12:11:37 +0000
commit5d5c13d1df9ffe304f595ea886092a75d4be381e (patch)
tree24df0b3f3ccd708fcb555a9320e46837f519cbe5 /sync
parenta1733df46d06f88f1d212de14a0ba352a5383731 (diff)
downloadchromium_src-5d5c13d1df9ffe304f595ea886092a75d4be381e.zip
chromium_src-5d5c13d1df9ffe304f595ea886092a75d4be381e.tar.gz
chromium_src-5d5c13d1df9ffe304f595ea886092a75d4be381e.tar.bz2
[Sync] Move HttpBridge to sync/
Remove all references to content in HttpBridge. Clean up handling of HTTP user agent in HttpBridge. BUG=133791 TEST= Review URL: https://chromiumcodereview.appspot.com/10645004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@143575 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sync')
-rw-r--r--sync/engine/net/server_connection_manager.cc4
-rw-r--r--sync/engine/net/server_connection_manager.h8
-rw-r--r--sync/engine/syncer_proto_util_unittest.cc2
-rw-r--r--sync/internal_api/DEPS4
-rw-r--r--sync/internal_api/http_bridge.cc317
-rw-r--r--sync/internal_api/http_bridge_unittest.cc404
-rw-r--r--sync/internal_api/public/http_bridge.h232
-rw-r--r--sync/internal_api/public/http_post_provider_interface.h4
-rw-r--r--sync/internal_api/public/sync_manager.h4
-rw-r--r--sync/internal_api/sync_manager.cc6
-rw-r--r--sync/internal_api/syncapi_server_connection_manager.cc4
-rw-r--r--sync/internal_api/syncapi_server_connection_manager.h1
-rw-r--r--sync/internal_api/syncapi_server_connection_manager_unittest.cc5
-rw-r--r--sync/internal_api/syncapi_unittest.cc3
-rw-r--r--sync/sync.gyp5
-rw-r--r--sync/test/engine/mock_connection_manager.cc2
16 files changed, 971 insertions, 34 deletions
diff --git a/sync/engine/net/server_connection_manager.cc b/sync/engine/net/server_connection_manager.cc
index 92f083e..152223a 100644
--- a/sync/engine/net/server_connection_manager.cc
+++ b/sync/engine/net/server_connection_manager.cc
@@ -168,11 +168,9 @@ ScopedServerStatusWatcher::~ScopedServerStatusWatcher() {
ServerConnectionManager::ServerConnectionManager(
const string& server,
int port,
- bool use_ssl,
- const string& user_agent)
+ bool use_ssl)
: sync_server_(server),
sync_server_port_(port),
- user_agent_(user_agent),
use_ssl_(use_ssl),
proto_sync_path_(kSyncServerSyncPath),
get_time_path_(kSyncServerGetTimePath),
diff --git a/sync/engine/net/server_connection_manager.h b/sync/engine/net/server_connection_manager.h
index 4083ba2..c61352e 100644
--- a/sync/engine/net/server_connection_manager.h
+++ b/sync/engine/net/server_connection_manager.h
@@ -176,8 +176,7 @@ class ServerConnectionManager {
ServerConnectionManager(const std::string& server,
int port,
- bool use_ssl,
- const std::string& user_agent);
+ bool use_ssl);
virtual ~ServerConnectionManager();
@@ -191,8 +190,6 @@ class ServerConnectionManager {
void AddListener(ServerConnectionEventListener* listener);
void RemoveListener(ServerConnectionEventListener* listener);
- inline std::string user_agent() const { return user_agent_; }
-
inline HttpResponse::ServerConnectionCode server_status() const {
DCHECK(thread_checker_.CalledOnValidThread());
return server_status_;
@@ -287,9 +284,6 @@ class ServerConnectionManager {
// The unique id of the user's client.
std::string client_id_;
- // The user-agent string for HTTP.
- std::string user_agent_;
-
// Indicates whether or not requests should be made using HTTPS.
bool use_ssl_;
diff --git a/sync/engine/syncer_proto_util_unittest.cc b/sync/engine/syncer_proto_util_unittest.cc
index 753e490..b0c9f6e 100644
--- a/sync/engine/syncer_proto_util_unittest.cc
+++ b/sync/engine/syncer_proto_util_unittest.cc
@@ -206,7 +206,7 @@ TEST_F(SyncerProtoUtilTest, AddRequestBirthday) {
class DummyConnectionManager : public csync::ServerConnectionManager {
public:
DummyConnectionManager()
- : ServerConnectionManager("unused", 0, false, "version"),
+ : ServerConnectionManager("unused", 0, false),
send_error_(false),
access_denied_(false) {}
diff --git a/sync/internal_api/DEPS b/sync/internal_api/DEPS
index 955b31e..ab23f90 100644
--- a/sync/internal_api/DEPS
+++ b/sync/internal_api/DEPS
@@ -1,8 +1,6 @@
include_rules = [
"+googleurl",
- "+net/base/net_errors.h",
- "+net/base/network_change_notifier.h",
- "+net/http/http_status_code.h",
+ "+net",
"+sync/engine",
"+sync/js",
"+sync/notifier",
diff --git a/sync/internal_api/http_bridge.cc b/sync/internal_api/http_bridge.cc
new file mode 100644
index 0000000..6aa6c4a
--- /dev/null
+++ b/sync/internal_api/http_bridge.cc
@@ -0,0 +1,317 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/internal_api/public/http_bridge.h"
+
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "base/string_number_conversions.h"
+#include "net/base/host_resolver.h"
+#include "net/base/load_flags.h"
+#include "net/base/net_errors.h"
+#include "net/cookies/cookie_monster.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_fetcher.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_status.h"
+
+namespace browser_sync {
+
+HttpBridge::RequestContextGetter::RequestContextGetter(
+ net::URLRequestContextGetter* baseline_context_getter,
+ const std::string& user_agent)
+ : baseline_context_getter_(baseline_context_getter),
+ network_task_runner_(
+ baseline_context_getter_->GetNetworkTaskRunner()),
+ user_agent_(user_agent) {
+ DCHECK(baseline_context_getter_);
+ DCHECK(network_task_runner_);
+ DCHECK(!user_agent_.empty());
+}
+
+HttpBridge::RequestContextGetter::~RequestContextGetter() {}
+
+net::URLRequestContext*
+HttpBridge::RequestContextGetter::GetURLRequestContext() {
+ // Lazily create the context.
+ if (!context_.get()) {
+ net::URLRequestContext* baseline_context =
+ baseline_context_getter_->GetURLRequestContext();
+ context_.reset(
+ new RequestContext(baseline_context, GetNetworkTaskRunner(),
+ user_agent_));
+ baseline_context_getter_ = NULL;
+ }
+
+ return context_.get();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+HttpBridge::RequestContextGetter::GetNetworkTaskRunner() const {
+ return network_task_runner_;
+}
+
+HttpBridgeFactory::HttpBridgeFactory(
+ net::URLRequestContextGetter* baseline_context_getter,
+ const std::string& user_agent)
+ : request_context_getter_(
+ new HttpBridge::RequestContextGetter(
+ baseline_context_getter, user_agent)) {}
+
+HttpBridgeFactory::~HttpBridgeFactory() {
+}
+
+csync::HttpPostProviderInterface* HttpBridgeFactory::Create() {
+ HttpBridge* http = new HttpBridge(request_context_getter_);
+ http->AddRef();
+ return http;
+}
+
+void HttpBridgeFactory::Destroy(csync::HttpPostProviderInterface* http) {
+ static_cast<HttpBridge*>(http)->Release();
+}
+
+HttpBridge::RequestContext::RequestContext(
+ net::URLRequestContext* baseline_context,
+ const scoped_refptr<base::SingleThreadTaskRunner>&
+ network_task_runner,
+ const std::string& user_agent)
+ : baseline_context_(baseline_context),
+ network_task_runner_(network_task_runner),
+ user_agent_(user_agent) {
+ DCHECK(!user_agent_.empty());
+
+ // Create empty, in-memory cookie store.
+ set_cookie_store(new net::CookieMonster(NULL, NULL));
+
+ // We don't use a cache for bridged loads, but we do want to share proxy info.
+ set_host_resolver(baseline_context->host_resolver());
+ set_proxy_service(baseline_context->proxy_service());
+ set_ssl_config_service(baseline_context->ssl_config_service());
+
+ // We want to share the HTTP session data with the network layer factory,
+ // which includes auth_cache for proxies.
+ // Session is not refcounted so we need to be careful to not lose the parent
+ // context.
+ net::HttpNetworkSession* session =
+ baseline_context->http_transaction_factory()->GetSession();
+ DCHECK(session);
+ set_http_transaction_factory(new net::HttpNetworkLayer(session));
+
+ // TODO(timsteele): We don't currently listen for pref changes of these
+ // fields or CookiePolicy; I'm not sure we want to strictly follow the
+ // default settings, since for example if the user chooses to block all
+ // cookies, sync will start failing. Also it seems like accept_lang/charset
+ // should be tied to whatever the sync servers expect (if anything). These
+ // fields should probably just be settable by sync backend; though we should
+ // figure out if we need to give the user explicit control over policies etc.
+ set_accept_language(baseline_context->accept_language());
+ set_accept_charset(baseline_context->accept_charset());
+
+ set_net_log(baseline_context->net_log());
+}
+
+HttpBridge::RequestContext::~RequestContext() {
+ DCHECK(network_task_runner_->BelongsToCurrentThread());
+ delete http_transaction_factory();
+}
+
+const std::string& HttpBridge::RequestContext::GetUserAgent(
+ const GURL& url) const {
+ return user_agent_;
+}
+
+HttpBridge::URLFetchState::URLFetchState() : url_poster(NULL),
+ aborted(false),
+ request_completed(false),
+ request_succeeded(false),
+ http_response_code(-1),
+ error_code(-1) {}
+HttpBridge::URLFetchState::~URLFetchState() {}
+
+HttpBridge::HttpBridge(HttpBridge::RequestContextGetter* context_getter)
+ : context_getter_for_request_(context_getter),
+ network_task_runner_(
+ context_getter_for_request_->GetNetworkTaskRunner()),
+ created_on_loop_(MessageLoop::current()),
+ http_post_completed_(false, false) {
+}
+
+HttpBridge::~HttpBridge() {
+}
+
+void HttpBridge::SetExtraRequestHeaders(const char * headers) {
+ DCHECK(extra_headers_.empty())
+ << "HttpBridge::SetExtraRequestHeaders called twice.";
+ extra_headers_.assign(headers);
+}
+
+void HttpBridge::SetURL(const char* url, int port) {
+ DCHECK_EQ(MessageLoop::current(), created_on_loop_);
+ if (DCHECK_IS_ON()) {
+ base::AutoLock lock(fetch_state_lock_);
+ DCHECK(!fetch_state_.request_completed);
+ }
+ DCHECK(url_for_request_.is_empty())
+ << "HttpBridge::SetURL called more than once?!";
+ GURL temp(url);
+ GURL::Replacements replacements;
+ std::string port_str = base::IntToString(port);
+ replacements.SetPort(port_str.c_str(),
+ url_parse::Component(0, port_str.length()));
+ url_for_request_ = temp.ReplaceComponents(replacements);
+}
+
+void HttpBridge::SetPostPayload(const char* content_type,
+ int content_length,
+ const char* content) {
+ DCHECK_EQ(MessageLoop::current(), created_on_loop_);
+ if (DCHECK_IS_ON()) {
+ base::AutoLock lock(fetch_state_lock_);
+ DCHECK(!fetch_state_.request_completed);
+ }
+ DCHECK(content_type_.empty()) << "Bridge payload already set.";
+ DCHECK_GE(content_length, 0) << "Content length < 0";
+ content_type_ = content_type;
+ if (!content || (content_length == 0)) {
+ DCHECK_EQ(content_length, 0);
+ request_content_ = " "; // TODO(timsteele): URLFetcher requires non-empty
+ // content for POSTs whereas CURL does not, for now
+ // we hack this to support the sync backend.
+ } else {
+ request_content_.assign(content, content_length);
+ }
+}
+
+bool HttpBridge::MakeSynchronousPost(int* error_code, int* response_code) {
+ DCHECK_EQ(MessageLoop::current(), created_on_loop_);
+ if (DCHECK_IS_ON()) {
+ base::AutoLock lock(fetch_state_lock_);
+ DCHECK(!fetch_state_.request_completed);
+ }
+ DCHECK(url_for_request_.is_valid()) << "Invalid URL for request";
+ DCHECK(!content_type_.empty()) << "Payload not set";
+
+ if (!network_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&HttpBridge::CallMakeAsynchronousPost, this))) {
+ // This usually happens when we're in a unit test.
+ LOG(WARNING) << "Could not post CallMakeAsynchronousPost task";
+ return false;
+ }
+
+ // Block until network request completes or is aborted. See
+ // OnURLFetchComplete and Abort.
+ http_post_completed_.Wait();
+
+ base::AutoLock lock(fetch_state_lock_);
+ DCHECK(fetch_state_.request_completed || fetch_state_.aborted);
+ *error_code = fetch_state_.error_code;
+ *response_code = fetch_state_.http_response_code;
+ return fetch_state_.request_succeeded;
+}
+
+void HttpBridge::MakeAsynchronousPost() {
+ DCHECK(network_task_runner_->BelongsToCurrentThread());
+ base::AutoLock lock(fetch_state_lock_);
+ DCHECK(!fetch_state_.request_completed);
+ if (fetch_state_.aborted)
+ return;
+
+ fetch_state_.url_poster = net::URLFetcher::Create(
+ url_for_request_, net::URLFetcher::POST, this);
+ fetch_state_.url_poster->SetRequestContext(context_getter_for_request_);
+ fetch_state_.url_poster->SetUploadData(content_type_, request_content_);
+ fetch_state_.url_poster->SetExtraRequestHeaders(extra_headers_);
+ fetch_state_.url_poster->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES);
+ fetch_state_.url_poster->Start();
+}
+
+int HttpBridge::GetResponseContentLength() const {
+ DCHECK_EQ(MessageLoop::current(), created_on_loop_);
+ base::AutoLock lock(fetch_state_lock_);
+ DCHECK(fetch_state_.request_completed);
+ return fetch_state_.response_content.size();
+}
+
+const char* HttpBridge::GetResponseContent() const {
+ DCHECK_EQ(MessageLoop::current(), created_on_loop_);
+ base::AutoLock lock(fetch_state_lock_);
+ DCHECK(fetch_state_.request_completed);
+ return fetch_state_.response_content.data();
+}
+
+const std::string HttpBridge::GetResponseHeaderValue(
+ const std::string& name) const {
+
+ DCHECK_EQ(MessageLoop::current(), created_on_loop_);
+ base::AutoLock lock(fetch_state_lock_);
+ DCHECK(fetch_state_.request_completed);
+
+ std::string value;
+ fetch_state_.response_headers->EnumerateHeader(NULL, name, &value);
+ return value;
+}
+
+void HttpBridge::Abort() {
+ base::AutoLock lock(fetch_state_lock_);
+ DCHECK(!fetch_state_.aborted);
+ if (fetch_state_.aborted || fetch_state_.request_completed)
+ return;
+
+ fetch_state_.aborted = true;
+ if (!network_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&HttpBridge::DestroyURLFetcherOnIOThread, this,
+ fetch_state_.url_poster))) {
+ // Madness ensues.
+ NOTREACHED() << "Could not post task to delete URLFetcher";
+ }
+
+ fetch_state_.url_poster = NULL;
+ fetch_state_.error_code = net::ERR_ABORTED;
+ http_post_completed_.Signal();
+}
+
+void HttpBridge::DestroyURLFetcherOnIOThread(net::URLFetcher* fetcher) {
+ DCHECK(network_task_runner_->BelongsToCurrentThread());
+ delete fetcher;
+}
+
+void HttpBridge::OnURLFetchComplete(const net::URLFetcher* source) {
+ DCHECK(network_task_runner_->BelongsToCurrentThread());
+ base::AutoLock lock(fetch_state_lock_);
+ if (fetch_state_.aborted)
+ return;
+
+ fetch_state_.request_completed = true;
+ fetch_state_.request_succeeded =
+ (net::URLRequestStatus::SUCCESS == source->GetStatus().status());
+ fetch_state_.http_response_code = source->GetResponseCode();
+ fetch_state_.error_code = source->GetStatus().error();
+
+ // Use a real (non-debug) log to facilitate troubleshooting in the wild.
+ VLOG(2) << "HttpBridge::OnURLFetchComplete for: "
+ << fetch_state_.url_poster->GetURL().spec();
+ VLOG(1) << "HttpBridge received response code: "
+ << fetch_state_.http_response_code;
+
+ source->GetResponseAsString(&fetch_state_.response_content);
+ fetch_state_.response_headers = source->GetResponseHeaders();
+
+ // 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
+ // URLFetcher, so it seems most natural / "polite" to let the stack unwind.
+ MessageLoop::current()->DeleteSoon(FROM_HERE, fetch_state_.url_poster);
+ fetch_state_.url_poster = NULL;
+
+ // Wake the blocked syncer thread in MakeSynchronousPost.
+ // WARNING: DONT DO ANYTHING AFTER THIS CALL! |this| may be deleted!
+ http_post_completed_.Signal();
+}
+
+} // namespace browser_sync
diff --git a/sync/internal_api/http_bridge_unittest.cc b/sync/internal_api/http_bridge_unittest.cc
new file mode 100644
index 0000000..a4a4ceb
--- /dev/null
+++ b/sync/internal_api/http_bridge_unittest.cc
@@ -0,0 +1,404 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop_proxy.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "net/test/test_server.h"
+#include "net/url_request/test_url_fetcher_factory.h"
+#include "net/url_request/url_fetcher_delegate.h"
+#include "net/url_request/url_request_test_util.h"
+#include "sync/internal_api/public/http_bridge.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using browser_sync::HttpBridge;
+
+namespace {
+// TODO(timsteele): Should use PathService here. See Chromium Issue 3113.
+const FilePath::CharType kDocRoot[] = FILE_PATH_LITERAL("chrome/test/data");
+}
+
+class SyncHttpBridgeTest : public testing::Test {
+ public:
+ SyncHttpBridgeTest()
+ : test_server_(net::TestServer::TYPE_HTTP,
+ net::TestServer::kLocalhost,
+ FilePath(kDocRoot)),
+ fake_default_request_context_getter_(NULL),
+ bridge_for_race_test_(NULL),
+ io_thread_("IO thread") {
+ }
+
+ virtual void SetUp() {
+ base::Thread::Options options;
+ options.message_loop_type = MessageLoop::TYPE_IO;
+ io_thread_.StartWithOptions(options);
+ }
+
+ virtual void TearDown() {
+ if (fake_default_request_context_getter_) {
+ GetIOThreadLoop()->ReleaseSoon(FROM_HERE,
+ fake_default_request_context_getter_);
+ fake_default_request_context_getter_ = NULL;
+ }
+ io_thread_.Stop();
+ }
+
+ HttpBridge* BuildBridge() {
+ if (!fake_default_request_context_getter_) {
+ fake_default_request_context_getter_ =
+ new TestURLRequestContextGetter(io_thread_.message_loop_proxy());
+ fake_default_request_context_getter_->AddRef();
+ }
+ HttpBridge* bridge = new HttpBridge(
+ new HttpBridge::RequestContextGetter(
+ fake_default_request_context_getter_,
+ "user agent"));
+ return bridge;
+ }
+
+ static void Abort(HttpBridge* bridge) {
+ bridge->Abort();
+ }
+
+ // Used by AbortAndReleaseBeforeFetchCompletes to test an interesting race
+ // condition.
+ void RunSyncThreadBridgeUseTest(base::WaitableEvent* signal_when_created,
+ base::WaitableEvent* signal_when_released);
+
+ static void TestSameHttpNetworkSession(MessageLoop* main_message_loop,
+ SyncHttpBridgeTest* test) {
+ scoped_refptr<HttpBridge> http_bridge(test->BuildBridge());
+ EXPECT_TRUE(test->GetTestRequestContextGetter());
+ net::HttpNetworkSession* test_session =
+ test->GetTestRequestContextGetter()->GetURLRequestContext()->
+ http_transaction_factory()->GetSession();
+ EXPECT_EQ(test_session,
+ http_bridge->GetRequestContextGetter()->
+ GetURLRequestContext()->
+ http_transaction_factory()->GetSession());
+ main_message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+ }
+
+ MessageLoop* GetIOThreadLoop() {
+ return io_thread_.message_loop();
+ }
+
+ // Note this is lazy created, so don't call this before your bridge.
+ TestURLRequestContextGetter* GetTestRequestContextGetter() {
+ return fake_default_request_context_getter_;
+ }
+
+ net::TestServer test_server_;
+
+ base::Thread* io_thread() { return &io_thread_; }
+
+ HttpBridge* bridge_for_race_test() { return bridge_for_race_test_; }
+
+ private:
+ // A make-believe "default" request context, as would be returned by
+ // Profile::GetDefaultRequestContext(). Created lazily by BuildBridge.
+ TestURLRequestContextGetter* fake_default_request_context_getter_;
+
+ HttpBridge* bridge_for_race_test_;
+
+ // Separate thread for IO used by the HttpBridge.
+ base::Thread io_thread_;
+ MessageLoop loop_;
+};
+
+// An HttpBridge that doesn't actually make network requests and just calls
+// back with dummy response info.
+// TODO(tim): Instead of inheriting here we should inject a component
+// responsible for the MakeAsynchronousPost bit.
+class ShuntedHttpBridge : public HttpBridge {
+ public:
+ // If |never_finishes| is true, the simulated request never actually
+ // returns.
+ ShuntedHttpBridge(net::URLRequestContextGetter* baseline_context_getter,
+ SyncHttpBridgeTest* test, bool never_finishes)
+ : HttpBridge(
+ new HttpBridge::RequestContextGetter(
+ baseline_context_getter, "user agent")),
+ test_(test), never_finishes_(never_finishes) { }
+ protected:
+ virtual void MakeAsynchronousPost() {
+ ASSERT_TRUE(MessageLoop::current() == test_->GetIOThreadLoop());
+ if (never_finishes_)
+ return;
+
+ // We don't actually want to make a request for this test, so just callback
+ // as if it completed.
+ test_->GetIOThreadLoop()->PostTask(FROM_HERE,
+ base::Bind(&ShuntedHttpBridge::CallOnURLFetchComplete, this));
+ }
+ private:
+ ~ShuntedHttpBridge() {}
+
+ void CallOnURLFetchComplete() {
+ ASSERT_TRUE(MessageLoop::current() == test_->GetIOThreadLoop());
+ // We return no cookies and a dummy content response.
+ net::ResponseCookies cookies;
+
+ std::string response_content = "success!";
+ net::TestURLFetcher fetcher(0, GURL(), NULL);
+ fetcher.set_url(GURL("www.google.com"));
+ fetcher.set_response_code(200);
+ fetcher.set_cookies(cookies);
+ fetcher.SetResponseString(response_content);
+ OnURLFetchComplete(&fetcher);
+ }
+ SyncHttpBridgeTest* test_;
+ bool never_finishes_;
+};
+
+void SyncHttpBridgeTest::RunSyncThreadBridgeUseTest(
+ base::WaitableEvent* signal_when_created,
+ base::WaitableEvent* signal_when_released) {
+ scoped_refptr<net::URLRequestContextGetter> ctx_getter(
+ new TestURLRequestContextGetter(io_thread_.message_loop_proxy()));
+ {
+ scoped_refptr<ShuntedHttpBridge> bridge(new ShuntedHttpBridge(
+ ctx_getter, this, true));
+ bridge->SetURL("http://www.google.com", 9999);
+ bridge->SetPostPayload("text/plain", 2, " ");
+ bridge_for_race_test_ = bridge;
+ signal_when_created->Signal();
+
+ int os_error = 0;
+ int response_code = 0;
+ bridge->MakeSynchronousPost(&os_error, &response_code);
+ bridge_for_race_test_ = NULL;
+ }
+ signal_when_released->Signal();
+}
+
+TEST_F(SyncHttpBridgeTest, TestUsesSameHttpNetworkSession) {
+ // Run this test on the IO thread because we can only call
+ // URLRequestContextGetter::GetURLRequestContext on the IO thread.
+ io_thread()->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&SyncHttpBridgeTest::TestSameHttpNetworkSession,
+ MessageLoop::current(), this));
+ MessageLoop::current()->Run();
+}
+
+// Test the HttpBridge without actually making any network requests.
+TEST_F(SyncHttpBridgeTest, TestMakeSynchronousPostShunted) {
+ scoped_refptr<net::URLRequestContextGetter> ctx_getter(
+ new TestURLRequestContextGetter(io_thread()->message_loop_proxy()));
+ scoped_refptr<HttpBridge> http_bridge(new ShuntedHttpBridge(
+ ctx_getter, this, false));
+ http_bridge->SetURL("http://www.google.com", 9999);
+ http_bridge->SetPostPayload("text/plain", 2, " ");
+
+ 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(8, http_bridge->GetResponseContentLength());
+ EXPECT_EQ(std::string("success!"),
+ std::string(http_bridge->GetResponseContent()));
+}
+
+// Full round-trip test of the HttpBridge, using default UA string and
+// no request cookies.
+TEST_F(SyncHttpBridgeTest, TestMakeSynchronousPostLiveWithPayload) {
+ ASSERT_TRUE(test_server_.Start());
+
+ scoped_refptr<HttpBridge> http_bridge(BuildBridge());
+
+ std::string payload = "this should be echoed back";
+ GURL echo = test_server_.GetURL("echo");
+ http_bridge->SetURL(echo.spec().c_str(), echo.IntPort());
+ http_bridge->SetPostPayload("application/x-www-form-urlencoded",
+ payload.length() + 1, 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(payload.length() + 1,
+ static_cast<size_t>(http_bridge->GetResponseContentLength()));
+ EXPECT_EQ(payload, std::string(http_bridge->GetResponseContent()));
+}
+
+// Full round-trip test of the HttpBridge.
+TEST_F(SyncHttpBridgeTest, TestMakeSynchronousPostLiveComprehensive) {
+ ASSERT_TRUE(test_server_.Start());
+
+ scoped_refptr<HttpBridge> http_bridge(BuildBridge());
+
+ GURL echo_header = test_server_.GetURL("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);
+
+ std::string response(http_bridge->GetResponseContent(),
+ http_bridge->GetResponseContentLength());
+ EXPECT_EQ(std::string::npos, response.find("Cookie:"));
+ EXPECT_NE(std::string::npos, response.find("User-Agent: user agent"));
+ EXPECT_NE(std::string::npos, response.find(test_payload.c_str()));
+}
+
+TEST_F(SyncHttpBridgeTest, TestExtraRequestHeaders) {
+ ASSERT_TRUE(test_server_.Start());
+
+ scoped_refptr<HttpBridge> http_bridge(BuildBridge());
+
+ GURL echo_header = test_server_.GetURL("echoall");
+
+ http_bridge->SetURL(echo_header.spec().c_str(), echo_header.IntPort());
+ http_bridge->SetExtraRequestHeaders("test:fnord");
+
+ 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);
+
+ std::string response(http_bridge->GetResponseContent(),
+ http_bridge->GetResponseContentLength());
+
+ EXPECT_NE(std::string::npos, response.find("fnord"));
+ EXPECT_NE(std::string::npos, response.find(test_payload.c_str()));
+}
+
+TEST_F(SyncHttpBridgeTest, TestResponseHeader) {
+ ASSERT_TRUE(test_server_.Start());
+
+ scoped_refptr<HttpBridge> http_bridge(BuildBridge());
+
+ GURL echo_header = test_server_.GetURL("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());
+}
+
+TEST_F(SyncHttpBridgeTest, Abort) {
+ scoped_refptr<net::URLRequestContextGetter> ctx_getter(
+ new TestURLRequestContextGetter(io_thread()->message_loop_proxy()));
+ scoped_refptr<ShuntedHttpBridge> http_bridge(new ShuntedHttpBridge(
+ ctx_getter, this, true));
+ http_bridge->SetURL("http://www.google.com", 9999);
+ http_bridge->SetPostPayload("text/plain", 2, " ");
+
+ int os_error = 0;
+ int response_code = 0;
+
+ io_thread()->message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&SyncHttpBridgeTest::Abort, http_bridge));
+ bool success = http_bridge->MakeSynchronousPost(&os_error, &response_code);
+ EXPECT_FALSE(success);
+ EXPECT_EQ(net::ERR_ABORTED, os_error);
+}
+
+TEST_F(SyncHttpBridgeTest, AbortLate) {
+ scoped_refptr<net::URLRequestContextGetter> ctx_getter(
+ new TestURLRequestContextGetter(io_thread()->message_loop_proxy()));
+ scoped_refptr<ShuntedHttpBridge> http_bridge(new ShuntedHttpBridge(
+ ctx_getter, this, false));
+ http_bridge->SetURL("http://www.google.com", 9999);
+ http_bridge->SetPostPayload("text/plain", 2, " ");
+
+ int os_error = 0;
+ int response_code = 0;
+
+ bool success = http_bridge->MakeSynchronousPost(&os_error, &response_code);
+ ASSERT_TRUE(success);
+ http_bridge->Abort();
+ // Ensures no double-free of URLFetcher, etc.
+}
+
+// Tests an interesting case where code using the HttpBridge aborts the fetch
+// and releases ownership before a pending fetch completed callback is issued by
+// the underlying URLFetcher (and before that URLFetcher is destroyed, which
+// would cancel the callback).
+TEST_F(SyncHttpBridgeTest, AbortAndReleaseBeforeFetchComplete) {
+ base::Thread sync_thread("SyncThread");
+ sync_thread.Start();
+
+ // First, block the sync thread on the post.
+ base::WaitableEvent signal_when_created(false, false);
+ base::WaitableEvent signal_when_released(false, false);
+ sync_thread.message_loop()->PostTask(FROM_HERE,
+ base::Bind(&SyncHttpBridgeTest::RunSyncThreadBridgeUseTest,
+ base::Unretained(this),
+ &signal_when_created,
+ &signal_when_released));
+
+ // Stop IO so we can control order of operations.
+ base::WaitableEvent io_waiter(false, false);
+ ASSERT_TRUE(io_thread()->message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&base::WaitableEvent::Wait, base::Unretained(&io_waiter))));
+
+ signal_when_created.Wait(); // Wait till we have a bridge to abort.
+ ASSERT_TRUE(bridge_for_race_test());
+
+ // Schedule the fetch completion callback (but don't run it yet). Don't take
+ // a reference to the bridge to mimic URLFetcher's handling of the delegate.
+ net::URLFetcherDelegate* delegate =
+ static_cast<net::URLFetcherDelegate*>(bridge_for_race_test());
+ net::ResponseCookies cookies;
+ std::string response_content = "success!";
+ net::TestURLFetcher fetcher(0, GURL(), NULL);
+ fetcher.set_url(GURL("www.google.com"));
+ fetcher.set_response_code(200);
+ fetcher.set_cookies(cookies);
+ fetcher.SetResponseString(response_content);
+ ASSERT_TRUE(io_thread()->message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&net::URLFetcherDelegate::OnURLFetchComplete,
+ base::Unretained(delegate), &fetcher)));
+
+ // Abort the fetch. This should be smart enough to handle the case where
+ // the bridge is destroyed before the callback scheduled above completes.
+ bridge_for_race_test()->Abort();
+
+ // Wait until the sync thread releases its ref on the bridge.
+ signal_when_released.Wait();
+ ASSERT_FALSE(bridge_for_race_test());
+
+ // Unleash the hounds. The fetch completion callback should fire first, and
+ // succeed even though we Release()d the bridge above because the call to
+ // Abort should have held a reference.
+ io_waiter.Signal();
+
+ // Done.
+ sync_thread.Stop();
+ io_thread()->Stop();
+}
diff --git a/sync/internal_api/public/http_bridge.h b/sync/internal_api/public/http_bridge.h
new file mode 100644
index 0000000..cec5526
--- /dev/null
+++ b/sync/internal_api/public/http_bridge.h
@@ -0,0 +1,232 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SYNC_INTERNAL_API_PUBLIC_HTTP_BRIDGE_H_
+#define SYNC_INTERNAL_API_PUBLIC_HTTP_BRIDGE_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event.h"
+#include "googleurl/src/gurl.h"
+#include "net/url_request/url_fetcher_delegate.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "sync/internal_api/public/http_post_provider_factory.h"
+#include "sync/internal_api/public/http_post_provider_interface.h"
+
+class MessageLoop;
+class HttpBridgeTest;
+
+namespace net {
+class HttpResponseHeaders;
+class URLFetcher;
+}
+
+namespace browser_sync {
+
+// A bridge between the syncer and Chromium HTTP layers.
+// Provides a way for the sync backend to use Chromium directly for HTTP
+// requests rather than depending on a third party provider (e.g libcurl).
+// This is a one-time use bridge. Create one for each request you want to make.
+// It is RefCountedThreadSafe because it can PostTask to the io loop, and thus
+// needs to stick around across context switches, etc.
+class HttpBridge : public base::RefCountedThreadSafe<HttpBridge>,
+ public csync::HttpPostProviderInterface,
+ public net::URLFetcherDelegate {
+ public:
+ // A request context used for HTTP requests bridged from the sync backend.
+ // A bridged RequestContext has a dedicated in-memory cookie store and does
+ // not use a cache. Thus the same type can be used for incognito mode.
+ class RequestContext : public net::URLRequestContext {
+ public:
+ // |baseline_context| is used to obtain the accept-language,
+ // accept-charsets, and proxy service information for bridged requests.
+ // Typically |baseline_context| should be the net::URLRequestContext of the
+ // currently active profile.
+ RequestContext(
+ net::URLRequestContext* baseline_context,
+ const scoped_refptr<base::SingleThreadTaskRunner>&
+ network_task_runner,
+ const std::string& user_agent);
+
+ // The destructor MUST be called on the IO thread.
+ virtual ~RequestContext();
+
+ virtual const std::string& GetUserAgent(const GURL& url) const OVERRIDE;
+
+ private:
+ net::URLRequestContext* const baseline_context_;
+ const scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
+ const std::string user_agent_;
+
+ DISALLOW_COPY_AND_ASSIGN(RequestContext);
+ };
+
+ // Lazy-getter for RequestContext objects.
+ class RequestContextGetter : public net::URLRequestContextGetter {
+ public:
+ RequestContextGetter(
+ net::URLRequestContextGetter* baseline_context_getter,
+ const std::string& user_agent);
+
+ // net::URLRequestContextGetter implementation.
+ virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE;
+ virtual scoped_refptr<base::SingleThreadTaskRunner>
+ GetNetworkTaskRunner() const OVERRIDE;
+
+ protected:
+ virtual ~RequestContextGetter();
+
+ private:
+ scoped_refptr<net::URLRequestContextGetter> baseline_context_getter_;
+ const scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
+ // User agent to apply to the net::URLRequestContext.
+ const std::string user_agent_;
+
+ // Lazily initialized by GetURLRequestContext().
+ scoped_ptr<RequestContext> context_;
+
+ DISALLOW_COPY_AND_ASSIGN(RequestContextGetter);
+ };
+
+ explicit HttpBridge(RequestContextGetter* context);
+
+ // csync::HttpPostProvider implementation.
+ virtual void SetExtraRequestHeaders(const char* headers) OVERRIDE;
+ virtual void SetURL(const char* url, int port) OVERRIDE;
+ virtual void SetPostPayload(const char* content_type, int content_length,
+ const char* content) OVERRIDE;
+ virtual bool MakeSynchronousPost(int* error_code,
+ int* response_code) OVERRIDE;
+ virtual void Abort() OVERRIDE;
+
+ // WARNING: these response content methods are used to extract plain old data
+ // and not null terminated strings, so you should make sure you have read
+ // GetResponseContentLength() characters when using GetResponseContent. e.g
+ // string r(b->GetResponseContent(), b->GetResponseContentLength()).
+ virtual int GetResponseContentLength() const OVERRIDE;
+ virtual const char* GetResponseContent() const OVERRIDE;
+ virtual const std::string GetResponseHeaderValue(
+ const std::string& name) const OVERRIDE;
+
+ // net::URLFetcherDelegate implementation.
+ virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
+
+#if defined(UNIT_TEST)
+ net::URLRequestContextGetter* GetRequestContextGetter() const {
+ return context_getter_for_request_;
+ }
+#endif
+
+ protected:
+ friend class base::RefCountedThreadSafe<HttpBridge>;
+
+ virtual ~HttpBridge();
+
+ // Protected virtual so the unit test can override to shunt network requests.
+ virtual void MakeAsynchronousPost();
+
+ private:
+ friend class ::HttpBridgeTest;
+
+ // Called on the IO loop to issue the network request. The extra level
+ // of indirection is so that the unit test can override this behavior but we
+ // still have a function to statically pass to PostTask.
+ void CallMakeAsynchronousPost() { MakeAsynchronousPost(); }
+
+ // Used to destroy a fetcher when the bridge is Abort()ed, to ensure that
+ // a reference to |this| is held while flushing any pending fetch completion
+ // callbacks coming from the IO thread en route to finally destroying the
+ // fetcher.
+ void DestroyURLFetcherOnIOThread(net::URLFetcher* fetcher);
+
+ // Gets a customized net::URLRequestContext for bridged requests. See
+ // RequestContext definition for details.
+ const scoped_refptr<RequestContextGetter> context_getter_for_request_;
+
+ const scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
+
+ // The message loop of the thread we were created on. This is the thread that
+ // will block on MakeSynchronousPost while the IO thread fetches data from
+ // the network.
+ // This should be the main syncer thread (SyncerThread) which is what blocks
+ // on network IO through curl_easy_perform.
+ MessageLoop* const created_on_loop_;
+
+ // The URL to POST to.
+ GURL url_for_request_;
+
+ // POST payload information.
+ std::string content_type_;
+ std::string request_content_;
+ std::string extra_headers_;
+
+ // A waitable event we use to provide blocking semantics to
+ // MakeSynchronousPost. We block created_on_loop_ while the IO loop fetches
+ // network request.
+ base::WaitableEvent http_post_completed_;
+
+ struct URLFetchState {
+ URLFetchState();
+ ~URLFetchState();
+ // Our hook into the network layer is a URLFetcher. USED ONLY ON THE IO
+ // LOOP, so we can block created_on_loop_ while the fetch is in progress.
+ // NOTE: This is not a scoped_ptr for a reason. It must be deleted on the
+ // same thread that created it, which isn't the same thread |this| gets
+ // deleted on. We must manually delete url_poster_ on the IO loop.
+ net::URLFetcher* url_poster;
+
+ // Used to support 'Abort' functionality.
+ bool aborted;
+
+ // Cached response data.
+ bool request_completed;
+ bool request_succeeded;
+ int http_response_code;
+ int error_code;
+ std::string response_content;
+ scoped_refptr<net::HttpResponseHeaders> response_headers;
+ };
+
+ // This lock synchronizes use of state involved in the flow to fetch a URL
+ // using URLFetcher. Because we can Abort() from any thread, for example,
+ // this flow needs to be synchronized to gracefully clean up URLFetcher and
+ // return appropriate values in |error_code|.
+ mutable base::Lock fetch_state_lock_;
+ URLFetchState fetch_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(HttpBridge);
+};
+
+class HttpBridgeFactory : public csync::HttpPostProviderFactory {
+ public:
+ HttpBridgeFactory(
+ net::URLRequestContextGetter* baseline_context_getter,
+ const std::string& user_agent);
+ virtual ~HttpBridgeFactory();
+
+ // csync::HttpPostProviderFactory:
+ virtual csync::HttpPostProviderInterface* Create() OVERRIDE;
+ virtual void Destroy(csync::HttpPostProviderInterface* http) OVERRIDE;
+
+ private:
+ // This request context is built on top of the baseline context and shares
+ // common components.
+ HttpBridge::RequestContextGetter* GetRequestContextGetter();
+
+ const scoped_refptr<HttpBridge::RequestContextGetter>
+ request_context_getter_;
+
+ DISALLOW_COPY_AND_ASSIGN(HttpBridgeFactory);
+};
+
+} // namespace browser_sync
+
+#endif // SYNC_INTERNAL_API_PUBLIC_HTTP_BRIDGE_H_
diff --git a/sync/internal_api/public/http_post_provider_interface.h b/sync/internal_api/public/http_post_provider_interface.h
index adee0df..378e18f 100644
--- a/sync/internal_api/public/http_post_provider_interface.h
+++ b/sync/internal_api/public/http_post_provider_interface.h
@@ -16,10 +16,6 @@ namespace csync {
// want to make a subsequent POST.
class HttpPostProviderInterface {
public:
- // Use specified user agent string when POSTing. If not called a default UA
- // may be used.
- virtual void SetUserAgent(const char* user_agent) = 0;
-
// Add additional headers to the request.
virtual void SetExtraRequestHeaders(const char* headers) = 0;
diff --git a/sync/internal_api/public/sync_manager.h b/sync/internal_api/public/sync_manager.h
index 86f2b6d..3a2cf2e 100644
--- a/sync/internal_api/public/sync_manager.h
+++ b/sync/internal_api/public/sync_manager.h
@@ -368,6 +368,9 @@ class SyncManager {
// HTTP header. Used internally when collecting stats to classify clients.
// |sync_notifier| is owned and used to listen for notifications.
// |report_unrecoverable_error_function| may be NULL.
+ //
+ // TODO(akalin): Replace the |post_factory| parameter with a
+ // URLFetcher parameter.
bool Init(const FilePath& database_location,
const csync::WeakHandle<csync::JsEventHandler>&
event_handler,
@@ -381,7 +384,6 @@ class SyncManager {
csync::ExtensionsActivityMonitor*
extensions_activity_monitor,
ChangeDelegate* change_delegate,
- const std::string& user_agent,
const SyncCredentials& credentials,
csync::SyncNotifier* sync_notifier,
const std::string& restored_key_for_bootstrapping,
diff --git a/sync/internal_api/sync_manager.cc b/sync/internal_api/sync_manager.cc
index 25eee06..eb5a02d 100644
--- a/sync/internal_api/sync_manager.cc
+++ b/sync/internal_api/sync_manager.cc
@@ -204,7 +204,6 @@ class SyncManager::SyncInternal
csync::ExtensionsActivityMonitor*
extensions_activity_monitor,
ChangeDelegate* change_delegate,
- const std::string& user_agent,
const SyncCredentials& credentials,
csync::SyncNotifier* sync_notifier,
const std::string& restored_key_for_bootstrapping,
@@ -720,7 +719,6 @@ bool SyncManager::Init(
const std::vector<csync::ModelSafeWorker*>& workers,
csync::ExtensionsActivityMonitor* extensions_activity_monitor,
ChangeDelegate* change_delegate,
- const std::string& user_agent,
const SyncCredentials& credentials,
csync::SyncNotifier* sync_notifier,
const std::string& restored_key_for_bootstrapping,
@@ -743,7 +741,6 @@ bool SyncManager::Init(
workers,
extensions_activity_monitor,
change_delegate,
- user_agent,
credentials,
sync_notifier,
restored_key_for_bootstrapping,
@@ -866,7 +863,6 @@ bool SyncManager::SyncInternal::Init(
const std::vector<csync::ModelSafeWorker*>& workers,
csync::ExtensionsActivityMonitor* extensions_activity_monitor,
ChangeDelegate* change_delegate,
- const std::string& user_agent,
const SyncCredentials& credentials,
csync::SyncNotifier* sync_notifier,
const std::string& restored_key_for_bootstrapping,
@@ -905,7 +901,7 @@ bool SyncManager::SyncInternal::Init(
report_unrecoverable_error_function_));
connection_manager_.reset(new SyncAPIServerConnectionManager(
- sync_server_and_path, port, use_ssl, user_agent, post_factory));
+ sync_server_and_path, port, use_ssl, post_factory));
net::NetworkChangeNotifier::AddIPAddressObserver(this);
observing_ip_address_changes_ = true;
diff --git a/sync/internal_api/syncapi_server_connection_manager.cc b/sync/internal_api/syncapi_server_connection_manager.cc
index 078c6fc..f2abcc9 100644
--- a/sync/internal_api/syncapi_server_connection_manager.cc
+++ b/sync/internal_api/syncapi_server_connection_manager.cc
@@ -37,7 +37,6 @@ bool SyncAPIBridgedConnection::Init(const char* path,
std::string connection_url = MakeConnectionURL(sync_server, path, use_ssl);
HttpPostProviderInterface* http = post_provider_;
- http->SetUserAgent(scm_->user_agent().c_str());
http->SetURL(connection_url.c_str(), sync_server_port);
if (!auth_token.empty()) {
@@ -90,9 +89,8 @@ SyncAPIServerConnectionManager::SyncAPIServerConnectionManager(
const std::string& server,
int port,
bool use_ssl,
- const std::string& client_version,
HttpPostProviderFactory* factory)
- : ServerConnectionManager(server, port, use_ssl, client_version),
+ : ServerConnectionManager(server, port, use_ssl),
post_provider_factory_(factory) {
DCHECK(post_provider_factory_.get());
}
diff --git a/sync/internal_api/syncapi_server_connection_manager.h b/sync/internal_api/syncapi_server_connection_manager.h
index 5a3f952..9678045 100644
--- a/sync/internal_api/syncapi_server_connection_manager.h
+++ b/sync/internal_api/syncapi_server_connection_manager.h
@@ -55,7 +55,6 @@ class SyncAPIServerConnectionManager
SyncAPIServerConnectionManager(const std::string& server,
int port,
bool use_ssl,
- const std::string& client_version,
HttpPostProviderFactory* factory);
virtual ~SyncAPIServerConnectionManager();
diff --git a/sync/internal_api/syncapi_server_connection_manager_unittest.cc b/sync/internal_api/syncapi_server_connection_manager_unittest.cc
index 67b3e25..a6e34d0 100644
--- a/sync/internal_api/syncapi_server_connection_manager_unittest.cc
+++ b/sync/internal_api/syncapi_server_connection_manager_unittest.cc
@@ -29,7 +29,6 @@ class BlockingHttpPost : public HttpPostProviderInterface {
BlockingHttpPost() : wait_for_abort_(false, false) {}
virtual ~BlockingHttpPost() {}
- virtual void SetUserAgent(const char* user_agent) OVERRIDE {}
virtual void SetExtraRequestHeaders(const char* headers) OVERRIDE {}
virtual void SetURL(const char* url, int port) OVERRIDE {}
virtual void SetPostPayload(const char* content_type,
@@ -74,7 +73,7 @@ class BlockingHttpPostFactory : public HttpPostProviderFactory {
TEST(SyncAPIServerConnectionManagerTest, EarlyAbortPost) {
SyncAPIServerConnectionManager server(
- "server", 0, true, "1", new BlockingHttpPostFactory());
+ "server", 0, true, new BlockingHttpPostFactory());
ServerConnectionManager::PostBufferParams params;
ScopedServerStatusWatcher watcher(&server, &params.response);
@@ -90,7 +89,7 @@ TEST(SyncAPIServerConnectionManagerTest, EarlyAbortPost) {
TEST(SyncAPIServerConnectionManagerTest, AbortPost) {
SyncAPIServerConnectionManager server(
- "server", 0, true, "1", new BlockingHttpPostFactory());
+ "server", 0, true, new BlockingHttpPostFactory());
ServerConnectionManager::PostBufferParams params;
ScopedServerStatusWatcher watcher(&server, &params.response);
diff --git a/sync/internal_api/syncapi_unittest.cc b/sync/internal_api/syncapi_unittest.cc
index 8384de2..1d125ce 100644
--- a/sync/internal_api/syncapi_unittest.cc
+++ b/sync/internal_api/syncapi_unittest.cc
@@ -653,7 +653,6 @@ class TestHttpPostProviderInterface : public HttpPostProviderInterface {
public:
virtual ~TestHttpPostProviderInterface() {}
- virtual void SetUserAgent(const char* user_agent) OVERRIDE {}
virtual void SetExtraRequestHeaders(const char* headers) OVERRIDE {}
virtual void SetURL(const char* url, int port) OVERRIDE {}
virtual void SetPostPayload(const char* content_type,
@@ -785,7 +784,7 @@ class SyncManagerTest : public testing::Test,
"bogus", 0, false,
base::MessageLoopProxy::current(),
new TestHttpPostProviderFactory(), routing_info, workers,
- &extensions_activity_monitor_, this, "bogus",
+ &extensions_activity_monitor_, this,
credentials,
sync_notifier_mock_, "",
csync::SyncManager::TEST_IN_MEMORY,
diff --git a/sync/sync.gyp b/sync/sync.gyp
index 7fca6b9..9d4cd1f 100644
--- a/sync/sync.gyp
+++ b/sync/sync.gyp
@@ -297,6 +297,7 @@
'internal_api/public/base_transaction.h',
'internal_api/public/change_record.h',
'internal_api/public/configure_reason.h',
+ 'internal_api/public/http_bridge.h',
'internal_api/public/http_post_provider_factory.h',
'internal_api/public/http_post_provider_interface.h',
'internal_api/public/read_node.h',
@@ -312,6 +313,7 @@
'internal_api/change_reorder_buffer.h',
'internal_api/debug_info_event_listener.cc',
'internal_api/debug_info_event_listener.h',
+ 'internal_api/http_bridge.cc',
'internal_api/js_mutation_event_observer.cc',
'internal_api/js_mutation_event_observer.h',
'internal_api/js_sync_manager_observer.cc',
@@ -639,6 +641,7 @@
'dependencies': [
'../base/base.gyp:base',
'../net/net.gyp:net',
+ '../net/net.gyp:net_test_support',
'../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',
'protocol/sync_proto.gyp:sync_proto',
@@ -652,6 +655,7 @@
'export_dependent_settings': [
'../base/base.gyp:base',
'../net/net.gyp:net',
+ '../net/net.gyp:net_test_support',
'../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',
'protocol/sync_proto.gyp:sync_proto',
@@ -668,6 +672,7 @@
'sources': [
'internal_api/public/change_record_unittest.cc',
'internal_api/debug_info_event_listener_unittest.cc',
+ 'internal_api/http_bridge_unittest.cc',
'internal_api/js_mutation_event_observer_unittest.cc',
'internal_api/js_sync_manager_observer_unittest.cc',
'internal_api/syncapi_server_connection_manager_unittest.cc',
diff --git a/sync/test/engine/mock_connection_manager.cc b/sync/test/engine/mock_connection_manager.cc
index 4bf97f5..ab29b9a 100644
--- a/sync/test/engine/mock_connection_manager.cc
+++ b/sync/test/engine/mock_connection_manager.cc
@@ -41,7 +41,7 @@ using syncable::WriteTransaction;
static char kValidAuthToken[] = "AuthToken";
MockConnectionManager::MockConnectionManager(syncable::Directory* directory)
- : ServerConnectionManager("unused", 0, false, "version"),
+ : ServerConnectionManager("unused", 0, false),
server_reachable_(true),
conflict_all_commits_(false),
conflict_n_commits_(0),