Bug 939318 - Introduce the "network.notify.changed" prefs. r=mcmanus
☠☠ backed out by 0e28f15b78bb ☠ ☠
authorDaniel Stenberg <daniel@haxx.se>
Fri, 19 Sep 2014 06:36:00 -0400
changeset 207039 fedb7e3d1ae08cd4afdf60acd3171e4e1a084a7b
parent 207038 c15814d1ec25a3282a9c4c01c9b42aacf77a83c8
child 207040 04dc86a457c19db88cefaa919fa4ce4997583e84
push id27544
push userryanvm@gmail.com
push dateWed, 24 Sep 2014 21:10:36 +0000
treeherdermozilla-central@1735ff2bb23e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmcmanus
bugs939318
milestone35.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 network changed event in test_ping_aboutnetworking.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
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1012,16 +1012,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)*)
@@ -86,16 +91,17 @@ NS_IMPL_ISUPPORTS(nsNotifyAddrListener,
                   nsIObserver)
 
 nsNotifyAddrListener::nsNotifyAddrListener()
     : mLinkUp(true)  // assume true by default
     , mStatusKnown(false)
     , mCheckAttempted(false)
     , mShutdownEvent(nullptr)
     , mIPInterfaceChecksum(0)
+    , mAllowChangedEvent(true)
 {
     InitIphlpapi();
 }
 
 nsNotifyAddrListener::~nsNotifyAddrListener()
 {
     NS_ASSERTION(!mThread, "nsNotifyAddrListener thread shutdown failed");
     FreeDynamicLibraries();
@@ -210,16 +216,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;
 }
@@ -495,18 +504,18 @@ nsNotifyAddrListener::CheckLinkStatus(vo
         if (ret != ERROR_SUCCESS) {
             mLinkUp = true;
         }
 
         if (mLinkUp && (prevCsum != mIPInterfaceChecksum)) {
             TimeDuration since = TimeStamp::Now() - mChangedTime;
 
             // Network is online. Topology has changed. Always send CHANGED
-            // before UP - after having cooled down.
-            if (since.ToMilliseconds() > 2000) {
+            // before UP - if allowed to and having cooled down.
+            if (mAllowChangedEvent && (since.ToMilliseconds() > 2000)) {
                 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
@@ -64,11 +64,14 @@ protected:
 
 private:
     // This is a checksum of various meta data for all network interfaces
     // considered UP at last check.
     ULONG mIPInterfaceChecksum;
 
     // time of the last sent changed event
     mozilla::TimeStamp mChangedTime;
+
+    // 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,26 @@ 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);
+
+  do_register_cleanup(function() {
+    ps.clearUserPref("network.notify.changed");
+  });
+
   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") {