mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-21 09:49:14 +00:00
Bug 1748550 support persisted events for captivePortal r=rpl,robwu
Differential Revision: https://phabricator.services.mozilla.com/D136299
This commit is contained in:
parent
8d79179a4c
commit
d854f45476
@ -27,83 +27,126 @@ var { getSettingsAPI } = ExtensionPreferencesManager;
|
|||||||
|
|
||||||
const CAPTIVE_URL_PREF = "captivedetect.canonicalURL";
|
const CAPTIVE_URL_PREF = "captivedetect.canonicalURL";
|
||||||
|
|
||||||
function nameForCPSState(state) {
|
|
||||||
switch (state) {
|
|
||||||
case gCPS.UNKNOWN:
|
|
||||||
return "unknown";
|
|
||||||
case gCPS.NOT_CAPTIVE:
|
|
||||||
return "not_captive";
|
|
||||||
case gCPS.UNLOCKED_PORTAL:
|
|
||||||
return "unlocked_portal";
|
|
||||||
case gCPS.LOCKED_PORTAL:
|
|
||||||
return "locked_portal";
|
|
||||||
default:
|
|
||||||
return "unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var { ExtensionError } = ExtensionUtils;
|
var { ExtensionError } = ExtensionUtils;
|
||||||
|
|
||||||
this.captivePortal = class extends ExtensionAPI {
|
this.captivePortal = class extends ExtensionAPI {
|
||||||
getAPI(context) {
|
checkCaptivePortalEnabled() {
|
||||||
function checkEnabled() {
|
if (!gCaptivePortalEnabled) {
|
||||||
if (!gCaptivePortalEnabled) {
|
throw new ExtensionError("Captive Portal detection is not enabled");
|
||||||
throw new ExtensionError("Captive Portal detection is not enabled");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nameForCPSState(state) {
|
||||||
|
switch (state) {
|
||||||
|
case gCPS.UNKNOWN:
|
||||||
|
return "unknown";
|
||||||
|
case gCPS.NOT_CAPTIVE:
|
||||||
|
return "not_captive";
|
||||||
|
case gCPS.UNLOCKED_PORTAL:
|
||||||
|
return "unlocked_portal";
|
||||||
|
case gCPS.LOCKED_PORTAL:
|
||||||
|
return "locked_portal";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PERSISTENT_EVENTS = {
|
||||||
|
onStateChanged: fire => {
|
||||||
|
this.checkCaptivePortalEnabled();
|
||||||
|
|
||||||
|
let observer = (subject, topic) => {
|
||||||
|
fire.async({ state: this.nameForCPSState(gCPS.state) });
|
||||||
|
};
|
||||||
|
|
||||||
|
Services.obs.addObserver(
|
||||||
|
observer,
|
||||||
|
"ipc:network:captive-portal-set-state"
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
unregister: () => {
|
||||||
|
Services.obs.removeObserver(
|
||||||
|
observer,
|
||||||
|
"ipc:network:captive-portal-set-state"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
convert(_fire, context) {
|
||||||
|
fire = _fire;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onConnectivityAvailable: fire => {
|
||||||
|
this.checkCaptivePortalEnabled();
|
||||||
|
|
||||||
|
let observer = (subject, topic, data) => {
|
||||||
|
fire.async({ status: data });
|
||||||
|
};
|
||||||
|
|
||||||
|
Services.obs.addObserver(observer, "network:captive-portal-connectivity");
|
||||||
|
return {
|
||||||
|
unregister: () => {
|
||||||
|
Services.obs.removeObserver(
|
||||||
|
observer,
|
||||||
|
"network:captive-portal-connectivity"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
convert(_fire, context) {
|
||||||
|
fire = _fire;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
"captiveURL.onChange": fire => {
|
||||||
|
let listener = (text, id) => {
|
||||||
|
fire.async({
|
||||||
|
levelOfControl: "not_controllable",
|
||||||
|
value: Services.prefs.getStringPref(CAPTIVE_URL_PREF),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
Services.prefs.addObserver(CAPTIVE_URL_PREF, listener);
|
||||||
|
return {
|
||||||
|
unregister: () => {
|
||||||
|
Services.prefs.removeObserver(CAPTIVE_URL_PREF, listener);
|
||||||
|
},
|
||||||
|
convert(_fire, context) {
|
||||||
|
fire = _fire;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
primeListener(extension, event, fire) {
|
||||||
|
if (Object.hasOwn(this.PERSISTENT_EVENTS, event)) {
|
||||||
|
return this.PERSISTENT_EVENTS[event](fire);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getAPI(context) {
|
||||||
|
let self = this;
|
||||||
return {
|
return {
|
||||||
captivePortal: {
|
captivePortal: {
|
||||||
getState() {
|
getState() {
|
||||||
checkEnabled();
|
self.checkCaptivePortalEnabled();
|
||||||
return nameForCPSState(gCPS.state);
|
return self.nameForCPSState(gCPS.state);
|
||||||
},
|
},
|
||||||
getLastChecked() {
|
getLastChecked() {
|
||||||
checkEnabled();
|
self.checkCaptivePortalEnabled();
|
||||||
return gCPS.lastChecked;
|
return gCPS.lastChecked;
|
||||||
},
|
},
|
||||||
onStateChanged: new EventManager({
|
onStateChanged: new EventManager({
|
||||||
context,
|
context,
|
||||||
name: "captivePortal.onStateChanged",
|
module: "captivePortal",
|
||||||
|
event: "onStateChanged",
|
||||||
register: fire => {
|
register: fire => {
|
||||||
checkEnabled();
|
return self.PERSISTENT_EVENTS.onStateChanged(fire).unregister;
|
||||||
|
|
||||||
let observer = (subject, topic) => {
|
|
||||||
fire.async({ state: nameForCPSState(gCPS.state) });
|
|
||||||
};
|
|
||||||
|
|
||||||
Services.obs.addObserver(
|
|
||||||
observer,
|
|
||||||
"ipc:network:captive-portal-set-state"
|
|
||||||
);
|
|
||||||
return () => {
|
|
||||||
Services.obs.removeObserver(
|
|
||||||
observer,
|
|
||||||
"ipc:network:captive-portal-set-state"
|
|
||||||
);
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
}).api(),
|
}).api(),
|
||||||
onConnectivityAvailable: new EventManager({
|
onConnectivityAvailable: new EventManager({
|
||||||
context,
|
context,
|
||||||
name: "captivePortal.onConnectivityAvailable",
|
module: "captivePortal",
|
||||||
|
event: "onConnectivityAvailable",
|
||||||
register: fire => {
|
register: fire => {
|
||||||
checkEnabled();
|
return self.PERSISTENT_EVENTS.onConnectivityAvailable(fire)
|
||||||
|
.unregister;
|
||||||
let observer = (subject, topic, data) => {
|
|
||||||
fire.async({ status: data });
|
|
||||||
};
|
|
||||||
|
|
||||||
Services.obs.addObserver(
|
|
||||||
observer,
|
|
||||||
"network:captive-portal-connectivity"
|
|
||||||
);
|
|
||||||
return () => {
|
|
||||||
Services.obs.removeObserver(
|
|
||||||
observer,
|
|
||||||
"network:captive-portal-connectivity"
|
|
||||||
);
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
}).api(),
|
}).api(),
|
||||||
canonicalURL: getSettingsAPI({
|
canonicalURL: getSettingsAPI({
|
||||||
@ -115,18 +158,11 @@ this.captivePortal = class extends ExtensionAPI {
|
|||||||
readOnly: true,
|
readOnly: true,
|
||||||
onChange: new ExtensionCommon.EventManager({
|
onChange: new ExtensionCommon.EventManager({
|
||||||
context,
|
context,
|
||||||
name: "captiveURL.onChange",
|
module: "captivePortal",
|
||||||
|
event: "captiveURL.onChange",
|
||||||
register: fire => {
|
register: fire => {
|
||||||
let listener = (text, id) => {
|
return self.PERSISTENT_EVENTS["captiveURL.onChange"](fire)
|
||||||
fire.async({
|
.unregister;
|
||||||
levelOfControl: "not_controllable",
|
|
||||||
value: Services.prefs.getStringPref(CAPTIVE_URL_PREF),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Services.prefs.addObserver(CAPTIVE_URL_PREF, listener);
|
|
||||||
return () => {
|
|
||||||
Services.prefs.removeObserver(CAPTIVE_URL_PREF, listener);
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
}).api(),
|
}).api(),
|
||||||
}),
|
}),
|
||||||
|
@ -1,5 +1,19 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
Services.prefs.setBoolPref(
|
||||||
|
"extensions.webextensions.background-delayed-startup",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
AddonTestUtils.init(this);
|
||||||
|
AddonTestUtils.overrideCertDB();
|
||||||
|
AddonTestUtils.createAppInfo(
|
||||||
|
"xpcshell@tests.mozilla.org",
|
||||||
|
"XPCShell",
|
||||||
|
"1",
|
||||||
|
"43"
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This duplicates the test from netwerk/test/unit/test_captive_portal_service.js
|
* This duplicates the test from netwerk/test/unit/test_captive_portal_service.js
|
||||||
* however using an extension to gather the captive portal information.
|
* however using an extension to gather the captive portal information.
|
||||||
@ -30,7 +44,7 @@ registerCleanupFunction(() => {
|
|||||||
Services.prefs.clearUserPref(PREF_DNS_NATIVE_IS_LOCALHOST);
|
Services.prefs.clearUserPref(PREF_DNS_NATIVE_IS_LOCALHOST);
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function setup() {
|
add_task(async function setup() {
|
||||||
Services.prefs.setCharPref(
|
Services.prefs.setCharPref(
|
||||||
PREF_CAPTIVE_ENDPOINT,
|
PREF_CAPTIVE_ENDPOINT,
|
||||||
`http://localhost:${httpserver.identity.primaryPort}/captive.txt`
|
`http://localhost:${httpserver.identity.primaryPort}/captive.txt`
|
||||||
@ -38,6 +52,9 @@ add_task(function setup() {
|
|||||||
Services.prefs.setBoolPref(PREF_CAPTIVE_TESTMODE, true);
|
Services.prefs.setBoolPref(PREF_CAPTIVE_TESTMODE, true);
|
||||||
Services.prefs.setIntPref(PREF_CAPTIVE_MINTIME, 0);
|
Services.prefs.setIntPref(PREF_CAPTIVE_MINTIME, 0);
|
||||||
Services.prefs.setBoolPref(PREF_DNS_NATIVE_IS_LOCALHOST, true);
|
Services.prefs.setBoolPref(PREF_DNS_NATIVE_IS_LOCALHOST, true);
|
||||||
|
|
||||||
|
Services.prefs.setBoolPref("extensions.eventPages.enabled", true);
|
||||||
|
await AddonTestUtils.promiseStartupManager();
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function test_captivePortal_basic() {
|
add_task(async function test_captivePortal_basic() {
|
||||||
@ -46,8 +63,10 @@ add_task(async function test_captivePortal_basic() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let extension = ExtensionTestUtils.loadExtension({
|
let extension = ExtensionTestUtils.loadExtension({
|
||||||
|
useAddonManager: "permanent",
|
||||||
manifest: {
|
manifest: {
|
||||||
permissions: ["captivePortal"],
|
permissions: ["captivePortal"],
|
||||||
|
background: { persistent: false },
|
||||||
},
|
},
|
||||||
isPrivileged: true,
|
isPrivileged: true,
|
||||||
async background() {
|
async background() {
|
||||||
@ -63,6 +82,10 @@ add_task(async function test_captivePortal_basic() {
|
|||||||
browser.test.sendMessage("state", details);
|
browser.test.sendMessage("state", details);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
browser.captivePortal.canonicalURL.onChange.addListener(details => {
|
||||||
|
browser.test.sendMessage("url", details);
|
||||||
|
});
|
||||||
|
|
||||||
browser.test.onMessage.addListener(async msg => {
|
browser.test.onMessage.addListener(async msg => {
|
||||||
if (msg == "getstate") {
|
if (msg == "getstate") {
|
||||||
browser.test.sendMessage(
|
browser.test.sendMessage(
|
||||||
@ -71,21 +94,20 @@ add_task(async function test_captivePortal_basic() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
browser.test.assertEq(
|
|
||||||
"unknown",
|
|
||||||
await browser.captivePortal.getState(),
|
|
||||||
"initial state unknown"
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
await extension.startup();
|
await extension.startup();
|
||||||
|
|
||||||
|
extension.sendMessage("getstate");
|
||||||
|
let details = await extension.awaitMessage("getstate");
|
||||||
|
equal(details, "unknown", "initial state");
|
||||||
|
|
||||||
// The captive portal service is started by nsIOService when the pref becomes true, so we
|
// The captive portal service is started by nsIOService when the pref becomes true, so we
|
||||||
// toggle the pref. We cannot set to false before the extension loads above.
|
// toggle the pref. We cannot set to false before the extension loads above.
|
||||||
Services.prefs.setBoolPref(PREF_CAPTIVE_ENABLED, false);
|
Services.prefs.setBoolPref(PREF_CAPTIVE_ENABLED, false);
|
||||||
Services.prefs.setBoolPref(PREF_CAPTIVE_ENABLED, true);
|
Services.prefs.setBoolPref(PREF_CAPTIVE_ENABLED, true);
|
||||||
|
|
||||||
let details = await extension.awaitMessage("connectivity");
|
details = await extension.awaitMessage("connectivity");
|
||||||
equal(details.status, "clear", "initial connectivity");
|
equal(details.status, "clear", "initial connectivity");
|
||||||
extension.sendMessage("getstate");
|
extension.sendMessage("getstate");
|
||||||
details = await extension.awaitMessage("getstate");
|
details = await extension.awaitMessage("getstate");
|
||||||
@ -106,5 +128,65 @@ add_task(async function test_captivePortal_basic() {
|
|||||||
details = await extension.awaitMessage("state");
|
details = await extension.awaitMessage("state");
|
||||||
equal(details.state, "unlocked_portal", "state after unlocking portal");
|
equal(details.state, "unlocked_portal", "state after unlocking portal");
|
||||||
|
|
||||||
|
assertPersistentListeners(
|
||||||
|
extension,
|
||||||
|
"captivePortal",
|
||||||
|
"onConnectivityAvailable",
|
||||||
|
{
|
||||||
|
primed: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assertPersistentListeners(extension, "captivePortal", "onStateChanged", {
|
||||||
|
primed: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
assertPersistentListeners(extension, "captivePortal", "captiveURL.onChange", {
|
||||||
|
primed: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
info("Test event page terminate/waken");
|
||||||
|
await extension.terminateBackground();
|
||||||
|
|
||||||
|
assertPersistentListeners(extension, "captivePortal", "onStateChanged", {
|
||||||
|
primed: true,
|
||||||
|
});
|
||||||
|
assertPersistentListeners(
|
||||||
|
extension,
|
||||||
|
"captivePortal",
|
||||||
|
"onConnectivityAvailable",
|
||||||
|
{
|
||||||
|
primed: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assertPersistentListeners(extension, "captivePortal", "captiveURL.onChange", {
|
||||||
|
primed: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
info("REFRESH 2nd pass to other");
|
||||||
|
cpResponse = "other";
|
||||||
|
cps.recheckCaptivePortal();
|
||||||
|
details = await extension.awaitMessage("state");
|
||||||
|
equal(details.state, "locked_portal", "state in portal");
|
||||||
|
|
||||||
|
info("Test event page terminate/waken with settings");
|
||||||
|
await extension.terminateBackground();
|
||||||
|
|
||||||
|
assertPersistentListeners(extension, "captivePortal", "captiveURL.onChange", {
|
||||||
|
primed: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
Services.prefs.setStringPref(
|
||||||
|
"captivedetect.canonicalURL",
|
||||||
|
"http://example.com"
|
||||||
|
);
|
||||||
|
let url = await extension.awaitMessage("url");
|
||||||
|
equal(
|
||||||
|
url.value,
|
||||||
|
"http://example.com",
|
||||||
|
"The canonicalURL setting has the expected value."
|
||||||
|
);
|
||||||
|
|
||||||
await extension.unload();
|
await extension.unload();
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user