mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1188686 - Clear push subscriptions when forgetting about site. r=kitcambridge
--HG-- extra : commitid : 4z3omFAziAN extra : transplant_source : %0A%E7%85%26%EE9%CE%95%0C/%AC%7E%89%ED%08%9A%3C%99mA
This commit is contained in:
parent
839a3bc3fb
commit
97ea06c0c0
@ -11,7 +11,7 @@
|
|||||||
* uses service workers to notify applications. This interface exists to allow
|
* uses service workers to notify applications. This interface exists to allow
|
||||||
* privileged code to receive messages without migrating to service workers.
|
* privileged code to receive messages without migrating to service workers.
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(abde228b-7d14-4cab-b1f9-9f87750ede0f)]
|
[scriptable, uuid(74586476-d73f-4867-bece-87c1dea35750)]
|
||||||
interface nsIPushNotificationService : nsISupports
|
interface nsIPushNotificationService : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -48,7 +48,12 @@ interface nsIPushNotificationService : nsISupports
|
|||||||
jsval registration(in string scope, in jsval originAttributes);
|
jsval registration(in string scope, in jsval originAttributes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all subscriptions
|
* Clear all subscriptions.
|
||||||
*/
|
*/
|
||||||
jsval clearAll();
|
jsval clearAll();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear subscriptions for a domain.
|
||||||
|
*/
|
||||||
|
jsval clearForDomain(in string domain);
|
||||||
};
|
};
|
||||||
|
@ -154,6 +154,36 @@ this.PushDB.prototype = {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// testFn(record) is called with a database record and should return true if
|
||||||
|
// that record should be deleted.
|
||||||
|
clearIf: function(testFn) {
|
||||||
|
debug("clearIf()");
|
||||||
|
return new Promise((resolve, reject) =>
|
||||||
|
this.newTxn(
|
||||||
|
"readwrite",
|
||||||
|
this._dbStoreName,
|
||||||
|
(aTxn, aStore) => {
|
||||||
|
aTxn.result = undefined;
|
||||||
|
|
||||||
|
aStore.openCursor().onsuccess = event => {
|
||||||
|
let cursor = event.target.result;
|
||||||
|
if (cursor) {
|
||||||
|
if (testFn(this.toPushRecord(cursor.value))) {
|
||||||
|
let deleteRequest = cursor.delete();
|
||||||
|
deleteRequest.onerror = e => {
|
||||||
|
debug("Failed to delete entry even when test succeeded!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cursor.continue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resolve,
|
||||||
|
reject
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
getByPushEndpoint: function(aPushEndpoint) {
|
getByPushEndpoint: function(aPushEndpoint) {
|
||||||
debug("getByPushEndpoint()");
|
debug("getByPushEndpoint()");
|
||||||
|
|
||||||
|
@ -58,6 +58,10 @@ PushNotificationService.prototype = {
|
|||||||
return PushService._clearAll();
|
return PushService._clearAll();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
clearForDomain: function(domain) {
|
||||||
|
return PushService._clearForDomain(domain);
|
||||||
|
},
|
||||||
|
|
||||||
observe: function observe(subject, topic, data) {
|
observe: function observe(subject, topic, data) {
|
||||||
switch (topic) {
|
switch (topic) {
|
||||||
case "app-startup":
|
case "app-startup":
|
||||||
|
@ -1027,7 +1027,47 @@ this.PushService = {
|
|||||||
_clearAll: function _clearAll() {
|
_clearAll: function _clearAll() {
|
||||||
return this._checkActivated()
|
return this._checkActivated()
|
||||||
.then(_ => this._db.clearAll())
|
.then(_ => this._db.clearAll())
|
||||||
.catch(_ => {
|
.catch(_ => Promise.resolve());
|
||||||
|
},
|
||||||
|
|
||||||
|
_clearForDomain: function(domain) {
|
||||||
|
/**
|
||||||
|
* Copied from ForgetAboutSite.jsm.
|
||||||
|
*
|
||||||
|
* Returns true if the string passed in is part of the root domain of the
|
||||||
|
* current string. For example, if this is "www.mozilla.org", and we pass in
|
||||||
|
* "mozilla.org", this will return true. It would return false the other way
|
||||||
|
* around.
|
||||||
|
*/
|
||||||
|
function hasRootDomain(str, aDomain)
|
||||||
|
{
|
||||||
|
let index = str.indexOf(aDomain);
|
||||||
|
// If aDomain is not found, we know we do not have it as a root domain.
|
||||||
|
if (index == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If the strings are the same, we obviously have a match.
|
||||||
|
if (str == aDomain)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Otherwise, we have aDomain as our root domain iff the index of aDomain is
|
||||||
|
// aDomain.length subtracted from our length and (since we do not have an
|
||||||
|
// exact match) the character before the index is a dot or slash.
|
||||||
|
let prevChar = str[index - 1];
|
||||||
|
return (index == (str.length - aDomain.length)) &&
|
||||||
|
(prevChar == "." || prevChar == "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
let clear = (db, domain) => {
|
||||||
|
db.clearIf(record => {
|
||||||
|
return hasRootDomain(record.origin, domain);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._checkActivated()
|
||||||
|
.then(_ => clear(this._db, domain))
|
||||||
|
.catch(e => {
|
||||||
|
debug("Error forgetting about domain! " + e);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
let {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||||
|
|
||||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||||
Cu.import('resource://gre/modules/Services.jsm');
|
Cu.import('resource://gre/modules/Services.jsm');
|
||||||
|
@ -181,6 +181,16 @@ this.ForgetAboutSite = {
|
|||||||
let np = Cc["@mozilla.org/network/predictor;1"].
|
let np = Cc["@mozilla.org/network/predictor;1"].
|
||||||
getService(Ci.nsINetworkPredictor);
|
getService(Ci.nsINetworkPredictor);
|
||||||
np.reset();
|
np.reset();
|
||||||
|
|
||||||
|
// Push notifications.
|
||||||
|
try {
|
||||||
|
var push = Cc["@mozilla.org/push/NotificationService;1"]
|
||||||
|
.getService(Ci.nsIPushNotificationService);
|
||||||
|
push.clearForDomain(aDomain);
|
||||||
|
} catch (e) {
|
||||||
|
dump("Web Push may not be available.\n");
|
||||||
|
}
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
const Cc = Components.classes;
|
let Cc = Components.classes;
|
||||||
const Ci = Components.interfaces;
|
let Ci = Components.interfaces;
|
||||||
const Cu = Components.utils;
|
let Cu = Components.utils;
|
||||||
|
|
||||||
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
|
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
|
||||||
var profileDir = do_get_profile();
|
var profileDir = do_get_profile();
|
||||||
|
@ -462,6 +462,67 @@ function test_content_preferences_not_cleared_with_uri_contains_domain()
|
|||||||
do_check_false(yield preference_exists(TEST_URI));
|
do_check_false(yield preference_exists(TEST_URI));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Push
|
||||||
|
function test_push_cleared()
|
||||||
|
{
|
||||||
|
let ps;
|
||||||
|
try {
|
||||||
|
ps = Cc["@mozilla.org/push/NotificationService;1"].
|
||||||
|
getService(Ci.nsIPushNotificationService);
|
||||||
|
} catch(e) {
|
||||||
|
// No push service, skip test.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_get_profile();
|
||||||
|
setPrefs();
|
||||||
|
const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
|
||||||
|
const userAgentID = 'bd744428-f125-436a-b6d0-dd0c9845837f';
|
||||||
|
const channelID = '0ef2ad4a-6c49-41ad-af6e-95d2425276bf';
|
||||||
|
|
||||||
|
let db = PushServiceWebSocket.newPushDB();
|
||||||
|
do_register_cleanup(() => {return db.drop().then(_ => db.close());});
|
||||||
|
|
||||||
|
PushService.init({
|
||||||
|
serverURI: "wss://push.example.org/",
|
||||||
|
networkInfo: new MockDesktopNetworkInfo(),
|
||||||
|
db,
|
||||||
|
makeWebSocket(uri) {
|
||||||
|
return new MockWebSocket(uri, {
|
||||||
|
onHello(request) {
|
||||||
|
this.serverSendMsg(JSON.stringify({
|
||||||
|
messageType: 'hello',
|
||||||
|
status: 200,
|
||||||
|
uaid: userAgentID,
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function push_registration_exists(aURL, ps)
|
||||||
|
{
|
||||||
|
return ps.registration(aURL, ChromeUtils.originAttributesToSuffix({ appId: Ci.nsIScriptSecurityManager.NO_APP_ID, inBrowser: false }))
|
||||||
|
.then(record => !!record)
|
||||||
|
.catch(_ => false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const TEST_URL = "https://www.mozilla.org/scope/";
|
||||||
|
do_check_false(yield push_registration_exists(TEST_URL, ps));
|
||||||
|
yield db.put({
|
||||||
|
channelID,
|
||||||
|
pushEndpoint: 'https://example.org/update/clear-success',
|
||||||
|
scope: TEST_URL,
|
||||||
|
version: 1,
|
||||||
|
originAttributes: '',
|
||||||
|
quota: Infinity,
|
||||||
|
});
|
||||||
|
do_check_true(yield push_registration_exists(TEST_URL, ps));
|
||||||
|
ForgetAboutSite.removeDataFromDomain("mozilla.org");
|
||||||
|
yield waitForPurgeNotification();
|
||||||
|
do_check_false(yield push_registration_exists(TEST_URL, ps));
|
||||||
|
}
|
||||||
|
|
||||||
// Cache
|
// Cache
|
||||||
function test_cache_cleared()
|
function test_cache_cleared()
|
||||||
{
|
{
|
||||||
@ -555,6 +616,9 @@ let tests = [
|
|||||||
test_content_preferences_cleared_with_subdomain,
|
test_content_preferences_cleared_with_subdomain,
|
||||||
test_content_preferences_not_cleared_with_uri_contains_domain,
|
test_content_preferences_not_cleared_with_uri_contains_domain,
|
||||||
|
|
||||||
|
// Push
|
||||||
|
test_push_cleared,
|
||||||
|
|
||||||
// Storage
|
// Storage
|
||||||
test_storage_cleared,
|
test_storage_cleared,
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
head = head_forgetaboutsite.js
|
head = head_forgetaboutsite.js ../../../../dom/push/test/xpcshell/head.js
|
||||||
tail =
|
tail =
|
||||||
skip-if = toolkit == 'android' || toolkit == 'gonk'
|
skip-if = toolkit == 'android' || toolkit == 'gonk'
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user