332 lines
9 KiB
JavaScript
332 lines
9 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
const userAgentID = "2c43af06-ab6e-476a-adc4-16cbda54fb89";
|
|
|
|
let db;
|
|
|
|
function run_test() {
|
|
do_get_profile();
|
|
setPrefs({
|
|
userAgentID,
|
|
});
|
|
|
|
db = PushServiceWebSocket.newPushDB();
|
|
registerCleanupFunction(() => {
|
|
return db.drop().then(_ => db.close());
|
|
});
|
|
|
|
run_next_test();
|
|
}
|
|
|
|
let unregisterDefers = {};
|
|
|
|
function promiseUnregister(keyID) {
|
|
return new Promise(r => (unregisterDefers[keyID] = r));
|
|
}
|
|
|
|
function makePushPermission(url, capability) {
|
|
return {
|
|
QueryInterface: ChromeUtils.generateQI(["nsIPermission"]),
|
|
capability: Ci.nsIPermissionManager[capability],
|
|
expireTime: 0,
|
|
expireType: Ci.nsIPermissionManager.EXPIRE_NEVER,
|
|
principal: Services.scriptSecurityManager.createContentPrincipal(
|
|
Services.io.newURI(url),
|
|
{}
|
|
),
|
|
type: "desktop-notification",
|
|
};
|
|
}
|
|
|
|
function promiseObserverNotifications(topic, count) {
|
|
let notifiedScopes = [];
|
|
let subChangePromise = promiseObserverNotification(topic, (subject, data) => {
|
|
notifiedScopes.push(data);
|
|
return notifiedScopes.length == count;
|
|
});
|
|
return subChangePromise.then(_ => notifiedScopes.sort());
|
|
}
|
|
|
|
function promiseSubscriptionChanges(count) {
|
|
return promiseObserverNotifications(
|
|
PushServiceComponent.subscriptionChangeTopic,
|
|
count
|
|
);
|
|
}
|
|
|
|
function promiseSubscriptionModifications(count) {
|
|
return promiseObserverNotifications(
|
|
PushServiceComponent.subscriptionModifiedTopic,
|
|
count
|
|
);
|
|
}
|
|
|
|
function allExpired(...keyIDs) {
|
|
return Promise.all(keyIDs.map(keyID => db.getByKeyID(keyID))).then(records =>
|
|
records.every(record => record.isExpired())
|
|
);
|
|
}
|
|
|
|
add_task(async function setUp() {
|
|
// Active registration; quota should be reset to 16. Since the quota isn't
|
|
// exposed to content, we shouldn't receive a subscription change event.
|
|
await putTestRecord(db, "active-allow", "https://example.info/page/1", 8);
|
|
|
|
// Expired registration; should be dropped.
|
|
await putTestRecord(db, "expired-allow", "https://example.info/page/2", 0);
|
|
|
|
// Active registration; should be expired when we change the permission
|
|
// to "deny".
|
|
await putTestRecord(
|
|
db,
|
|
"active-deny-changed",
|
|
"https://example.xyz/page/1",
|
|
16
|
|
);
|
|
|
|
// Two active registrations for a visited site. These will expire when we
|
|
// add a "deny" permission.
|
|
await putTestRecord(db, "active-deny-added-1", "https://example.net/ham", 16);
|
|
await putTestRecord(
|
|
db,
|
|
"active-deny-added-2",
|
|
"https://example.net/green",
|
|
8
|
|
);
|
|
|
|
// An already-expired registration for a visited site. We shouldn't send an
|
|
// `unregister` request for this one, but still receive an observer
|
|
// notification when we restore permissions.
|
|
await putTestRecord(db, "expired-deny-added", "https://example.net/eggs", 0);
|
|
|
|
// A registration that should not be affected by permission list changes
|
|
// because its quota is set to `Infinity`.
|
|
await putTestRecord(db, "never-expires", "app://chrome/only", Infinity);
|
|
|
|
// A registration that should be dropped when we clear the permission
|
|
// list.
|
|
await putTestRecord(db, "drop-on-clear", "https://example.edu/lonely", 16);
|
|
|
|
let handshakeDone;
|
|
let handshakePromise = new Promise(resolve => (handshakeDone = resolve));
|
|
PushService.init({
|
|
serverURI: "wss://push.example.org/",
|
|
db,
|
|
makeWebSocket(uri) {
|
|
return new MockWebSocket(uri, {
|
|
onHello() {
|
|
this.serverSendMsg(
|
|
JSON.stringify({
|
|
messageType: "hello",
|
|
status: 200,
|
|
uaid: userAgentID,
|
|
})
|
|
);
|
|
handshakeDone();
|
|
},
|
|
onUnregister(request) {
|
|
let resolve = unregisterDefers[request.channelID];
|
|
equal(
|
|
typeof resolve,
|
|
"function",
|
|
"Dropped unexpected channel ID " + request.channelID
|
|
);
|
|
delete unregisterDefers[request.channelID];
|
|
equal(
|
|
request.code,
|
|
202,
|
|
"Expected permission revoked unregister reason"
|
|
);
|
|
resolve();
|
|
this.serverSendMsg(
|
|
JSON.stringify({
|
|
messageType: "unregister",
|
|
status: 200,
|
|
channelID: request.channelID,
|
|
})
|
|
);
|
|
},
|
|
onACK() {},
|
|
});
|
|
},
|
|
});
|
|
await handshakePromise;
|
|
});
|
|
|
|
add_task(async function test_permissions_allow_added() {
|
|
let subChangePromise = promiseSubscriptionChanges(1);
|
|
|
|
await PushService._onPermissionChange(
|
|
makePushPermission("https://example.info", "ALLOW_ACTION"),
|
|
"added"
|
|
);
|
|
let notifiedScopes = await subChangePromise;
|
|
|
|
deepEqual(
|
|
notifiedScopes,
|
|
["https://example.info/page/2"],
|
|
"Wrong scopes after adding allow"
|
|
);
|
|
|
|
let record = await db.getByKeyID("active-allow");
|
|
equal(
|
|
record.quota,
|
|
16,
|
|
"Should reset quota for active records after adding allow"
|
|
);
|
|
|
|
record = await db.getByKeyID("expired-allow");
|
|
ok(!record, "Should drop expired records after adding allow");
|
|
});
|
|
|
|
add_task(async function test_permissions_allow_deleted() {
|
|
let subModifiedPromise = promiseSubscriptionModifications(1);
|
|
|
|
let unregisterPromise = promiseUnregister("active-allow");
|
|
|
|
await PushService._onPermissionChange(
|
|
makePushPermission("https://example.info", "ALLOW_ACTION"),
|
|
"deleted"
|
|
);
|
|
|
|
await unregisterPromise;
|
|
|
|
let notifiedScopes = await subModifiedPromise;
|
|
deepEqual(
|
|
notifiedScopes,
|
|
["https://example.info/page/1"],
|
|
"Wrong scopes modified after deleting allow"
|
|
);
|
|
|
|
let record = await db.getByKeyID("active-allow");
|
|
ok(record.isExpired(), "Should expire active record after deleting allow");
|
|
});
|
|
|
|
add_task(async function test_permissions_deny_added() {
|
|
let subModifiedPromise = promiseSubscriptionModifications(2);
|
|
|
|
let unregisterPromise = Promise.all([
|
|
promiseUnregister("active-deny-added-1"),
|
|
promiseUnregister("active-deny-added-2"),
|
|
]);
|
|
|
|
await PushService._onPermissionChange(
|
|
makePushPermission("https://example.net", "DENY_ACTION"),
|
|
"added"
|
|
);
|
|
await unregisterPromise;
|
|
|
|
let notifiedScopes = await subModifiedPromise;
|
|
deepEqual(
|
|
notifiedScopes,
|
|
["https://example.net/green", "https://example.net/ham"],
|
|
"Wrong scopes modified after adding deny"
|
|
);
|
|
|
|
let isExpired = await allExpired("active-deny-added-1", "expired-deny-added");
|
|
ok(isExpired, "Should expire all registrations after adding deny");
|
|
});
|
|
|
|
add_task(async function test_permissions_deny_deleted() {
|
|
await PushService._onPermissionChange(
|
|
makePushPermission("https://example.net", "DENY_ACTION"),
|
|
"deleted"
|
|
);
|
|
|
|
let isExpired = await allExpired("active-deny-added-1", "expired-deny-added");
|
|
ok(isExpired, "Should retain expired registrations after deleting deny");
|
|
});
|
|
|
|
add_task(async function test_permissions_allow_changed() {
|
|
let subChangePromise = promiseSubscriptionChanges(3);
|
|
|
|
await PushService._onPermissionChange(
|
|
makePushPermission("https://example.net", "ALLOW_ACTION"),
|
|
"changed"
|
|
);
|
|
|
|
let notifiedScopes = await subChangePromise;
|
|
|
|
deepEqual(
|
|
notifiedScopes,
|
|
[
|
|
"https://example.net/eggs",
|
|
"https://example.net/green",
|
|
"https://example.net/ham",
|
|
],
|
|
"Wrong scopes after changing to allow"
|
|
);
|
|
|
|
let droppedRecords = await Promise.all([
|
|
db.getByKeyID("active-deny-added-1"),
|
|
db.getByKeyID("active-deny-added-2"),
|
|
db.getByKeyID("expired-deny-added"),
|
|
]);
|
|
ok(
|
|
!droppedRecords.some(Boolean),
|
|
"Should drop all expired registrations after changing to allow"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_permissions_deny_changed() {
|
|
let subModifiedPromise = promiseSubscriptionModifications(1);
|
|
|
|
let unregisterPromise = promiseUnregister("active-deny-changed");
|
|
|
|
await PushService._onPermissionChange(
|
|
makePushPermission("https://example.xyz", "DENY_ACTION"),
|
|
"changed"
|
|
);
|
|
|
|
await unregisterPromise;
|
|
|
|
let notifiedScopes = await subModifiedPromise;
|
|
deepEqual(
|
|
notifiedScopes,
|
|
["https://example.xyz/page/1"],
|
|
"Wrong scopes modified after changing to deny"
|
|
);
|
|
|
|
let record = await db.getByKeyID("active-deny-changed");
|
|
ok(record.isExpired(), "Should expire active record after changing to deny");
|
|
});
|
|
|
|
add_task(async function test_permissions_clear() {
|
|
let subModifiedPromise = promiseSubscriptionModifications(3);
|
|
|
|
deepEqual(
|
|
await getAllKeyIDs(db),
|
|
["active-allow", "active-deny-changed", "drop-on-clear", "never-expires"],
|
|
"Wrong records in database before clearing"
|
|
);
|
|
|
|
let unregisterPromise = Promise.all([
|
|
promiseUnregister("active-allow"),
|
|
promiseUnregister("active-deny-changed"),
|
|
promiseUnregister("drop-on-clear"),
|
|
]);
|
|
|
|
await PushService._onPermissionChange(null, "cleared");
|
|
|
|
await unregisterPromise;
|
|
|
|
let notifiedScopes = await subModifiedPromise;
|
|
deepEqual(
|
|
notifiedScopes,
|
|
[
|
|
"https://example.edu/lonely",
|
|
"https://example.info/page/1",
|
|
"https://example.xyz/page/1",
|
|
],
|
|
"Wrong scopes modified after clearing registrations"
|
|
);
|
|
|
|
deepEqual(
|
|
await getAllKeyIDs(db),
|
|
["never-expires"],
|
|
"Unrestricted registrations should not be dropped"
|
|
);
|
|
});
|