summaryrefslogtreecommitdiffstats
path: root/toolkit/components/captivedetect/test
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /toolkit/components/captivedetect/test
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/captivedetect/test')
-rw-r--r--toolkit/components/captivedetect/test/captive-portal-simulator.js76
-rw-r--r--toolkit/components/captivedetect/test/unit/head_setprefs.js76
-rw-r--r--toolkit/components/captivedetect/test/unit/test_abort.js52
-rw-r--r--toolkit/components/captivedetect/test/unit/test_abort_during_user_login.js64
-rw-r--r--toolkit/components/captivedetect/test/unit/test_abort_ongoing_request.js74
-rw-r--r--toolkit/components/captivedetect/test/unit/test_abort_pending_request.js71
-rw-r--r--toolkit/components/captivedetect/test/unit/test_captive_portal_found.js65
-rw-r--r--toolkit/components/captivedetect/test/unit/test_captive_portal_found_303.js74
-rw-r--r--toolkit/components/captivedetect/test/unit/test_captive_portal_not_found.js54
-rw-r--r--toolkit/components/captivedetect/test/unit/test_captive_portal_not_found_404.js47
-rw-r--r--toolkit/components/captivedetect/test/unit/test_multiple_requests.js83
-rw-r--r--toolkit/components/captivedetect/test/unit/test_user_cancel.js52
-rw-r--r--toolkit/components/captivedetect/test/unit/xpcshell.toml23
13 files changed, 811 insertions, 0 deletions
diff --git a/toolkit/components/captivedetect/test/captive-portal-simulator.js b/toolkit/components/captivedetect/test/captive-portal-simulator.js
new file mode 100644
index 0000000000..3fee88bf5f
--- /dev/null
+++ b/toolkit/components/captivedetect/test/captive-portal-simulator.js
@@ -0,0 +1,76 @@
+/*
+ * This is a NodeJS script that crudely simulates a captive portal. It is
+ * intended for use by QA and engineering while working on the captive portal
+ * feature in Firefox.
+ *
+ * It maintains the authentication state (logged in or logged out). The root
+ * URL ("/") displays either a link to log out (if the state is logged in) or
+ * to log in (if the state is logged out). A canonical URL ("/test") is
+ * provided: when this URL is requested, if the state is logged in, a "success"
+ * response is sent. If the state is logged out, a redirect is sent (back to
+ * "/"). This script can be used to test Firefox's captive portal detection
+ * features by setting the captivedetect.canonicalURL pref in about:config to
+ * http://localhost:8080/test.
+ *
+ * Originally written by Nihanth.
+ *
+ * Run it like this:
+ *
+ * mach node toolkit/components/captivedetect/test/captive-portal-simulator.js
+ */
+
+// eslint-disable-next-line no-undef
+var http = require("http");
+
+const PORT = 8080;
+
+// Crude HTML for login and logout links
+// loggedOutLink is displayed when the state is logged out, and shows a link
+// that sets the state to logged in.
+const loggedOutLink = "<html><body><a href='/set'>login</a></body></html>";
+// loggedInLink is displayed when the state is logged in, and shows a link
+// that resets the state to logged out.
+const loggedInLink = "<html><body><a href='/reset'>logout</a></body></html>";
+
+// Our state constants
+const OUT = 0;
+const IN = 1;
+
+// State variable
+var state = OUT;
+
+function handleRequest(request, response) {
+ if (request.url == "/reset") {
+ // Set state to logged out and redirect to "/"
+ state = OUT;
+ response.writeHead(302, { location: "/" });
+ response.end();
+ } else if (request.url == "/set") {
+ // Set state to logged in and redirect to canonical URL
+ state = IN;
+ response.writeHead(302, { location: "/test" });
+ response.end();
+ } else if (request.url == "/test") {
+ // Canonical URL. Send canonical response if logged in, else
+ // redirect to index.
+ if (state == IN) {
+ response.setHeader("Content-Type", "text/html");
+ response.end(
+ `<meta http-equiv="refresh" content="0;url=https://support.mozilla.org/kb/captive-portal"/>`
+ );
+ return;
+ }
+ response.writeHead(302, { location: "/" });
+ response.end();
+ } else {
+ // Index: send a login or logout link based on state.
+ response.setHeader("Content-Type", "text/html");
+ response.end(state == IN ? loggedInLink : loggedOutLink);
+ }
+}
+
+// Start the server.
+var server = http.createServer(handleRequest);
+server.listen(PORT, function () {
+ console.log("Server listening on: http://localhost:%s", PORT);
+});
diff --git a/toolkit/components/captivedetect/test/unit/head_setprefs.js b/toolkit/components/captivedetect/test/unit/head_setprefs.js
new file mode 100644
index 0000000000..4e96a6ae46
--- /dev/null
+++ b/toolkit/components/captivedetect/test/unit/head_setprefs.js
@@ -0,0 +1,76 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+var { XPCOMUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/XPCOMUtils.sys.mjs"
+);
+var {
+ HTTP_400,
+ HTTP_401,
+ HTTP_402,
+ HTTP_403,
+ HTTP_404,
+ HTTP_405,
+ HTTP_406,
+ HTTP_407,
+ HTTP_408,
+ HTTP_409,
+ HTTP_410,
+ HTTP_411,
+ HTTP_412,
+ HTTP_413,
+ HTTP_414,
+ HTTP_415,
+ HTTP_417,
+ HTTP_500,
+ HTTP_501,
+ HTTP_502,
+ HTTP_503,
+ HTTP_504,
+ HTTP_505,
+ HttpError,
+ HttpServer,
+} = ChromeUtils.importESModule("resource://testing-common/httpd.sys.mjs");
+
+XPCOMUtils.defineLazyServiceGetter(
+ this,
+ "gCaptivePortalDetector",
+ "@mozilla.org/toolkit/captive-detector;1",
+ "nsICaptivePortalDetector"
+);
+
+const kCanonicalSitePath = "/canonicalSite.html";
+const kCanonicalSiteContent = "true";
+const kPrefsCanonicalURL = "captivedetect.canonicalURL";
+const kPrefsCanonicalContent = "captivedetect.canonicalContent";
+const kPrefsMaxWaitingTime = "captivedetect.maxWaitingTime";
+const kPrefsPollingTime = "captivedetect.pollingTime";
+
+var gServer;
+var gServerURL;
+
+function setupPrefs() {
+ Services.prefs.setCharPref(
+ kPrefsCanonicalURL,
+ gServerURL + kCanonicalSitePath
+ );
+ Services.prefs.setCharPref(kPrefsCanonicalContent, kCanonicalSiteContent);
+ Services.prefs.setIntPref(kPrefsMaxWaitingTime, 0);
+ Services.prefs.setIntPref(kPrefsPollingTime, 1);
+}
+
+function run_captivedetect_test(xhr_handler, fakeUIResponse, testfun) {
+ gServer = new HttpServer();
+ gServer.registerPathHandler(kCanonicalSitePath, xhr_handler);
+ gServer.start(-1);
+ gServerURL = "http://localhost:" + gServer.identity.primaryPort;
+
+ setupPrefs();
+
+ fakeUIResponse();
+
+ testfun();
+}
diff --git a/toolkit/components/captivedetect/test/unit/test_abort.js b/toolkit/components/captivedetect/test/unit/test_abort.js
new file mode 100644
index 0000000000..0e0a944f9b
--- /dev/null
+++ b/toolkit/components/captivedetect/test/unit/test_abort.js
@@ -0,0 +1,52 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const kInterfaceName = "wifi";
+
+var step = 0;
+var loginFinished = false;
+
+function xhr_handler(metadata, response) {
+ response.setStatusLine(metadata.httpVersion, 200, "OK");
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ if (loginFinished) {
+ response.write("true");
+ } else {
+ response.write("false");
+ }
+}
+
+function fakeUIResponse() {
+ Services.obs.addObserver(function observe(subject, topic, data) {
+ if (topic === "captive-portal-login") {
+ do_throw("should not receive captive-portal-login event");
+ }
+ }, "captive-portal-login");
+}
+
+function test_abort() {
+ do_test_pending();
+
+ let callback = {
+ QueryInterface: ChromeUtils.generateQI(["nsICaptivePortalCallback"]),
+ prepare: function prepare() {
+ Assert.equal(++step, 1);
+ gCaptivePortalDetector.finishPreparation(kInterfaceName);
+ },
+ complete: function complete(success) {
+ do_throw("should not execute |complete| callback");
+ },
+ };
+
+ gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
+ gCaptivePortalDetector.abort(kInterfaceName);
+ gServer.stop(do_test_finished);
+}
+
+function run_test() {
+ run_captivedetect_test(xhr_handler, fakeUIResponse, test_abort);
+}
diff --git a/toolkit/components/captivedetect/test/unit/test_abort_during_user_login.js b/toolkit/components/captivedetect/test/unit/test_abort_during_user_login.js
new file mode 100644
index 0000000000..bd0011817d
--- /dev/null
+++ b/toolkit/components/captivedetect/test/unit/test_abort_during_user_login.js
@@ -0,0 +1,64 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const kInterfaceName = "wifi";
+
+var step = 0;
+var loginFinished = false;
+
+function xhr_handler(metadata, response) {
+ response.setStatusLine(metadata.httpVersion, 200, "OK");
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ if (loginFinished) {
+ response.write("true");
+ } else {
+ response.write("false");
+ }
+}
+
+function fakeUIResponse() {
+ let requestId;
+ Services.obs.addObserver(function observe(subject, topic, data) {
+ if (topic === "captive-portal-login") {
+ let xhr = new XMLHttpRequest();
+ xhr.open("GET", gServerURL + kCanonicalSitePath, true);
+ xhr.send();
+ loginFinished = true;
+ Assert.equal(++step, 2);
+ requestId = JSON.parse(data).id;
+ gCaptivePortalDetector.abort(kInterfaceName);
+ }
+ }, "captive-portal-login");
+ Services.obs.addObserver(function observe(subject, topic, data) {
+ if (topic === "captive-portal-login-abort") {
+ Assert.equal(++step, 3);
+ Assert.equal(JSON.parse(data).id, requestId);
+ gServer.stop(do_test_finished);
+ }
+ }, "captive-portal-login-abort");
+}
+
+function test_abort() {
+ do_test_pending();
+
+ let callback = {
+ QueryInterface: ChromeUtils.generateQI(["nsICaptivePortalCallback"]),
+ prepare: function prepare() {
+ Assert.equal(++step, 1);
+ gCaptivePortalDetector.finishPreparation(kInterfaceName);
+ },
+ complete: function complete(success) {
+ do_throw("should not execute |complete| callback");
+ },
+ };
+
+ gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
+}
+
+function run_test() {
+ run_captivedetect_test(xhr_handler, fakeUIResponse, test_abort);
+}
diff --git a/toolkit/components/captivedetect/test/unit/test_abort_ongoing_request.js b/toolkit/components/captivedetect/test/unit/test_abort_ongoing_request.js
new file mode 100644
index 0000000000..b209e02796
--- /dev/null
+++ b/toolkit/components/captivedetect/test/unit/test_abort_ongoing_request.js
@@ -0,0 +1,74 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const kInterfaceName = "wifi";
+const kOtherInterfaceName = "ril";
+
+var step = 0;
+var loginFinished = false;
+
+function xhr_handler(metadata, response) {
+ response.setStatusLine(metadata.httpVersion, 200, "OK");
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ if (loginFinished) {
+ response.write("true");
+ } else {
+ response.write("false");
+ }
+}
+
+function fakeUIResponse() {
+ Services.obs.addObserver(function observe(subject, topic, data) {
+ if (topic === "captive-portal-login") {
+ let xhr = new XMLHttpRequest();
+ xhr.open("GET", gServerURL + kCanonicalSitePath, true);
+ xhr.send();
+ loginFinished = true;
+ Assert.equal(++step, 3);
+ }
+ }, "captive-portal-login");
+}
+
+function test_multiple_requests_abort() {
+ do_test_pending();
+
+ let callback = {
+ QueryInterface: ChromeUtils.generateQI(["nsICaptivePortalCallback"]),
+ prepare: function prepare() {
+ Assert.equal(++step, 1);
+ gCaptivePortalDetector.finishPreparation(kInterfaceName);
+ },
+ complete: function complete(success) {
+ do_throw("should not execute |complete| callback for " + kInterfaceName);
+ },
+ };
+
+ let otherCallback = {
+ QueryInterface: ChromeUtils.generateQI(["nsICaptivePortalCallback"]),
+ prepare: function prepare() {
+ Assert.equal(++step, 2);
+ gCaptivePortalDetector.finishPreparation(kOtherInterfaceName);
+ },
+ complete: function complete(success) {
+ Assert.equal(++step, 4);
+ Assert.ok(success);
+ gServer.stop(do_test_finished);
+ },
+ };
+
+ gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
+ gCaptivePortalDetector.checkCaptivePortal(kOtherInterfaceName, otherCallback);
+ gCaptivePortalDetector.abort(kInterfaceName);
+}
+
+function run_test() {
+ run_captivedetect_test(
+ xhr_handler,
+ fakeUIResponse,
+ test_multiple_requests_abort
+ );
+}
diff --git a/toolkit/components/captivedetect/test/unit/test_abort_pending_request.js b/toolkit/components/captivedetect/test/unit/test_abort_pending_request.js
new file mode 100644
index 0000000000..16d621a06b
--- /dev/null
+++ b/toolkit/components/captivedetect/test/unit/test_abort_pending_request.js
@@ -0,0 +1,71 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const kInterfaceName = "wifi";
+const kOtherInterfaceName = "ril";
+
+var step = 0;
+var loginFinished = false;
+
+function xhr_handler(metadata, response) {
+ response.setStatusLine(metadata.httpVersion, 200, "OK");
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ if (loginFinished) {
+ response.write("true");
+ } else {
+ response.write("false");
+ }
+}
+
+function fakeUIResponse() {
+ Services.obs.addObserver(function observe(subject, topic, data) {
+ if (topic === "captive-portal-login") {
+ let xhr = new XMLHttpRequest();
+ xhr.open("GET", gServerURL + kCanonicalSitePath, true);
+ xhr.send();
+ loginFinished = true;
+ Assert.equal(++step, 2);
+ }
+ }, "captive-portal-login");
+}
+
+function test_abort() {
+ do_test_pending();
+
+ let callback = {
+ QueryInterface: ChromeUtils.generateQI(["nsICaptivePortalCallback"]),
+ prepare: function prepare() {
+ Assert.equal(++step, 1);
+ gCaptivePortalDetector.finishPreparation(kInterfaceName);
+ },
+ complete: function complete(success) {
+ Assert.equal(++step, 3);
+ Assert.ok(success);
+ gServer.stop(do_test_finished);
+ },
+ };
+
+ let otherCallback = {
+ QueryInterface: ChromeUtils.generateQI(["nsICaptivePortalCallback"]),
+ prepare: function prepare() {
+ do_throw(
+ "should not execute |prepare| callback for " + kOtherInterfaceName
+ );
+ },
+ complete: function complete(success) {
+ do_throw("should not execute |complete| callback for " + kInterfaceName);
+ },
+ };
+
+ gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
+ gCaptivePortalDetector.checkCaptivePortal(kOtherInterfaceName, otherCallback);
+ gCaptivePortalDetector.abort(kOtherInterfaceName);
+}
+
+function run_test() {
+ run_captivedetect_test(xhr_handler, fakeUIResponse, test_abort);
+}
diff --git a/toolkit/components/captivedetect/test/unit/test_captive_portal_found.js b/toolkit/components/captivedetect/test/unit/test_captive_portal_found.js
new file mode 100644
index 0000000000..2a9acb8ab0
--- /dev/null
+++ b/toolkit/components/captivedetect/test/unit/test_captive_portal_found.js
@@ -0,0 +1,65 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const kInterfaceName = "wifi";
+
+var step = 0;
+var loginFinished = false;
+
+function xhr_handler(metadata, response) {
+ response.setStatusLine(metadata.httpVersion, 200, "OK");
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ if (loginFinished) {
+ response.write("true");
+ } else {
+ response.write("false");
+ }
+}
+
+function fakeUIResponse() {
+ Services.obs.addObserver(function observe(subject, topic, data) {
+ if (topic === "captive-portal-login") {
+ let xhr = new XMLHttpRequest();
+ xhr.open("GET", gServerURL + kCanonicalSitePath, true);
+ xhr.send();
+ loginFinished = true;
+ Assert.equal(++step, 2);
+ }
+ }, "captive-portal-login");
+
+ Services.obs.addObserver(function observe(subject, topic, data) {
+ if (topic === "captive-portal-login-success") {
+ Assert.equal(++step, 4);
+ gServer.stop(do_test_finished);
+ }
+ }, "captive-portal-login-success");
+}
+
+function test_portal_found() {
+ do_test_pending();
+
+ let callback = {
+ QueryInterface: ChromeUtils.generateQI(["nsICaptivePortalCallback"]),
+ prepare: function prepare() {
+ Assert.equal(++step, 1);
+ gCaptivePortalDetector.finishPreparation(kInterfaceName);
+ },
+ complete: function complete(success) {
+ // Since this is a synchronous callback, it must happen before
+ // 'captive-portal-login-success' is received.
+ // (Check captivedetect.js::executeCallback
+ Assert.equal(++step, 3);
+ Assert.ok(success);
+ },
+ };
+
+ gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
+}
+
+function run_test() {
+ run_captivedetect_test(xhr_handler, fakeUIResponse, test_portal_found);
+}
diff --git a/toolkit/components/captivedetect/test/unit/test_captive_portal_found_303.js b/toolkit/components/captivedetect/test/unit/test_captive_portal_found_303.js
new file mode 100644
index 0000000000..1e4ec1f97d
--- /dev/null
+++ b/toolkit/components/captivedetect/test/unit/test_captive_portal_found_303.js
@@ -0,0 +1,74 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const kInterfaceName = "wifi";
+
+var step = 0;
+var loginFinished = false;
+
+var gRedirectServer;
+var gRedirectServerURL;
+
+function xhr_handler(metadata, response) {
+ if (loginFinished) {
+ response.setStatusLine(metadata.httpVersion, 200, "OK");
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write("true");
+ } else {
+ response.setStatusLine(metadata.httpVersion, 303, "See Other");
+ response.setHeader("Location", gRedirectServerURL, false);
+ response.setHeader("Content-Type", "text/html", false);
+ }
+}
+
+function fakeUIResponse() {
+ Services.obs.addObserver(function observe(subject, topic, data) {
+ if (topic === "captive-portal-login") {
+ let xhr = new XMLHttpRequest();
+ xhr.open("GET", gServerURL + kCanonicalSitePath, true);
+ xhr.send();
+ loginFinished = true;
+ Assert.equal(++step, 2);
+ }
+ }, "captive-portal-login");
+
+ Services.obs.addObserver(function observe(subject, topic, data) {
+ if (topic === "captive-portal-login-success") {
+ Assert.equal(++step, 4);
+ gServer.stop(function () {
+ gRedirectServer.stop(do_test_finished);
+ });
+ }
+ }, "captive-portal-login-success");
+}
+
+function test_portal_found() {
+ do_test_pending();
+
+ let callback = {
+ QueryInterface: ChromeUtils.generateQI(["nsICaptivePortalCallback"]),
+ prepare: function prepare() {
+ Assert.equal(++step, 1);
+ gCaptivePortalDetector.finishPreparation(kInterfaceName);
+ },
+ complete: function complete(success) {
+ Assert.equal(++step, 3);
+ Assert.ok(success);
+ },
+ };
+
+ gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
+}
+
+function run_test() {
+ gRedirectServer = new HttpServer();
+ gRedirectServer.start(-1);
+ gRedirectServerURL =
+ "http://localhost:" + gRedirectServer.identity.primaryPort;
+
+ run_captivedetect_test(xhr_handler, fakeUIResponse, test_portal_found);
+}
diff --git a/toolkit/components/captivedetect/test/unit/test_captive_portal_not_found.js b/toolkit/components/captivedetect/test/unit/test_captive_portal_not_found.js
new file mode 100644
index 0000000000..25dd5f7c99
--- /dev/null
+++ b/toolkit/components/captivedetect/test/unit/test_captive_portal_not_found.js
@@ -0,0 +1,54 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const kInterfaceName = "wifi";
+
+var step = 0;
+var attempt = 0;
+
+function xhr_handler(metadata, response) {
+ dump("HTTP activity\n");
+ response.setStatusLine(metadata.httpVersion, 200, "OK");
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write("true");
+ attempt++;
+}
+
+function fakeUIResponse() {
+ Services.obs.addObserver(function observe(subject, topic, data) {
+ if (topic == "captive-portal-login") {
+ do_throw("should not receive captive-portal-login event");
+ }
+ }, "captive-portal-login");
+}
+
+function test_portal_not_found() {
+ do_test_pending();
+
+ let callback = {
+ QueryInterface: ChromeUtils.generateQI(["nsICaptivePortalCallback"]),
+ prepare: function prepare() {
+ Assert.equal(++step, 1);
+ gCaptivePortalDetector.finishPreparation(kInterfaceName);
+ },
+ complete: function complete(success) {
+ Assert.equal(++step, 2);
+ Assert.ok(success);
+ Assert.equal(attempt, 1);
+ gServer.stop(function () {
+ dump("server stop\n");
+ do_test_finished();
+ });
+ },
+ };
+
+ gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
+}
+
+function run_test() {
+ run_captivedetect_test(xhr_handler, fakeUIResponse, test_portal_not_found);
+}
diff --git a/toolkit/components/captivedetect/test/unit/test_captive_portal_not_found_404.js b/toolkit/components/captivedetect/test/unit/test_captive_portal_not_found_404.js
new file mode 100644
index 0000000000..3f9d212a1f
--- /dev/null
+++ b/toolkit/components/captivedetect/test/unit/test_captive_portal_not_found_404.js
@@ -0,0 +1,47 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const kInterfaceName = "wifi";
+
+var step = 0;
+var attempt = 0;
+
+function xhr_handler(metadata, response) {
+ response.setStatusLine(metadata.httpVersion, 404, "Page not Found");
+ attempt++;
+}
+
+function fakeUIResponse() {
+ Services.obs.addObserver(function observe(subject, topic, data) {
+ if (topic === "captive-portal-login") {
+ do_throw("should not receive captive-portal-login event");
+ }
+ }, "captive-portal-login");
+}
+
+function test_portal_not_found() {
+ do_test_pending();
+
+ let callback = {
+ QueryInterface: ChromeUtils.generateQI(["nsICaptivePortalCallback"]),
+ prepare: function prepare() {
+ Assert.equal(++step, 1);
+ gCaptivePortalDetector.finishPreparation(kInterfaceName);
+ },
+ complete: function complete(success) {
+ Assert.equal(++step, 2);
+ Assert.ok(!success);
+ Assert.equal(attempt, 6);
+ gServer.stop(do_test_finished);
+ },
+ };
+
+ gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
+}
+
+function run_test() {
+ run_captivedetect_test(xhr_handler, fakeUIResponse, test_portal_not_found);
+}
diff --git a/toolkit/components/captivedetect/test/unit/test_multiple_requests.js b/toolkit/components/captivedetect/test/unit/test_multiple_requests.js
new file mode 100644
index 0000000000..7778a595b0
--- /dev/null
+++ b/toolkit/components/captivedetect/test/unit/test_multiple_requests.js
@@ -0,0 +1,83 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const kInterfaceName = "wifi";
+const kOtherInterfaceName = "ril";
+
+var step = 0;
+var loginFinished = false;
+var loginSuccessCount = 0;
+
+function xhr_handler(metadata, response) {
+ response.setStatusLine(metadata.httpVersion, 200, "OK");
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ if (loginFinished) {
+ response.write("true");
+ } else {
+ response.write("false");
+ }
+}
+
+function fakeUIResponse() {
+ Services.obs.addObserver(function observe(subject, topic, data) {
+ if (topic === "captive-portal-login") {
+ let xhr = new XMLHttpRequest();
+ xhr.open("GET", gServerURL + kCanonicalSitePath, true);
+ xhr.send();
+ loginFinished = true;
+ Assert.equal(++step, 2);
+ }
+ }, "captive-portal-login");
+
+ Services.obs.addObserver(function observe(subject, topic, data) {
+ if (topic === "captive-portal-login-success") {
+ loginSuccessCount++;
+ if (loginSuccessCount > 1) {
+ throw new Error(
+ "We should only receive 'captive-portal-login-success' once"
+ );
+ }
+ Assert.equal(++step, 4);
+ }
+ }, "captive-portal-login-success");
+}
+
+function test_multiple_requests() {
+ do_test_pending();
+
+ let callback = {
+ QueryInterface: ChromeUtils.generateQI(["nsICaptivePortalCallback"]),
+ prepare: function prepare() {
+ Assert.equal(++step, 1);
+ gCaptivePortalDetector.finishPreparation(kInterfaceName);
+ },
+ complete: function complete(success) {
+ Assert.equal(++step, 3);
+ Assert.ok(success);
+ },
+ };
+
+ let otherCallback = {
+ QueryInterface: ChromeUtils.generateQI(["nsICaptivePortalCallback"]),
+ prepare: function prepare() {
+ Assert.equal(++step, 5);
+ gCaptivePortalDetector.finishPreparation(kOtherInterfaceName);
+ },
+ complete: function complete(success) {
+ Assert.equal(++step, 6);
+ Assert.ok(success);
+ gServer.stop(do_test_finished);
+ },
+ };
+
+ gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
+ gCaptivePortalDetector.checkCaptivePortal(kOtherInterfaceName, otherCallback);
+}
+
+function run_test() {
+ run_captivedetect_test(xhr_handler, fakeUIResponse, test_multiple_requests);
+}
diff --git a/toolkit/components/captivedetect/test/unit/test_user_cancel.js b/toolkit/components/captivedetect/test/unit/test_user_cancel.js
new file mode 100644
index 0000000000..cceb507403
--- /dev/null
+++ b/toolkit/components/captivedetect/test/unit/test_user_cancel.js
@@ -0,0 +1,52 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const kInterfaceName = "wifi";
+
+var step = 0;
+
+function xhr_handler(metadata, response) {
+ response.setStatusLine(metadata.httpVersion, 200, "OK");
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write("false");
+}
+
+function fakeUIResponse() {
+ Services.obs.addObserver(function observe(subject, topic, data) {
+ if (topic === "captive-portal-login") {
+ let xhr = new XMLHttpRequest();
+ xhr.open("GET", gServerURL + kCanonicalSitePath, true);
+ xhr.send();
+ Assert.equal(++step, 2);
+ let details = JSON.parse(data);
+ gCaptivePortalDetector.cancelLogin(details.id);
+ }
+ }, "captive-portal-login");
+}
+
+function test_cancel() {
+ do_test_pending();
+
+ let callback = {
+ QueryInterface: ChromeUtils.generateQI(["nsICaptivePortalCallback"]),
+ prepare: function prepare() {
+ Assert.equal(++step, 1);
+ gCaptivePortalDetector.finishPreparation(kInterfaceName);
+ },
+ complete: function complete(success) {
+ Assert.equal(++step, 3);
+ Assert.ok(!success);
+ gServer.stop(do_test_finished);
+ },
+ };
+
+ gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
+}
+
+function run_test() {
+ run_captivedetect_test(xhr_handler, fakeUIResponse, test_cancel);
+}
diff --git a/toolkit/components/captivedetect/test/unit/xpcshell.toml b/toolkit/components/captivedetect/test/unit/xpcshell.toml
new file mode 100644
index 0000000000..2d03dce948
--- /dev/null
+++ b/toolkit/components/captivedetect/test/unit/xpcshell.toml
@@ -0,0 +1,23 @@
+[DEFAULT]
+head = "head_setprefs.js"
+
+["test_abort.js"]
+
+["test_abort_during_user_login.js"]
+
+["test_abort_ongoing_request.js"]
+
+["test_abort_pending_request.js"]
+
+
+["test_captive_portal_found.js"]
+
+["test_captive_portal_found_303.js"]
+
+["test_captive_portal_not_found.js"]
+
+["test_captive_portal_not_found_404.js"]
+
+["test_multiple_requests.js"]
+
+["test_user_cancel.js"]