diff options
author | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-20 00:46:13 +0000 |
---|---|---|
committer | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-20 00:46:13 +0000 |
commit | 60b4db44f97540f61996863830ad122b33b00c40 (patch) | |
tree | dd732298aa0182533739a0bebb0f7e9959292731 | |
parent | 1a4a5cc452e74bd71a9702a43e8ba116900e8629 (diff) | |
download | chromium_src-60b4db44f97540f61996863830ad122b33b00c40.zip chromium_src-60b4db44f97540f61996863830ad122b33b00c40.tar.gz chromium_src-60b4db44f97540f61996863830ad122b33b00c40.tar.bz2 |
Implemented AddressWatchTask for OS X.
Added some utility methods to ServerConnectionManager.
BUG=32430
TEST=Manual testing with a laptop
Review URL: http://codereview.chromium.org/543098
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@36586 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/sync/engine/net/server_connection_manager.cc | 20 | ||||
-rw-r--r-- | chrome/browser/sync/engine/net/server_connection_manager.h | 6 | ||||
-rwxr-xr-x | chrome/browser/sync/engine/syncapi.cc | 141 | ||||
-rw-r--r-- | chrome/browser/sync/glue/sync_backend_host.h | 3 |
4 files changed, 169 insertions, 1 deletions
diff --git a/chrome/browser/sync/engine/net/server_connection_manager.cc b/chrome/browser/sync/engine/net/server_connection_manager.cc index 10c6aef..bbdef87 100644 --- a/chrome/browser/sync/engine/net/server_connection_manager.cc +++ b/chrome/browser/sync/engine/net/server_connection_manager.cc @@ -19,6 +19,7 @@ #include "chrome/browser/sync/protocol/sync.pb.h" #include "chrome/browser/sync/syncable/directory_manager.h" #include "chrome/browser/sync/util/event_sys-inl.h" +#include "googleurl/src/gurl.h" namespace browser_sync { @@ -273,6 +274,13 @@ bool ServerConnectionManager::CheckServerReachable() { return server_is_reachable; } +void ServerConnectionManager::SetServerUnreachable() { + if (server_reachable_) { + server_reachable_ = false; + NotifyStatusChanged(); + } +} + void ServerConnectionManager::kill() { { AutoLock lock(terminate_all_io_mutex_); @@ -343,6 +351,18 @@ void ServerConnectionManager::GetServerParameters(string* server_url, *use_ssl = use_ssl_; } +std::string ServerConnectionManager::GetServerHost() const { + string server_url; + int port; + bool use_ssl; + GetServerParameters(&server_url, &port, &use_ssl); + // We just want the hostname, so we don't need to switch on use_ssl. + server_url = "http://" + server_url; + GURL gurl(server_url); + DCHECK(gurl.is_valid()) << gurl; + return gurl.host(); +} + bool FillMessageWithShareDetails(sync_pb::ClientToServerMessage* csm, syncable::DirectoryManager* manager, const std::string& share) { diff --git a/chrome/browser/sync/engine/net/server_connection_manager.h b/chrome/browser/sync/engine/net/server_connection_manager.h index c34d4ae..28a2e4e 100644 --- a/chrome/browser/sync/engine/net/server_connection_manager.h +++ b/chrome/browser/sync/engine/net/server_connection_manager.h @@ -214,6 +214,10 @@ class ServerConnectionManager { // Updates status and broadcasts events on change. bool CheckServerReachable(); + // Updates server status to "unreachable" and broadcasts events if + // necessary. + void SetServerUnreachable(); + // Signal the shutdown event to notify listeners. virtual void kill(); @@ -251,6 +255,8 @@ class ServerConnectionManager { int* port, bool* use_ssl) const; + std::string GetServerHost() const; + bool terminate_all_io() const { AutoLock lock(terminate_all_io_mutex_); return terminate_all_io_; diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc index 8dcf8c5..623b779 100755 --- a/chrome/browser/sync/engine/syncapi.cc +++ b/chrome/browser/sync/engine/syncapi.cc @@ -9,6 +9,11 @@ #if defined(OS_WIN) #include <windows.h> #include <iphlpapi.h> +#elif defined(OS_MACOSX) +#include <SystemConfiguration/SCNetworkReachability.h> +#include "base/condition_variable.h" +#include "base/scoped_cftyperef.h" +#include "base/sys_string_conversions.h" #endif #if defined(OS_LINUX) @@ -25,6 +30,7 @@ #include "base/basictypes.h" #include "base/command_line.h" +#include "base/lock.h" #include "base/platform_thread.h" #include "base/scoped_ptr.h" #include "base/string_util.h" @@ -77,7 +83,9 @@ using syncable::DirectoryManager; typedef GoogleServiceAuthError AuthError; +#if defined(OS_WIN) static const int kServerReachablePollingIntervalMsec = 60000 * 60; +#endif static const int kThreadExitTimeoutMsec = 60000; static const int kSSLPort = 443; @@ -85,11 +93,90 @@ struct AddressWatchTaskParams { browser_sync::ServerConnectionManager* conn_mgr; #if defined(OS_WIN) HANDLE exit_flag; + + AddressWatchTaskParams() : conn_mgr(NULL), exit_flag() {} #elif defined(OS_LINUX) int exit_pipe[2]; + + AddressWatchTaskParams() : conn_mgr(NULL) {} +#elif defined(OS_MACOSX) + // Protects run_loop and run_loop_initialized. + Lock run_loop_lock; + // May be NULL if an error was encountered by the AddressWatchTask. + CFRunLoopRef run_loop; + bool run_loop_initialized; + // Signalled when run_loop and run_loop_initialized are set. + ConditionVariable params_set; + + AddressWatchTaskParams() + : conn_mgr(NULL), + run_loop(NULL), + run_loop_initialized(false), + params_set(&run_loop_lock) {} #endif + + private: + DISALLOW_COPY_AND_ASSIGN(AddressWatchTaskParams); }; +#if defined(OS_MACOSX) +CFStringRef NetworkReachabilityCopyDescription(const void *info) { + return base::SysUTF8ToCFStringRef( + StringPrintf("AddressWatchTask(0x%p)", info)); +} + +void NetworkReachabilityChangedCallback(SCNetworkReachabilityRef target, + SCNetworkConnectionFlags flags, + void* info) { + bool network_active = ((flags & (kSCNetworkFlagsReachable | + kSCNetworkFlagsConnectionRequired | + kSCNetworkFlagsConnectionAutomatic | + kSCNetworkFlagsInterventionRequired)) == + kSCNetworkFlagsReachable); + LOG(INFO) << "Network reachability changed: it is now " + << (network_active ? "active" : "inactive"); + AddressWatchTaskParams* params = + static_cast<AddressWatchTaskParams*>(info); + if (network_active) { + params->conn_mgr->CheckServerReachable(); + } else { + params->conn_mgr->SetServerUnreachable(); + } +} + +SCNetworkReachabilityRef CreateAndScheduleNetworkReachability( + SCNetworkReachabilityContext* network_reachability_context, + const char* nodename) { + scoped_cftyperef<SCNetworkReachabilityRef> network_reachability( + SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, nodename)); + if (!network_reachability.get()) { + LOG(WARNING) << "Could not create network reachability object"; + return NULL; + } + + if (!SCNetworkReachabilitySetCallback(network_reachability.get(), + &NetworkReachabilityChangedCallback, + network_reachability_context)) { + LOG(WARNING) << "Could not set network reachability callback"; + return NULL; + } + + if (!SCNetworkReachabilityScheduleWithRunLoop(network_reachability.get(), + CFRunLoopGetCurrent(), + kCFRunLoopDefaultMode)) { + LOG(WARNING) << "Could not schedule network reachability with run loop"; + return NULL; + } + + return network_reachability.release(); +} +#endif + +// TODO(akalin): This code needs some serious refactoring. At the +// very least, all the gross platform-specific code should be put in +// one place; ideally, the code shared between this and the network +// status detector (in sync/notifier) will be put in one place. + // This thread calls CheckServerReachable() whenever a change occurs in the // table that maps IP addresses to interfaces, for example when the user // unplugs his network cable. @@ -175,6 +262,44 @@ class AddressWatchTask : public Task { } } close(params_->exit_pipe[0]); +#elif defined(OS_MACOSX) + SCNetworkReachabilityContext network_reachability_context; + network_reachability_context.version = 0; + network_reachability_context.info = static_cast<void *>(params_); + network_reachability_context.retain = NULL; + network_reachability_context.release = NULL; + network_reachability_context.copyDescription = + &NetworkReachabilityCopyDescription; + + std::string hostname = params_->conn_mgr->GetServerHost(); + scoped_cftyperef<SCNetworkReachabilityRef> network_reachability( + CreateAndScheduleNetworkReachability( + &network_reachability_context, hostname.c_str())); + if (!network_reachability.get()) { + { + AutoLock auto_lock(params_->run_loop_lock); + params_->run_loop = NULL; + params_->run_loop_initialized = true; + } + params_->params_set.Signal(); + LOG(INFO) << "The address watch thread has stopped due to an error"; + return; + } + + CFRunLoopRef run_loop = CFRunLoopGetCurrent(); + { + AutoLock auto_lock(params_->run_loop_lock); + params_->run_loop = run_loop; + params_->run_loop_initialized = true; + } + params_->params_set.Signal(); + + CFRunLoopRun(); + + { + AutoLock auto_lock(params_->run_loop_lock); + params_->run_loop = NULL; + } #endif LOG(INFO) << "The address watch thread has stopped"; } @@ -1026,6 +1151,15 @@ bool SyncManager::SyncInternal::Init( address_watch_thread_.message_loop()->PostTask(FROM_HERE, new AddressWatchTask(&address_watch_params_)); +#if defined(OS_MACOSX) + { + AutoLock auto_lock(address_watch_params_.run_loop_lock); + while (!address_watch_params_.run_loop_initialized) { + address_watch_params_.params_set.Wait(); + } + } +#endif + // Hand over the bridged POST factory to be owned by the connection // dir_manager. connection_manager()->SetHttpPostProviderFactory(post_factory); @@ -1238,6 +1372,13 @@ void SyncManager::SyncInternal::Shutdown() { LOG(WARNING) << "Error sending error signal to AddressWatchTask"; } close(address_watch_params_.exit_pipe[1]); +#elif defined(OS_MACOSX) + { + AutoLock auto_lock(address_watch_params_.run_loop_lock); + if (address_watch_params_.run_loop) { + CFRunLoopStop(address_watch_params_.run_loop); + } + } #endif address_watch_thread_.Stop(); diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h index 59ce96c..63ec7c1 100644 --- a/chrome/browser/sync/glue/sync_backend_host.h +++ b/chrome/browser/sync/glue/sync_backend_host.h @@ -189,7 +189,8 @@ class SyncBackendHost { const std::wstring& test_user, sync_api::HttpPostProviderFactory* factory, sync_api::HttpPostProviderFactory* auth_factory) { - DoInitialize(GURL(), bookmark_model_worker, false, factory, + DoInitialize(GURL("http://www.example.com/example/path"), + bookmark_model_worker, false, factory, auth_factory, std::string()); syncapi_->SetupForTestMode(test_user); } |