diff options
author | adamk@chromium.org <adamk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-04 22:42:08 +0000 |
---|---|---|
committer | adamk@chromium.org <adamk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-04 22:42:08 +0000 |
commit | 232a58169700ed7abde79d9858c288eb21409e60 (patch) | |
tree | a1424f86d252cd3859c060954882a9a1809a5121 | |
parent | cdc5489ddff18b5ff13296abc1c8869e3cd7db28 (diff) | |
download | chromium_src-232a58169700ed7abde79d9858c288eb21409e60.zip chromium_src-232a58169700ed7abde79d9858c288eb21409e60.tar.gz chromium_src-232a58169700ed7abde79d9858c288eb21409e60.tar.bz2 |
Plumb through NetworkChangeNotifier::IsOffline() to WebKit, enabling
navigator.onLine and online/offline events. Only works on Windows at the moment, as IsCurrentlyOffline() is supported only by NetworkChangeNotifierWin.
Most of the changes are due to the need to support two different kinds of NetworkChangeNotifier observers. Both observers currently happen to trigger on the same event, but that could change, e.g., if we store the previous online state and only notify on a change. Thus the need for two different observer interfaces, and associated Add/Remove methods.
BUG=7469
TEST=Load https://bug336359.bugzilla.mozilla.org/attachment.cgi?id=220609, unplug network cable, reload, see that page changes to note offline status
Review URL: http://codereview.chromium.org/6526059
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76985 0039d316-1c4b-4281-b951-d872f2087c98
27 files changed, 154 insertions, 57 deletions
diff --git a/chrome/browser/google/google_url_tracker.cc b/chrome/browser/google/google_url_tracker.cc index 142e7c7..1b2c686 100644 --- a/chrome/browser/google/google_url_tracker.cc +++ b/chrome/browser/google/google_url_tracker.cc @@ -105,7 +105,7 @@ GoogleURLTracker::GoogleURLTracker() registrar_.Add(this, NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE, NotificationService::AllSources()); - net::NetworkChangeNotifier::AddObserver(this); + net::NetworkChangeNotifier::AddIPAddressObserver(this); MessageLoop::current()->PostTask(FROM_HERE, runnable_method_factory_.NewRunnableMethod( @@ -114,7 +114,7 @@ GoogleURLTracker::GoogleURLTracker() GoogleURLTracker::~GoogleURLTracker() { runnable_method_factory_.RevokeAll(); - net::NetworkChangeNotifier::RemoveObserver(this); + net::NetworkChangeNotifier::RemoveIPAddressObserver(this); } // static diff --git a/chrome/browser/google/google_url_tracker.h b/chrome/browser/google/google_url_tracker.h index 0c405dd..bfac848 100644 --- a/chrome/browser/google/google_url_tracker.h +++ b/chrome/browser/google/google_url_tracker.h @@ -37,7 +37,7 @@ class TemplateURL; // RequestServerCheck(). class GoogleURLTracker : public URLFetcher::Delegate, public NotificationObserver, - public net::NetworkChangeNotifier::Observer { + public net::NetworkChangeNotifier::IPAddressObserver { public: // Only the main browser process loop should call this, when setting up // g_browser_process->google_url_tracker_. No code other than the @@ -118,7 +118,7 @@ class GoogleURLTracker : public URLFetcher::Delegate, const NotificationSource& source, const NotificationDetails& details); - // NetworkChangeNotifier::Observer + // NetworkChangeNotifier::IPAddressObserver virtual void OnIPAddressChanged(); void SearchCommitted(); diff --git a/chrome/browser/intranet_redirect_detector.cc b/chrome/browser/intranet_redirect_detector.cc index 8be4d5e..7a5eef7 100644 --- a/chrome/browser/intranet_redirect_detector.cc +++ b/chrome/browser/intranet_redirect_detector.cc @@ -42,11 +42,11 @@ IntranetRedirectDetector::IntranetRedirectDetector() &IntranetRedirectDetector::FinishSleep), kStartFetchDelayMS); - net::NetworkChangeNotifier::AddObserver(this); + net::NetworkChangeNotifier::AddIPAddressObserver(this); } IntranetRedirectDetector::~IntranetRedirectDetector() { - net::NetworkChangeNotifier::RemoveObserver(this); + net::NetworkChangeNotifier::RemoveIPAddressObserver(this); STLDeleteElements(&fetchers_); } diff --git a/chrome/browser/intranet_redirect_detector.h b/chrome/browser/intranet_redirect_detector.h index 5e920cf..9366d6f 100644 --- a/chrome/browser/intranet_redirect_detector.h +++ b/chrome/browser/intranet_redirect_detector.h @@ -35,9 +35,10 @@ class PrefService; // Consumers should call RedirectOrigin(), which is guaranteed to synchronously // return a value at all times (even during startup or in unittest mode). If no // redirection is in place, the returned GURL will be empty. -class IntranetRedirectDetector : public URLFetcher::Delegate, - public NotificationObserver, - public net::NetworkChangeNotifier::Observer { +class IntranetRedirectDetector + : public URLFetcher::Delegate, + public NotificationObserver, + public net::NetworkChangeNotifier::IPAddressObserver { public: // Only the main browser process loop should call this, when setting up // g_browser_process->intranet_redirect_detector_. No code other than the @@ -81,7 +82,7 @@ class IntranetRedirectDetector : public URLFetcher::Delegate, const NotificationSource& source, const NotificationDetails& details); - // NetworkChangeNotifier::Observer + // NetworkChangeNotifier::IPAddressObserver virtual void OnIPAddressChanged(); NotificationRegistrar registrar_; diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index 1c66a84..ccf0603 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc @@ -153,16 +153,16 @@ net::HostResolver* CreateGlobalHostResolver(net::NetLog* net_log) { } class LoggingNetworkChangeObserver - : public net::NetworkChangeNotifier::Observer { + : public net::NetworkChangeNotifier::IPAddressObserver { public: // |net_log| must remain valid throughout our lifetime. explicit LoggingNetworkChangeObserver(net::NetLog* net_log) : net_log_(net_log) { - net::NetworkChangeNotifier::AddObserver(this); + net::NetworkChangeNotifier::AddIPAddressObserver(this); } ~LoggingNetworkChangeObserver() { - net::NetworkChangeNotifier::RemoveObserver(this); + net::NetworkChangeNotifier::RemoveIPAddressObserver(this); } virtual void OnIPAddressChanged() { diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h index d5ee15b..d3bf4e7 100644 --- a/chrome/browser/io_thread.h +++ b/chrome/browser/io_thread.h @@ -153,7 +153,8 @@ class IOThread : public BrowserProcessSubThread { Globals* globals_; // Observer that logs network changes to the ChromeNetLog. - scoped_ptr<net::NetworkChangeNotifier::Observer> network_change_observer_; + scoped_ptr<net::NetworkChangeNotifier::IPAddressObserver> + network_change_observer_; // Store HTTP Auth-related policies in this thread. std::string auth_schemes_; diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc index 81d57de..416df24 100644 --- a/chrome/browser/sync/engine/syncapi.cc +++ b/chrome/browser/sync/engine/syncapi.cc @@ -1112,7 +1112,7 @@ const sync_pb::PasswordSpecificsData& ////////////////////////////////////////////////////////////////////////// // SyncManager's implementation: SyncManager::SyncInternal class SyncManager::SyncInternal - : public net::NetworkChangeNotifier::Observer, + : public net::NetworkChangeNotifier::IPAddressObserver, public TalkMediator::Delegate, public sync_notifier::StateWriter, public browser_sync::ChannelEventHandler<syncable::DirectoryChangeEvent>, @@ -1681,7 +1681,7 @@ bool SyncManager::SyncInternal::Init( NewEventListenerHookup(connection_manager()->channel(), this, &SyncManager::SyncInternal::HandleServerConnectionEvent)); - net::NetworkChangeNotifier::AddObserver(this); + net::NetworkChangeNotifier::AddIPAddressObserver(this); // TODO(akalin): CheckServerReachable() can block, which may cause jank if we // try to shut down sync. Fix this. core_message_loop_->PostTask(FROM_HERE, @@ -2178,7 +2178,7 @@ void SyncManager::SyncInternal::Shutdown() { core_message_loop_->SetNestableTasksAllowed(old_state); } - net::NetworkChangeNotifier::RemoveObserver(this); + net::NetworkChangeNotifier::RemoveIPAddressObserver(this); connection_manager_hookup_.reset(); diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index cd13198..2b4db144 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -1073,6 +1073,11 @@ IPC_MESSAGE_ROUTED1(ViewMsg_SelectPopupMenuItem, IPC_MESSAGE_ROUTED1(ViewMsg_ContextMenuClosed, webkit_glue::CustomContextMenuContext /* custom_context */) +// Tells the renderer that the network state has changed and that +// window.navigator.onLine should be updated for all WebViews. +IPC_MESSAGE_ROUTED1(ViewMsg_NetworkStateChanged, + bool /* online */) + //----------------------------------------------------------------------------- // TabContents messages // These are messages sent from the renderer to the browser process. diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 49182bb..d73032e 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -135,6 +135,7 @@ #include "third_party/WebKit/Source/WebKit/chromium/public/WebHistoryItem.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebImage.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebNetworkStateNotifier.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeList.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebPageSerializer.h" @@ -248,6 +249,7 @@ using WebKit::WebMediaPlayerAction; using WebKit::WebMediaPlayerClient; using WebKit::WebNavigationPolicy; using WebKit::WebNavigationType; +using WebKit::WebNetworkStateNotifier; using WebKit::WebNode; using WebKit::WebPageSerializer; using WebKit::WebPageSerializerClient; @@ -1118,6 +1120,7 @@ bool RenderView::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewMsg_JavaScriptStressTestControl, OnJavaScriptStressTestControl) IPC_MESSAGE_HANDLER(ViewMsg_ContextMenuClosed, OnContextMenuClosed) + IPC_MESSAGE_HANDLER(ViewMsg_NetworkStateChanged, OnNetworkStateChanged) // TODO(viettrungluu): Move to a separate message filter. #if defined(ENABLE_FLAPPER_HACKS) @@ -5710,3 +5713,7 @@ void RenderView::OnContextMenuClosed( else context_menu_node_.reset(); } + +void RenderView::OnNetworkStateChanged(bool online) { + WebNetworkStateNotifier::setOnLine(online); +} diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index c5fa9e9..7173547 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -884,6 +884,7 @@ class RenderView : public RenderWidget, const WebKit::WebMediaPlayerAction& action); void OnMoveOrResizeStarted(); void OnNavigate(const ViewMsg_Navigate_Params& params); + void OnNetworkStateChanged(bool online); void OnNotifyRendererViewType(ViewType::Type view_type); void OnPaste(); #if defined(OS_MACOSX) diff --git a/content/browser/tab_contents/tab_contents.cc b/content/browser/tab_contents/tab_contents.cc index 0ae8f4a1..2668403 100644 --- a/content/browser/tab_contents/tab_contents.cc +++ b/content/browser/tab_contents/tab_contents.cc @@ -392,6 +392,8 @@ TabContents::~TabContents() { } FOR_EACH_OBSERVER(TabContentsObserver, observers_, set_tab_contents(NULL)); + + net::NetworkChangeNotifier::RemoveOnlineStateObserver(this); } void TabContents::AddObservers() { @@ -406,6 +408,7 @@ void TabContents::AddObservers() { plugin_observer_.reset(new PluginObserver(this)); safebrowsing_detection_host_.reset(new safe_browsing::ClientSideDetectionHost( this)); + net::NetworkChangeNotifier::AddOnlineStateObserver(this); } bool TabContents::OnMessageReceived(const IPC::Message& message) { @@ -2846,6 +2849,11 @@ void TabContents::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) { rwh_view->SetSize(view()->GetContainerSize()); } +void TabContents::OnOnlineStateChanged(bool online) { + render_view_host()->Send(new ViewMsg_NetworkStateChanged( + render_view_host()->routing_id(), online)); +} + bool TabContents::MaybeUsePreloadedPage(const GURL& url) { prerender::PrerenderManager* pm = profile()->GetPrerenderManager(); if (pm != NULL) { diff --git a/content/browser/tab_contents/tab_contents.h b/content/browser/tab_contents/tab_contents.h index a9af86d..a8a3574 100644 --- a/content/browser/tab_contents/tab_contents.h +++ b/content/browser/tab_contents/tab_contents.h @@ -35,6 +35,7 @@ #include "content/browser/tab_contents/render_view_host_manager.h" #include "content/browser/webui/web_ui_factory.h" #include "net/base/load_states.h" +#include "net/base/network_change_notifier.h" #include "ui/gfx/native_widget_types.h" #if defined(OS_WIN) @@ -101,7 +102,8 @@ class TabContents : public PageNavigator, public RenderViewHostManager::Delegate, public JavaScriptAppModalDialogDelegate, public ImageLoadingTracker::Observer, - public TabSpecificContentSettings::Delegate { + public TabSpecificContentSettings::Delegate, + public net::NetworkChangeNotifier::OnlineStateObserver { public: // Flags passed to the TabContentsDelegate.NavigationStateChanged to tell it // what has changed. Combine them to update more than one thing. @@ -1026,6 +1028,9 @@ class TabContents : public PageNavigator, virtual void OnImageLoaded(SkBitmap* image, ExtensionResource resource, int index); + // NetworkChangeNotifier::OnlineStateObserver: + virtual void OnOnlineStateChanged(bool online); + // Checks with the PrerenderManager if the specified URL has been preloaded, // and if so, swap the RenderViewHost with the preload into this TabContents // object. diff --git a/jingle/notifier/communicator/login.cc b/jingle/notifier/communicator/login.cc index de0d525..b19169c 100644 --- a/jingle/notifier/communicator/login.cc +++ b/jingle/notifier/communicator/login.cc @@ -47,12 +47,12 @@ Login::Login(Delegate* delegate, server_count, try_ssltcp_first)), redirect_port_(0) { - net::NetworkChangeNotifier::AddObserver(this); + net::NetworkChangeNotifier::AddIPAddressObserver(this); ResetReconnectState(); } Login::~Login() { - net::NetworkChangeNotifier::RemoveObserver(this); + net::NetworkChangeNotifier::RemoveIPAddressObserver(this); } void Login::StartConnection() { diff --git a/jingle/notifier/communicator/login.h b/jingle/notifier/communicator/login.h index e4ec069b..d7ecbdf 100644 --- a/jingle/notifier/communicator/login.h +++ b/jingle/notifier/communicator/login.h @@ -44,7 +44,7 @@ typedef SingleLoginAttempt::Delegate SingleLoginAttemptDelegate; // Does the login, keeps it alive (with refreshing cookies and reattempting // login when disconnected), figures out what actions to take on the various // errors that may occur. -class Login : public net::NetworkChangeNotifier::Observer, +class Login : public net::NetworkChangeNotifier::IPAddressObserver, public SingleLoginAttemptDelegate { public: class Delegate { @@ -69,7 +69,7 @@ class Login : public net::NetworkChangeNotifier::Observer, void StartConnection(); - // net::NetworkChangeNotifier::Observer implementation. + // net::NetworkChangeNotifier::IPAddressObserver implementation. virtual void OnIPAddressChanged(); // SingleLoginAttempt::Delegate implementation. diff --git a/net/base/dnsrr_resolver.h b/net/base/dnsrr_resolver.h index 3280774..a9ff84b 100644 --- a/net/base/dnsrr_resolver.h +++ b/net/base/dnsrr_resolver.h @@ -67,7 +67,7 @@ class RRResolverJob; // // A DnsRRResolver must be used from the MessageLoop which created it. class DnsRRResolver : public base::NonThreadSafe, - public NetworkChangeNotifier::Observer { + public NetworkChangeNotifier::IPAddressObserver { public: typedef intptr_t Handle; @@ -105,7 +105,7 @@ class DnsRRResolver : public base::NonThreadSafe, // must not have already been called. void CancelResolve(Handle handle); - // Implementation of NetworkChangeNotifier::Observer + // Implementation of NetworkChangeNotifier::IPAddressObserver virtual void OnIPAddressChanged(); private: diff --git a/net/base/host_resolver_impl.cc b/net/base/host_resolver_impl.cc index b22eee8..894443c 100644 --- a/net/base/host_resolver_impl.cc +++ b/net/base/host_resolver_impl.cc @@ -925,7 +925,7 @@ HostResolverImpl::HostResolverImpl( if (HaveOnlyLoopbackAddresses()) additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; #endif - NetworkChangeNotifier::AddObserver(this); + NetworkChangeNotifier::AddIPAddressObserver(this); } HostResolverImpl::~HostResolverImpl() { @@ -939,7 +939,7 @@ HostResolverImpl::~HostResolverImpl() { if (cur_completing_job_) cur_completing_job_->Cancel(); - NetworkChangeNotifier::RemoveObserver(this); + NetworkChangeNotifier::RemoveIPAddressObserver(this); // Delete the job pools. for (size_t i = 0u; i < arraysize(job_pools_); ++i) diff --git a/net/base/host_resolver_impl.h b/net/base/host_resolver_impl.h index a571bb7..89d4f46 100644 --- a/net/base/host_resolver_impl.h +++ b/net/base/host_resolver_impl.h @@ -51,7 +51,7 @@ namespace net { class HostResolverImpl : public HostResolver, public base::NonThreadSafe, - public NetworkChangeNotifier::Observer { + public NetworkChangeNotifier::IPAddressObserver { public: // The index into |job_pools_| for the various job pools. Pools with a higher // index have lower priority. @@ -223,7 +223,7 @@ class HostResolverImpl : public HostResolver, // Aborts all in progress jobs (but might start new ones). void AbortAllInProgressJobs(); - // NetworkChangeNotifier::Observer methods: + // NetworkChangeNotifier::IPAddressObserver methods: virtual void OnIPAddressChanged(); // Cache of host resolution results. diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc index 8c61ac6..596ce8e 100644 --- a/net/base/network_change_notifier.cc +++ b/net/base/network_change_notifier.cc @@ -58,29 +58,56 @@ NetworkChangeNotifier* NetworkChangeNotifier::CreateMock() { return new MockNetworkChangeNotifier(); } -void NetworkChangeNotifier::AddObserver(Observer* observer) { +void NetworkChangeNotifier::AddIPAddressObserver(IPAddressObserver* observer) { if (g_network_change_notifier) - g_network_change_notifier->observer_list_->AddObserver(observer); + g_network_change_notifier->ip_address_observer_list_->AddObserver(observer); } -void NetworkChangeNotifier::RemoveObserver(Observer* observer) { - if (g_network_change_notifier) - g_network_change_notifier->observer_list_->RemoveObserver(observer); +void NetworkChangeNotifier::AddOnlineStateObserver( + OnlineStateObserver* observer) { + if (g_network_change_notifier) { + g_network_change_notifier->online_state_observer_list_->AddObserver( + observer); + } +} + +void NetworkChangeNotifier::RemoveIPAddressObserver( + IPAddressObserver* observer) { + if (g_network_change_notifier) { + g_network_change_notifier->ip_address_observer_list_->RemoveObserver( + observer); + } +} + +void NetworkChangeNotifier::RemoveOnlineStateObserver( + OnlineStateObserver* observer) { + if (g_network_change_notifier) { + g_network_change_notifier->online_state_observer_list_->RemoveObserver( + observer); + } } NetworkChangeNotifier::NetworkChangeNotifier() - : observer_list_( - new ObserverListThreadSafe<Observer>( - ObserverListBase<Observer>::NOTIFY_EXISTING_ONLY)) { + : ip_address_observer_list_( + new ObserverListThreadSafe<IPAddressObserver>( + ObserverListBase<IPAddressObserver>::NOTIFY_EXISTING_ONLY)), + online_state_observer_list_( + new ObserverListThreadSafe<OnlineStateObserver>( + ObserverListBase<OnlineStateObserver>::NOTIFY_EXISTING_ONLY)) { DCHECK(!g_network_change_notifier); g_network_change_notifier = this; } void NetworkChangeNotifier::NotifyObserversOfIPAddressChange() { if (g_network_change_notifier) { - g_network_change_notifier->observer_list_->Notify( - &Observer::OnIPAddressChanged); + g_network_change_notifier->ip_address_observer_list_->Notify( + &IPAddressObserver::OnIPAddressChanged); } } +void NetworkChangeNotifier::NotifyObserversOfOnlineStateChange() { + online_state_observer_list_->Notify( + &OnlineStateObserver::OnOnlineStateChanged, !IsOffline()); +} + } // namespace net diff --git a/net/base/network_change_notifier.h b/net/base/network_change_notifier.h index 770b321..4550eed 100644 --- a/net/base/network_change_notifier.h +++ b/net/base/network_change_notifier.h @@ -16,19 +16,35 @@ namespace net { // and will be called back on the thread from which they registered. class NetworkChangeNotifier { public: - class Observer { + class IPAddressObserver { public: - virtual ~Observer() {} + virtual ~IPAddressObserver() {} // Will be called when the IP address of the primary interface changes. // This includes when the primary interface itself changes. virtual void OnIPAddressChanged() = 0; protected: - Observer() {} + IPAddressObserver() {} private: - DISALLOW_COPY_AND_ASSIGN(Observer); + DISALLOW_COPY_AND_ASSIGN(IPAddressObserver); + }; + + class OnlineStateObserver { + public: + virtual ~OnlineStateObserver() {} + + // Will be called when the online state of the system may have changed. + // See NetworkChangeNotifier::IsOffline() for important caveats about + // the unreliability of this signal. + virtual void OnOnlineStateChanged(bool online) = 0; + + protected: + OnlineStateObserver() {} + + private: + DISALLOW_COPY_AND_ASSIGN(OnlineStateObserver); }; virtual ~NetworkChangeNotifier(); @@ -64,7 +80,8 @@ class NetworkChangeNotifier { // called back with notifications. This is safe to call if Create() has not // been called (as long as it doesn't race the Create() call on another // thread), in which case it will simply do nothing. - static void AddObserver(Observer* observer); + static void AddIPAddressObserver(IPAddressObserver* observer); + static void AddOnlineStateObserver(OnlineStateObserver* observer); // Unregisters |observer| from receiving notifications. This must be called // on the same thread on which AddObserver() was called. Like AddObserver(), @@ -73,7 +90,8 @@ class NetworkChangeNotifier { // nothing. Technically, it's also safe to call after the notifier object has // been destroyed, if the call doesn't race the notifier's destruction, but // there's no reason to use the API in this risky way, so don't do it. - static void RemoveObserver(Observer* observer); + static void RemoveIPAddressObserver(IPAddressObserver* observer); + static void RemoveOnlineStateObserver(OnlineStateObserver* observer); #ifdef UNIT_TEST // Allow unit tests to trigger notifications. @@ -89,9 +107,13 @@ class NetworkChangeNotifier { // happens asynchronously, even for observers on the current thread, even in // tests. static void NotifyObserversOfIPAddressChange(); + void NotifyObserversOfOnlineStateChange(); private: - const scoped_refptr<ObserverListThreadSafe<Observer> > observer_list_; + const scoped_refptr<ObserverListThreadSafe<IPAddressObserver> > + ip_address_observer_list_; + const scoped_refptr<ObserverListThreadSafe<OnlineStateObserver> > + online_state_observer_list_; DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifier); }; diff --git a/net/base/network_change_notifier_win.cc b/net/base/network_change_notifier_win.cc index bc906cb..718e40b 100644 --- a/net/base/network_change_notifier_win.cc +++ b/net/base/network_change_notifier_win.cc @@ -8,6 +8,7 @@ #include <winsock2.h> #include "base/logging.h" +#include "base/time.h" #include "net/base/winsock_init.h" #pragma comment(lib, "iphlpapi.lib") @@ -146,6 +147,15 @@ bool NetworkChangeNotifierWin::IsCurrentlyOffline() const { void NetworkChangeNotifierWin::OnObjectSignaled(HANDLE object) { NotifyObserversOfIPAddressChange(); + // Calling IsOffline() at this very moment is likely to give + // the wrong result, so we delay that until a little bit later. + // + // The one second delay chosen here was determined experimentally + // by adamk on Windows 7. + timer_.Stop(); // cancel any already waiting notification + timer_.Start(base::TimeDelta::FromSeconds(1), this, + &NetworkChangeNotifierWin::NotifyParentOfOnlineStateChange); + // Start watching for the next address change. WatchForAddressChange(); } @@ -157,4 +167,8 @@ void NetworkChangeNotifierWin::WatchForAddressChange() { addr_watcher_.StartWatching(addr_overlapped_.hEvent, this); } +void NetworkChangeNotifierWin::NotifyParentOfOnlineStateChange() { + NotifyObserversOfOnlineStateChange(); +} + } // namespace net diff --git a/net/base/network_change_notifier_win.h b/net/base/network_change_notifier_win.h index c76f7fd..9c2457e 100644 --- a/net/base/network_change_notifier_win.h +++ b/net/base/network_change_notifier_win.h @@ -9,6 +9,7 @@ #include <windows.h> #include "base/basictypes.h" +#include "base/timer.h" #include "base/win/object_watcher.h" #include "net/base/network_change_notifier.h" @@ -31,9 +32,14 @@ class NetworkChangeNotifierWin : public NetworkChangeNotifier, // Begins listening for a single subsequent address change. void WatchForAddressChange(); + // Forwards online state notifications to parent class. + void NotifyParentOfOnlineStateChange(); + base::win::ObjectWatcher addr_watcher_; OVERLAPPED addr_overlapped_; + base::OneShotTimer<NetworkChangeNotifierWin> timer_; + DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierWin); }; diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc index 13d049e..47673c5 100644 --- a/net/proxy/proxy_service.cc +++ b/net/proxy/proxy_service.cc @@ -384,7 +384,7 @@ ProxyService::ProxyService(ProxyConfigService* config_service, stall_proxy_auto_config_delay_( base::TimeDelta::FromMilliseconds( kNumMillisToStallAfterNetworkChanges)) { - NetworkChangeNotifier::AddObserver(this); + NetworkChangeNotifier::AddIPAddressObserver(this); ResetConfigService(config_service); } @@ -560,7 +560,7 @@ int ProxyService::TryToCompleteSynchronously(const GURL& url, } ProxyService::~ProxyService() { - NetworkChangeNotifier::RemoveObserver(this); + NetworkChangeNotifier::RemoveIPAddressObserver(this); config_service_->RemoveObserver(this); // Cancel any inprogress requests. diff --git a/net/proxy/proxy_service.h b/net/proxy/proxy_service.h index 75ac3c9..72b76ef 100644 --- a/net/proxy/proxy_service.h +++ b/net/proxy/proxy_service.h @@ -34,7 +34,7 @@ class URLRequestContext; // HTTP(S) URL. It uses the given ProxyResolver to handle the actual proxy // resolution. See ProxyResolverV8 for example. class ProxyService : public base::RefCountedThreadSafe<ProxyService>, - public NetworkChangeNotifier::Observer, + public NetworkChangeNotifier::IPAddressObserver, public ProxyConfigService::Observer { public: // The instance takes ownership of |config_service| and |resolver|. @@ -280,7 +280,7 @@ class ProxyService : public base::RefCountedThreadSafe<ProxyService>, // Start initialization using |fetched_config_|. void InitializeUsingLastFetchedConfig(); - // NetworkChangeNotifier::Observer + // NetworkChangeNotifier::IPAddressObserver // When this is called, we re-fetch PAC scripts and re-run WPAD. virtual void OnIPAddressChanged(); diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc index 64fb831..8aaf1b5 100644 --- a/net/socket/client_socket_pool_base.cc +++ b/net/socket/client_socket_pool_base.cc @@ -163,7 +163,7 @@ ClientSocketPoolBaseHelper::ClientSocketPoolBaseHelper( DCHECK_LE(0, max_sockets_per_group); DCHECK_LE(max_sockets_per_group, max_sockets); - NetworkChangeNotifier::AddObserver(this); + NetworkChangeNotifier::AddIPAddressObserver(this); } ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() { @@ -175,7 +175,7 @@ ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() { DCHECK(pending_callback_map_.empty()); DCHECK_EQ(0, connecting_socket_count_); - NetworkChangeNotifier::RemoveObserver(this); + NetworkChangeNotifier::RemoveIPAddressObserver(this); } // InsertRequestIntoQueue inserts the request into the queue based on diff --git a/net/socket/client_socket_pool_base.h b/net/socket/client_socket_pool_base.h index 1798997c..89273cc 100644 --- a/net/socket/client_socket_pool_base.h +++ b/net/socket/client_socket_pool_base.h @@ -156,7 +156,7 @@ namespace internal { // ClientSocketPoolBase instead. class ClientSocketPoolBaseHelper : public ConnectJob::Delegate, - public NetworkChangeNotifier::Observer { + public NetworkChangeNotifier::IPAddressObserver { public: typedef uint32 Flags; @@ -289,7 +289,7 @@ class ClientSocketPoolBaseHelper // ConnectJob::Delegate methods: virtual void OnConnectJobComplete(int result, ConnectJob* job); - // NetworkChangeNotifier::Observer methods: + // NetworkChangeNotifier::IPAddressObserver methods: virtual void OnIPAddressChanged(); private: diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc index b32495e..e2cae2b 100644 --- a/net/spdy/spdy_session_pool.cc +++ b/net/spdy/spdy_session_pool.cc @@ -19,7 +19,7 @@ bool SpdySessionPool::g_force_single_domain = false; SpdySessionPool::SpdySessionPool(SSLConfigService* ssl_config_service) : ssl_config_service_(ssl_config_service) { - NetworkChangeNotifier::AddObserver(this); + NetworkChangeNotifier::AddIPAddressObserver(this); if (ssl_config_service_) ssl_config_service_->AddObserver(this); } @@ -29,7 +29,7 @@ SpdySessionPool::~SpdySessionPool() { if (ssl_config_service_) ssl_config_service_->RemoveObserver(this); - NetworkChangeNotifier::RemoveObserver(this); + NetworkChangeNotifier::RemoveIPAddressObserver(this); } scoped_refptr<SpdySession> SpdySessionPool::Get( diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h index 91ff8cb..16125e0 100644 --- a/net/spdy/spdy_session_pool.h +++ b/net/spdy/spdy_session_pool.h @@ -32,7 +32,7 @@ class SpdySession; // This is a very simple pool for open SpdySessions. // TODO(mbelshe): Make this production ready. class SpdySessionPool - : public NetworkChangeNotifier::Observer, + : public NetworkChangeNotifier::IPAddressObserver, public SSLConfigService::Observer { public: explicit SpdySessionPool(SSLConfigService* ssl_config_service); @@ -90,7 +90,7 @@ class SpdySessionPool SpdySettingsStorage* mutable_spdy_settings() { return &spdy_settings_; } const SpdySettingsStorage& spdy_settings() const { return spdy_settings_; } - // NetworkChangeNotifier::Observer methods: + // NetworkChangeNotifier::IPAddressObserver methods: // We flush all idle sessions and release references to the active ones so // they won't get re-used. The active ones will either complete successfully |