Bug 939318 - Introduce the "network.notify.changed" prefs. r=mcmanus
☠☠ backed out by 11e4f1678eab ☠ ☠
authorDaniel Stenberg <daniel@haxx.se>
Fri, 29 Aug 2014 01:11:00 -0400
changeset 202357 faece15110ef19190c179ed309d6391303a50b6c
parent 202356 ecc0368d9283018519be5f05fd37159cb7122bd0
child 202358 6e8db8f5d14270f9cfa25d993aa76e3e4c134a34
push id48402
push userryanvm@gmail.com
push dateFri, 29 Aug 2014 13:35:39 +0000
treeherdermozilla-inbound@de5cefa8e52e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmcmanus
bugs939318
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 939318 - Introduce the "network.notify.changed" prefs. r=mcmanus Makes it possible to disable 'changed' events. Disable the events in test_ping_aboutnetworking.js and in test_proxy-failover_passing.js
modules/libpref/init/all.js
netwerk/base/src/nsIOService.cpp
netwerk/base/src/nsIOService.h
netwerk/system/win32/nsNotifyAddrListener.cpp
netwerk/system/win32/nsNotifyAddrListener.h
netwerk/test/unit/test_ping_aboutnetworking.js
netwerk/test/unit/test_proxy-failover_passing.js
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -985,16 +985,20 @@ pref("security.fileuri.strict_origin_pol
 // prevents necko connecting to ports 1-5 unless the protocol
 // overrides.
 
 // Allow necko to do A/B testing. Will generally only happen if
 // telemetry is also enabled as otherwise there is no way to report
 // the results
 pref("network.allow-experiments", true);
 
+// Allow the network changed event to get sent when a network topology or
+// setup change is noticed while running.
+pref("network.notify.changed", true);
+
 // Transmit UDP busy-work to the LAN when anticipating low latency
 // network reads and on wifi to mitigate 802.11 Power Save Polling delays
 pref("network.tickle-wifi.enabled", false);
 pref("network.tickle-wifi.duration", 400);
 pref("network.tickle-wifi.delay", 16);
 
 // Turn off interprocess security checks. Needed to run xpcshell tests.
 pref("network.disable.ipc.security", false);
--- a/netwerk/base/src/nsIOService.cpp
+++ b/netwerk/base/src/nsIOService.cpp
@@ -50,16 +50,17 @@ using namespace mozilla;
 #define AUTODIAL_PREF              "network.autodial-helper.enabled"
 #define MANAGE_OFFLINE_STATUS_PREF "network.manage-offline-status"
 
 // Nb: these have been misnomers since bug 715770 removed the buffer cache.
 // "network.segment.count" and "network.segment.size" would be better names,
 // but the old names are still used to preserve backward compatibility.
 #define NECKO_BUFFER_CACHE_COUNT_PREF "network.buffer.cache.count"
 #define NECKO_BUFFER_CACHE_SIZE_PREF  "network.buffer.cache.size"
+#define NETWORK_NOTIFY_CHANGED_PREF   "network.notify.changed"
 
 #define MAX_RECURSION_COUNT 50
 
 nsIOService* gIOService = nullptr;
 static bool gHasWarnedUploadChannel2;
 
 // A general port blacklist.  Connections to these ports will not be allowed
 // unless the protocol overrides.
@@ -144,16 +145,17 @@ nsIOService::nsIOService()
     , mOfflineForProfileChange(false)
     , mManageOfflineStatus(false)
     , mSettingOffline(false)
     , mSetOfflineValue(false)
     , mShutdown(false)
     , mNetworkLinkServiceInitialized(false)
     , mChannelEventSinks(NS_CHANNEL_EVENT_SINK_CATEGORY)
     , mAutoDialEnabled(false)
+    , mNetworkNotifyChanged(true)
 {
 }
 
 nsresult
 nsIOService::Init()
 {
     nsresult rv;
 
@@ -183,16 +185,17 @@ nsIOService::Init()
     nsCOMPtr<nsIPrefBranch> prefBranch;
     GetPrefBranch(getter_AddRefs(prefBranch));
     if (prefBranch) {
         prefBranch->AddObserver(PORT_PREF_PREFIX, this, true);
         prefBranch->AddObserver(AUTODIAL_PREF, this, true);
         prefBranch->AddObserver(MANAGE_OFFLINE_STATUS_PREF, this, true);
         prefBranch->AddObserver(NECKO_BUFFER_CACHE_COUNT_PREF, this, true);
         prefBranch->AddObserver(NECKO_BUFFER_CACHE_SIZE_PREF, this, true);
+        prefBranch->AddObserver(NETWORK_NOTIFY_CHANGED_PREF, this, true);
         PrefsChanged(prefBranch);
     }
     
     // Register for profile change notifications
     nsCOMPtr<nsIObserverService> observerService =
         mozilla::services::GetObserverService();
     if (observerService) {
         observerService->AddObserver(this, kProfileChangeNetTeardownTopic, true);
@@ -847,16 +850,24 @@ nsIOService::PrefsChanged(nsIPrefBranch 
              * the upper limit here is arbitrary. having a 1mb segment size
              * is pretty crazy.  if you remove this, consider adding some
              * integer rollover test.
              */
             if (size > 0 && size < 1024*1024)
                 gDefaultSegmentSize = size;
         NS_WARN_IF_FALSE( (!(size & (size - 1))) , "network segment size is not a power of 2!");
     }
+
+    if (!pref || strcmp(pref, NETWORK_NOTIFY_CHANGED_PREF) == 0) {
+        bool allow;
+        nsresult rv = prefs->GetBoolPref(NETWORK_NOTIFY_CHANGED_PREF, &allow);
+        if (NS_SUCCEEDED(rv)) {
+            mNetworkNotifyChanged = allow;
+        }
+    }
 }
 
 void
 nsIOService::ParsePortList(nsIPrefBranch *prefBranch, const char *pref, bool remove)
 {
     nsXPIDLCString portList;
 
     // Get a pref string and chop it up into a list of ports.
@@ -953,17 +964,17 @@ nsIOService::Observe(nsISupports *subjec
         }
     } else if (!strcmp(topic, NS_WIDGET_WAKE_OBSERVER_TOPIC)) {
         // coming back alive from sleep
         nsCOMPtr<nsIObserverService> observerService =
             mozilla::services::GetObserverService();
 
         NS_ASSERTION(observerService, "The observer service should not be null");
 
-        if (observerService) {
+        if (observerService && mNetworkNotifyChanged) {
             (void)observerService->
                 NotifyObservers(nullptr,
                                 NS_NETWORK_LINK_TOPIC,
                                 MOZ_UTF16(NS_NETWORK_LINK_DATA_CHANGED));
         }
     }
 
     return NS_OK;
--- a/netwerk/base/src/nsIOService.h
+++ b/netwerk/base/src/nsIOService.h
@@ -124,16 +124,17 @@ private:
     nsWeakPtr                            mWeakHandler[NS_N(gScheme)];
 
     // cached categories
     nsCategoryCache<nsIChannelEventSink> mChannelEventSinks;
 
     nsTArray<int32_t>                    mRestrictedPortList;
 
     bool                                 mAutoDialEnabled;
+    bool                                 mNetworkNotifyChanged;
 public:
     // Used for all default buffer sizes that necko allocates.
     static uint32_t   gDefaultSegmentSize;
     static uint32_t   gDefaultSegmentCount;
 };
 
 /**
  * Reference to the IO service singleton. May be null.
--- a/netwerk/system/win32/nsNotifyAddrListener.cpp
+++ b/netwerk/system/win32/nsNotifyAddrListener.cpp
@@ -22,27 +22,32 @@
 #include "nsThreadUtils.h"
 #include "nsIObserverService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsNotifyAddrListener.h"
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "mozilla/Services.h"
 #include "nsCRT.h"
+#include "mozilla/Preferences.h"
 
 #include <iptypes.h>
 #include <iphlpapi.h>
 
+using namespace mozilla;
+
 static HMODULE sNetshell;
 static decltype(NcFreeNetconProperties)* sNcFreeNetconProperties;
 
 static HMODULE sIphlpapi;
 static decltype(NotifyIpInterfaceChange)* sNotifyIpInterfaceChange;
 static decltype(CancelMibChangeNotify2)* sCancelMibChangeNotify2;
 
+#define NETWORK_NOTIFY_CHANGED_PREF "network.notify.changed"
+
 static void InitIphlpapi(void)
 {
     if (!sIphlpapi) {
         sIphlpapi = LoadLibraryW(L"Iphlpapi.dll");
         if (sIphlpapi) {
             sNotifyIpInterfaceChange = (decltype(NotifyIpInterfaceChange)*)
                 GetProcAddress(sIphlpapi, "NotifyIpInterfaceChange");
             sCancelMibChangeNotify2 = (decltype(CancelMibChangeNotify2)*)
@@ -85,16 +90,17 @@ NS_IMPL_ISUPPORTS(nsNotifyAddrListener,
                   nsIRunnable,
                   nsIObserver)
 
 nsNotifyAddrListener::nsNotifyAddrListener()
     : mLinkUp(true)  // assume true by default
     , mStatusKnown(false)
     , mCheckAttempted(false)
     , mShutdownEvent(nullptr)
+    , mAllowChangedEvent(true)
 {
     InitIphlpapi();
 }
 
 nsNotifyAddrListener::~nsNotifyAddrListener()
 {
     NS_ASSERTION(!mThread, "nsNotifyAddrListener thread shutdown failed");
     FreeDynamicLibraries();
@@ -206,16 +212,19 @@ nsNotifyAddrListener::Init(void)
         mozilla::services::GetObserverService();
     if (!observerService)
         return NS_ERROR_FAILURE;
 
     nsresult rv = observerService->AddObserver(this, "xpcom-shutdown-threads",
                                                false);
     NS_ENSURE_SUCCESS(rv, rv);
 
+    Preferences::AddBoolVarCache(&mAllowChangedEvent,
+                                 NETWORK_NOTIFY_CHANGED_PREF, true);
+
     mShutdownEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
     NS_ENSURE_TRUE(mShutdownEvent, NS_ERROR_OUT_OF_MEMORY);
 
     rv = NS_NewThread(getter_AddRefs(mThread), this);
     NS_ENSURE_SUCCESS(rv, rv);
 
     return NS_OK;
 }
@@ -489,18 +498,20 @@ nsNotifyAddrListener::CheckLinkStatus(vo
     } else {
         ret = CheckAdaptersAddresses();
         if (ret != ERROR_SUCCESS) {
             mLinkUp = true;
         }
 
         if (mLinkUp && (prevCsum != mIPInterfaceChecksum)) {
             // Network is online. Topology has changed. Always send CHANGED
-            // before UP.
-            SendEvent(NS_NETWORK_LINK_DATA_CHANGED);
+            // before UP - if allowed to.
+            if (mAllowChangedEvent) {
+                SendEvent(NS_NETWORK_LINK_DATA_CHANGED);
+            }
         }
         if (prevLinkUp != mLinkUp) {
             // UP/DOWN status changed, send appropriate UP/DOWN event
             SendEvent(mLinkUp ?
                       NS_NETWORK_LINK_DATA_UP : NS_NETWORK_LINK_DATA_DOWN);
         }
     }
 }
--- a/netwerk/system/win32/nsNotifyAddrListener.h
+++ b/netwerk/system/win32/nsNotifyAddrListener.h
@@ -60,11 +60,14 @@ protected:
     nsCOMPtr<nsIThread> mThread;
 
     HANDLE        mShutdownEvent;
 
 private:
     // This is a checksum of various meta data for all network interfaces
     // considered UP at last check.
     ULONG mIPInterfaceChecksum;
+
+    // Network changed events are enabled
+    bool mAllowChangedEvent;
 };
 
 #endif /* NSNOTIFYADDRLISTENER_H_ */
--- a/netwerk/test/unit/test_ping_aboutnetworking.js
+++ b/netwerk/test/unit/test_ping_aboutnetworking.js
@@ -37,16 +37,22 @@ function test_sockets(serverSocket) {
     do_check_eq(data.sockets[index].port, serverSocket.port);
     do_check_eq(data.sockets[index].tcp, 1);
 
     do_test_finished();
   });
 }
 
 function run_test() {
+  var ps = Cc["@mozilla.org/preferences-service;1"]
+    .getService(Ci.nsIPrefBranch);
+  // disable network changed events to avoid the the risk of having the dns
+  // cache getting flushed behind our back
+  ps.setBoolPref("network.notify.changed", false);
+
   let serverSocket = Components.classes["@mozilla.org/network/server-socket;1"]
     .createInstance(Ci.nsIServerSocket);
   serverSocket.init(-1, true, -1);
 
   do_test_pending();
   gDashboard.requestConnection("localhost", serverSocket.port,
                                "tcp", 15, function(connInfo) {
     if (connInfo.status == "NS_NET_STATUS_CONNECTED_TO") {
--- a/netwerk/test/unit/test_proxy-failover_passing.js
+++ b/netwerk/test/unit/test_proxy-failover_passing.js
@@ -31,14 +31,17 @@ function run_test()
   var prefserv = Cc["@mozilla.org/preferences-service;1"].
                  getService(Ci.nsIPrefService);
   var prefs = prefserv.getBranch("network.proxy.");
   prefs.setIntPref("type", 2);
   prefs.setCharPref("autoconfig_url", "data:text/plain," +
     "function FindProxyForURL(url, host) {return 'PROXY a_non_existent_domain_x7x6c572v:80; PROXY localhost:" +
     httpServer.identity.primaryPort + "';}"
   );
+  // disable network changed events to avoid the the risk of having the 
+  // proxyservice reset in the middle
+  prefserv.setBoolPref("network.notify.changed", false);
 
   var chan = make_channel("http://localhost:" +
                           httpServer.identity.primaryPort + "/content");
   chan.asyncOpen(new ChannelListener(finish_test, null), null);
   do_test_pending();
 }