Bug 1233644 - use pattern matching when listening clear-origin-data. r=baku

This commit is contained in:
Yoshi Huang 2015-12-18 18:58:41 +08:00
parent aff7c68ec9
commit 43a41ee1b5
8 changed files with 239 additions and 52 deletions

View File

@ -6,8 +6,6 @@
#include "ServiceWorkerManager.h"
#include "mozIApplication.h"
#include "nsIAppsService.h"
#include "nsIConsoleService.h"
#include "nsIDOMEventTarget.h"
#include "nsIDocument.h"
@ -4466,11 +4464,11 @@ ServiceWorkerManager::PropagateRemoveAll()
}
void
ServiceWorkerManager::RemoveAllRegistrations(PrincipalOriginAttributes* aParams)
ServiceWorkerManager::RemoveAllRegistrations(OriginAttributesPattern* aPattern)
{
AssertIsOnMainThread();
MOZ_ASSERT(aParams);
MOZ_ASSERT(aPattern);
for (auto it1 = mRegistrationInfos.Iter(); !it1.Done(); it1.Next()) {
ServiceWorkerManager::RegistrationDataPerPrincipal* data = it1.UserData();
@ -4484,49 +4482,14 @@ ServiceWorkerManager::RemoveAllRegistrations(PrincipalOriginAttributes* aParams)
MOZ_ASSERT(reg);
MOZ_ASSERT(reg->mPrincipal);
bool equals = false;
if (aParams->mInBrowser) {
// When we do a system wide "clear cookies and stored data" on B2G we
// get the "clear-origin-data" notification with the System app appID
// and the browserOnly flag set to true. Web sites registering a
// service worker on B2G have a principal with the following
// information: web site origin + System app appId + inBrowser=1 So
// we need to check if the service worker registration info contains
// the System app appID and the enabled inBrowser flag and in that
// case remove it from the registry.
OriginAttributes attrs =
mozilla::BasePrincipal::Cast(reg->mPrincipal)->OriginAttributesRef();
equals = attrs == *aParams;
} else {
// If we get the "clear-origin-data" notification because of an app
// uninstallation, we need to check the full principal to get the
// match in the service workers registry. If we find a match, we
// unregister the worker.
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
if (NS_WARN_IF(!appsService)) {
continue;
}
nsCOMPtr<mozIApplication> app;
appsService->GetAppByLocalId(aParams->mAppId, getter_AddRefs(app));
if (NS_WARN_IF(!app)) {
continue;
}
nsCOMPtr<nsIPrincipal> principal;
app->GetPrincipal(getter_AddRefs(principal));
if (NS_WARN_IF(!principal)) {
continue;
}
reg->mPrincipal->Equals(principal, &equals);
bool matches =
aPattern->Matches(BasePrincipal::Cast(reg->mPrincipal)->OriginAttributesRef());
if (!matches) {
continue;
}
if (equals) {
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->ForceUnregister(data, reg);
}
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->ForceUnregister(data, reg);
}
}
}
@ -4699,10 +4662,10 @@ ServiceWorkerManager::Observe(nsISupports* aSubject,
if (strcmp(aTopic, CLEAR_ORIGIN_DATA) == 0) {
MOZ_ASSERT(XRE_IsParentProcess());
PrincipalOriginAttributes attrs;
MOZ_ALWAYS_TRUE(attrs.Init(nsAutoString(aData)));
OriginAttributesPattern pattern;
MOZ_ALWAYS_TRUE(pattern.Init(nsAutoString(aData)));
RemoveAllRegistrations(&attrs);
RemoveAllRegistrations(&pattern);
return NS_OK;
}
@ -5052,7 +5015,7 @@ ServiceWorkerManager::UpdateTimerFired(nsIPrincipal* aPrincipal,
}
PrincipalOriginAttributes attrs =
mozilla::BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
// Then trigger an update to fire asynchronously now.
PropagateSoftUpdate(attrs, NS_ConvertUTF8toUTF16(aScope));

View File

@ -640,10 +640,9 @@ private:
void
RemoveRegistrationInternal(ServiceWorkerRegistrationInfo* aRegistration);
// Removes all service worker registrations that matches the given
// mozIApplicationClearPrivateDataParams.
// Removes all service worker registrations that matches the given pattern.
void
RemoveAllRegistrations(PrincipalOriginAttributes* aParams);
RemoveAllRegistrations(OriginAttributesPattern* aPattern);
RefPtr<ServiceWorkerManagerChild> mActor;

View File

@ -0,0 +1,51 @@
<!DOCTYPE html>
<html>
<head>
<title>Test app for bug 1169249</title>
<script type='application/javascript;version=1.7'>
function ok(aCondition, aMessage) {
if (aCondition) {
alert('OK: ' + aMessage);
} else {
alert('KO: ' + aMessage);
}
}
function ready() {
alert('READY');
}
function registerServiceWorker() {
return new Promise((resolve, reject) => {
navigator.serviceWorker.ready.then(() => {
ready();
resolve();
});
navigator.serviceWorker.register('../empty.js', {scope: '.'})
.then(registration => {
ok(true, 'service worker registered');
})
.catch(reject);
});
}
function AddIframe() {
return new Promise((resolve, reject) => {
let iframe = document.createElement('iframe');
iframe.setAttribute('mozbrowser', 'true');
iframe.setAttribute('src', "http://test/chrome/dom/workers/test/serviceworkers/serviceworker.html");
document.body.appendChild(iframe);
iframe.addEventListener("mozbrowserloadend", resolve);
});
}
function runTests() {
return Promise.resolve()
.then(AddIframe)
.then(registerServiceWorker)
.then(ready)
}
</script>
</head>
<body onload='runTests()'>
</body>
</html>

View File

@ -0,0 +1,5 @@
{
"name": "App",
"launch_path": "/index.html",
"description": "Test app for bug 1169249"
}

View File

@ -0,0 +1 @@
Content-Type: application/manifest+json

View File

@ -3,7 +3,10 @@ skip-if = buildapp == 'b2g' || os == 'android'
support-files =
app/*
app2/*
app3/*
chrome_helpers.js
empty.js
serviceworker.html
serviceworkerinfo_iframe.html
serviceworkermanager_iframe.html
serviceworkerregistrationinfo_iframe.html
@ -12,6 +15,7 @@ support-files =
[test_aboutserviceworkers.html]
skip-if = true #bug 1193319
[test_clear_origin_data.html]
[test_app_installation.html]
[test_privateBrowsing.html]
[test_serviceworkerinfo.xul]

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script>
navigator.serviceWorker.register("worker.js");
</script>
</head>
<body>
This is a test page.
</body>
<html>

View File

@ -0,0 +1,152 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id={1233644}
-->
<head>
<title>Test for Bug {1233644}</title>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/chrome-harness.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={1233644}">Mozilla Bug {1233644}</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="application/javascript;version=1.7">
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "gServiceWorkerManager",
"@mozilla.org/serviceworkers/manager;1",
"nsIServiceWorkerManager");
SimpleTest.waitForExplicitFinish();
const gOrigin = 'http://test/chrome/dom/workers/test/serviceworkers/app3';
const appManifestURL = gOrigin + '/manifest.webapp';
let gApp;
addLoadEvent(go);
function setup() {
info('Setting up');
return new Promise((resolve, reject) => {
SpecialPowers.setAllAppsLaunchable(true);
SpecialPowers.pushPrefEnv({'set': [
['dom.mozBrowserFramesEnabled', true],
['dom.serviceWorkers.exemptFromPerDomainMax', true],
['dom.serviceWorkers.enabled', true],
['dom.serviceWorkers.testing.enabled', true],
['dom.serviceWorkers.interception.enabled', true],
]}, () => {
SpecialPowers.pushPermissions([
{ 'type': 'webapps-manage', 'allow': 1, 'context': document },
{ 'type': 'browser', 'allow': 1, 'context': document },
{ 'type': 'embed-apps', 'allow': 1, 'context': document }
], () => {
SpecialPowers.autoConfirmAppInstall(() => {
SpecialPowers.autoConfirmAppUninstall(resolve);
});
});
});
});
}
function installApp() {
return new Promise((resolve, reject) => {
let req = navigator.mozApps.install(appManifestURL);
req.onsuccess = function() {
gApp = req.result;
is(req.result.manifestURL, appManifestURL, 'app installed');
if (req.result.installState == 'installed') {
is(req.result.installState, 'installed', 'app downloaded');
resolve()
} else {
req.result.ondownloadapplied = function() {
is(req.result.installState, 'installed', 'app downloaded');
resolve();
}
}
}
req.onerror = reject;
});
}
function pushPermission() {
return new Promise((resolve, reject) => {
SpecialPowers.pushPermissions([
{'type': 'browser', 'allow': 1, 'context': {manifestURL: appManifestURL}}], resolve);
});
}
function checkSwRegistration() {
return new Promise((resolve, reject) => {
let registrations = gServiceWorkerManager.getAllRegistrations();
is(registrations.length, 0, "All registrations should be removed.");
resolve();
});
}
function launchApp() {
if (!gApp) {
ok(false, 'No test application to launch');
return Promise.reject();
}
return new Promise((resolve, reject) => {
let iframe = document.createElement('iframe');
iframe.setAttribute('mozbrowser', 'true');
iframe.setAttribute('mozapp', gApp.manifestURL);
iframe.addEventListener('mozbrowsershowmodalprompt', function listener(e) {
let message = e.detail.message;
if (/OK/.exec(message)) {
ok(true, "Message from app: " + message);
} else if (/READY/.exec(message)) {
ok(true, 'Message from app: ' + message);
resolve();
}
}, false);
let domParent = document.getElementById('container');
domParent.appendChild(iframe);
SpecialPowers.wrap(iframe.contentWindow).location =
gOrigin + gApp.manifest.launch_path;
});
}
function uninstallApp() {
return new Promise((resolve, reject) => {
if (!gApp) {
return reject();
}
let req = navigator.mozApps.mgmt.uninstall(gApp);
req.onsuccess = resolve;
req.onerror = reject;
});
}
function go() {
setup()
.then(installApp)
.then(pushPermission)
.then(launchApp)
.then(uninstallApp)
.then(checkSwRegistration)
.then(SimpleTest.finish)
.catch((e) => {
ok(false, 'Unexpected error ' + e);
SimpleTest.finish();
});
}
</script>
</pre>
<div id="container"></div>
</body>
</html>