Bug 1471628 - Add test for Captive Portal Service r=bagder
MozReview-Commit-ID: KgMN90ERTh5
--- a/netwerk/base/CaptivePortalService.cpp
+++ b/netwerk/base/CaptivePortalService.cpp
@@ -3,16 +3,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/net/CaptivePortalService.h"
#include "mozilla/Services.h"
#include "mozilla/Preferences.h"
#include "nsIObserverService.h"
#include "nsServiceManagerUtils.h"
#include "nsXULAppAPI.h"
+#include "xpcpublic.h"
static const char16_t kInterfaceName[] = u"captive-portal-inteface";
static const char kOpenCaptivePortalLoginEvent[] = "captive-portal-login";
static const char kAbortCaptivePortalLoginEvent[] = "captive-portal-login-abort";
static const char kCaptivePortalLoginSuccessEvent[] = "captive-portal-login-success";
static const uint32_t kDefaultInterval = 60*1000; // check every 60 seconds
@@ -132,16 +133,21 @@ CaptivePortalService::Initialize()
nsresult
CaptivePortalService::Start()
{
if (!mInitialized) {
return NS_ERROR_NOT_INITIALIZED;
}
+ if (xpc::AreNonLocalConnectionsDisabled()
+ && !Preferences::GetBool("network.captive-portal-service.testMode", false)) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
if (XRE_GetProcessType() != GeckoProcessType_Default) {
// Doesn't do anything if called in the content process.
return NS_OK;
}
if (mStarted) {
return NS_OK;
}
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -52,17 +52,16 @@
#include "mozilla/dom/ClientInfo.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ServiceWorkerDescriptor.h"
#include "mozilla/net/CaptivePortalService.h"
#include "mozilla/Unused.h"
#include "ReferrerPolicy.h"
#include "nsContentSecurityManager.h"
#include "nsContentUtils.h"
-#include "xpcpublic.h"
namespace mozilla {
namespace net {
using mozilla::Maybe;
using mozilla::dom::ClientInfo;
using mozilla::dom::ServiceWorkerDescriptor;
@@ -1126,17 +1125,17 @@ nsIOService::SetConnectivityInternal(boo
}
mConnectivity = aConnectivity;
// This is used for PR_Connect PR_Close telemetry so it is important that
// we have statistic about network change event even if we are offline.
mLastConnectivityChange = PR_IntervalNow();
if (mCaptivePortalService) {
- if (aConnectivity && !xpc::AreNonLocalConnectionsDisabled() && gCaptivePortalEnabled) {
+ if (aConnectivity && gCaptivePortalEnabled) {
// This will also trigger a captive portal check for the new network
static_cast<CaptivePortalService*>(mCaptivePortalService.get())->Start();
} else {
static_cast<CaptivePortalService*>(mCaptivePortalService.get())->Stop();
}
}
nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
@@ -1270,17 +1269,17 @@ nsIOService::PrefsChanged(nsIPrefBranch
if (NS_SUCCEEDED(rv)) {
mNetworkNotifyChanged = allow;
}
}
if (!pref || strcmp(pref, NETWORK_CAPTIVE_PORTAL_PREF) == 0) {
nsresult rv = prefs->GetBoolPref(NETWORK_CAPTIVE_PORTAL_PREF, &gCaptivePortalEnabled);
if (NS_SUCCEEDED(rv) && mCaptivePortalService) {
- if (gCaptivePortalEnabled && !xpc::AreNonLocalConnectionsDisabled()) {
+ if (gCaptivePortalEnabled) {
static_cast<CaptivePortalService*>(mCaptivePortalService.get())->Start();
} else {
static_cast<CaptivePortalService*>(mCaptivePortalService.get())->Stop();
}
}
}
}
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit/test_captive_portal_service.js
@@ -0,0 +1,90 @@
+"use strict";
+
+ChromeUtils.import("resource://testing-common/httpd.js");
+ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
+
+var httpserver = null;
+XPCOMUtils.defineLazyGetter(this, "cpURI", function() {
+ return "http://localhost:" + httpserver.identity.primaryPort + "/captive.txt";
+});
+
+const SUCCESS_STRING = "success\n";
+let cpResponse = SUCCESS_STRING;
+function contentHandler(metadata, response)
+{
+ response.setHeader("Content-Type", "text/plain");
+ response.bodyOutputStream.write(cpResponse, cpResponse.length);
+}
+
+const PREF_CAPTIVE_ENABLED = "network.captive-portal-service.enabled";
+const PREF_CAPTIVE_TESTMODE = "network.captive-portal-service.testMode";
+const PREF_CAPTIVE_ENDPOINT = "captivedetect.canonicalURL";
+const PREF_CAPTIVE_MINTIME = "network.captive-portal-service.minInterval";
+const PREF_CAPTIVE_MAXTIME = "network.captive-portal-service.maxInterval";
+
+registerCleanupFunction(() => {
+ Services.prefs.clearUserPref(PREF_CAPTIVE_ENABLED);
+ Services.prefs.clearUserPref(PREF_CAPTIVE_TESTMODE);
+ Services.prefs.clearUserPref(PREF_CAPTIVE_ENDPOINT);
+ Services.prefs.clearUserPref(PREF_CAPTIVE_MINTIME);
+ Services.prefs.clearUserPref(PREF_CAPTIVE_MAXTIME);
+
+ httpserver.stop(() => {});
+});
+
+function observerPromise(topic) {
+ return new Promise(resolve => {
+ let observer = {
+ QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver]),
+ observe: function(aSubject, aTopic, aData) {
+ if (aTopic == topic) {
+ Services.obs.removeObserver(observer, topic);
+ resolve(aData);
+ }
+ }
+ }
+ Services.obs.addObserver(observer, topic);
+ });
+}
+
+add_task(function setup(){
+ httpserver = new HttpServer();
+ httpserver.registerPathHandler("/captive.txt", contentHandler);
+ httpserver.start(-1);
+
+ Services.prefs.setCharPref(PREF_CAPTIVE_ENDPOINT, cpURI);
+ Services.prefs.setIntPref(PREF_CAPTIVE_MINTIME, 50);
+ Services.prefs.setIntPref(PREF_CAPTIVE_MAXTIME, 100);
+ Services.prefs.setBoolPref(PREF_CAPTIVE_TESTMODE, true);
+
+});
+
+add_task(async function test_simple()
+{
+ var cps = Cc["@mozilla.org/network/captive-portal-service;1"]
+ .getService(Ci.nsICaptivePortalService);
+ Services.prefs.setBoolPref(PREF_CAPTIVE_ENABLED, false);
+
+ equal(cps.state, Ci.nsICaptivePortalService.UNKNOWN);
+
+ let notification = observerPromise("network:captive-portal-connectivity");
+ // The service is started by nsIOService when the pref becomes true.
+ // We might want to add a method to do this in the future.
+ Services.prefs.setBoolPref(PREF_CAPTIVE_ENABLED, true);
+
+ let observerPayload = await notification;
+ equal(observerPayload, "clear");
+ equal(cps.state, Ci.nsICaptivePortalService.NOT_CAPTIVE);
+
+ cpResponse = "other";
+ notification = observerPromise("captive-portal-login");
+ cps.recheckCaptivePortal();
+ await notification;
+ equal(cps.state, Ci.nsICaptivePortalService.LOCKED_PORTAL);
+
+ cpResponse = SUCCESS_STRING;
+ notification = observerPromise("captive-portal-login-success");
+ cps.recheckCaptivePortal();
+ await notification;
+ equal(cps.state, Ci.nsICaptivePortalService.UNLOCKED_PORTAL);
+});
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -413,8 +413,10 @@ skip-if = (verify && (os == 'linux'))
# Test requires http/2, and http/2 server doesn't run on android.
skip-if = os == "android"
run-sequentially = node server exceptions dont replay well
[test_trr.js]
# http2-using tests require node available
skip-if = os == "android"
[test_ioservice.js]
[test_substituting_protocol_handler.js]
+[test_captive_portal_service.js]
+