зеркало из https://github.com/mozilla/gecko-dev.git
354 строки
12 KiB
JavaScript
354 строки
12 KiB
JavaScript
"use strict";
|
|
|
|
// Used to access the DOM node in this test
|
|
const DOM_PARENT_ID = "container";
|
|
const DOM_PARENT = document.getElementById(DOM_PARENT_ID);
|
|
const APP_IFRAME_ID = "appFrame";
|
|
const APP_IFRAME_ID2 = "appFrame2";
|
|
|
|
// Settings for testing the permission
|
|
const SESSION_PERSIST_MINUTES = 10;
|
|
const PERMISSION_TYPE = "geolocation";
|
|
const permManager = SpecialPowers.Cc["@mozilla.org/permissionmanager;1"]
|
|
.getService(SpecialPowers.Ci.nsIPermissionManager);
|
|
|
|
// Used to access App's information like appId
|
|
const gAppsService = SpecialPowers.Cc["@mozilla.org/AppsService;1"]
|
|
.getService(SpecialPowers.Ci.nsIAppsService);
|
|
|
|
// Target-app for this testing
|
|
const APP_URL = "http://example.org";
|
|
const APP_MANIFEST = "http://example.org/manifest.webapp";
|
|
|
|
// Used to embed a remote app that open the test-target-app above
|
|
const embedAppHostedManifestURL = window.location.origin +
|
|
'/tests/dom/ipc/tests/file_app.sjs?testToken=test_permission_embed.html&template=file_app.template.webapp';
|
|
var embedApp;
|
|
|
|
// Used to add listener for ipc:content-shutdown that
|
|
// will be triggered after ContentParent::DeallocateTabId
|
|
var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('test_permission_framescript.js'));
|
|
|
|
// Delay reporting a result until after finish() got called
|
|
SimpleTest.waitForExplicitFinish();
|
|
|
|
// Run tests in order
|
|
function runTests() {
|
|
if (!tests.length) {
|
|
ok(true, "pass all tests!");
|
|
SimpleTest.finish();
|
|
return;
|
|
}
|
|
|
|
var test = tests.shift();
|
|
test();
|
|
}
|
|
|
|
function test1() {
|
|
allocateAppFrame(APP_IFRAME_ID, DOM_PARENT, APP_URL, APP_MANIFEST);
|
|
|
|
var appId = gAppsService.getAppLocalIdByManifestURL(APP_MANIFEST);
|
|
|
|
if (!SpecialPowers.hasPermission( PERMISSION_TYPE,
|
|
{ url: APP_URL,
|
|
originAttributes: { appId: appId }})) {
|
|
errorHandler('[test 1] App should have permission: ' + PERMISSION_TYPE);
|
|
}
|
|
|
|
removeAppFrame(APP_IFRAME_ID);
|
|
|
|
// We expect there is no permission for the test-target-app
|
|
// after removing the in-process iframe embedding this app
|
|
runNextIfAppHasPermission(1, false, APP_URL, APP_MANIFEST);
|
|
}
|
|
|
|
function test2() {
|
|
var afterShutdown = function () {
|
|
// We expect there is no permission for the test-target-app
|
|
// after removing the remote iframe embedding this app
|
|
runNextIfAppHasPermission(2, false, APP_URL, APP_MANIFEST);
|
|
};
|
|
|
|
// Test permission after the child-process containing
|
|
// test-target-app is killed
|
|
afterContentShutdown(1, afterShutdown);
|
|
|
|
allocateAppFrame(APP_IFRAME_ID, DOM_PARENT, APP_URL, APP_MANIFEST, true);
|
|
|
|
var appId = gAppsService.getAppLocalIdByManifestURL(APP_MANIFEST);
|
|
|
|
if (!SpecialPowers.hasPermission( PERMISSION_TYPE,
|
|
{ url: APP_URL,
|
|
originAttributes: { appId: appId }})) {
|
|
errorHandler('[test 2] App should have permission: ' + PERMISSION_TYPE);
|
|
}
|
|
|
|
removeAppFrame(APP_IFRAME_ID);
|
|
}
|
|
|
|
function test3() {
|
|
var afterGrandchildShutdown = function () {
|
|
// We expect there is no permission for the test-target-app
|
|
// after removing the remote iframe embedding this app
|
|
runNextIfAppHasPermission(3, false, APP_URL, APP_MANIFEST);
|
|
};
|
|
|
|
// Test permission after the grandchild-process
|
|
// containing test-target-app is killed
|
|
afterContentShutdown(1, afterGrandchildShutdown);
|
|
|
|
allocateAppFrame(APP_IFRAME_ID,
|
|
DOM_PARENT,
|
|
embedApp.manifest.launch_path,
|
|
embedApp.manifestURL,
|
|
true);
|
|
|
|
var appId = gAppsService.getAppLocalIdByManifestURL(APP_MANIFEST);
|
|
|
|
if (!SpecialPowers.hasPermission(PERMISSION_TYPE,
|
|
{ url: APP_URL,
|
|
originAttributes: { appId: appId }})) {
|
|
errorHandler('[test 3] App should have permission: ' + PERMISSION_TYPE);
|
|
}
|
|
}
|
|
|
|
function test4() {
|
|
var afterGrandchildShutdown = function () {
|
|
// We expect there is still a permission for the test-target-app
|
|
// after killing test-target-app on 3rd-level process
|
|
runNextIfAppHasPermission(4, true, APP_URL, APP_MANIFEST);
|
|
};
|
|
|
|
// Test permission after the grandchild-process
|
|
// containing test-target-app is killed
|
|
afterContentShutdown(1, afterGrandchildShutdown);
|
|
|
|
// Open a child process(2nd level) and a grandchild process(3rd level)
|
|
// that contains a test-target-app
|
|
allocateAppFrame(APP_IFRAME_ID,
|
|
DOM_PARENT,
|
|
embedApp.manifest.launch_path,
|
|
embedApp.manifestURL,
|
|
true);
|
|
|
|
// Open another child process that contains
|
|
// another test-target-app(2nd level)
|
|
allocateAppFrame(APP_IFRAME_ID2,
|
|
DOM_PARENT,
|
|
APP_URL,
|
|
APP_MANIFEST,
|
|
true);
|
|
|
|
var appId = gAppsService.getAppLocalIdByManifestURL(APP_MANIFEST);
|
|
|
|
if (!SpecialPowers.hasPermission(PERMISSION_TYPE,
|
|
{ url: APP_URL,
|
|
originAttributes: { appId: appId }})) {
|
|
errorHandler('[test 4] App should have permission: ' + PERMISSION_TYPE);
|
|
}
|
|
}
|
|
|
|
function test5() {
|
|
var afterShutdown = function () {
|
|
// We expect there is no permission for the test-target-app
|
|
// after crashing its parent-process
|
|
runNextIfAppHasPermission(5, false, APP_URL, APP_MANIFEST);
|
|
};
|
|
|
|
// Test permission after the parent-process of test-target-app is crashed.
|
|
afterContentShutdown(2, afterShutdown);
|
|
|
|
allocateAppFrame(APP_IFRAME_ID,
|
|
DOM_PARENT,
|
|
embedApp.manifest.launch_path + '#' + encodeURIComponent('crash'),
|
|
embedApp.manifestURL,
|
|
true);
|
|
|
|
var appId = gAppsService.getAppLocalIdByManifestURL(APP_MANIFEST);
|
|
|
|
if (!SpecialPowers.hasPermission( PERMISSION_TYPE,
|
|
{ url: APP_URL,
|
|
originAttributes: { appId: appId }})) {
|
|
errorHandler('[test 5] App should have permission: ' + PERMISSION_TYPE);
|
|
}
|
|
|
|
// Crash the child-process on 2nd level after
|
|
// the grandchild process on 3rd is allocated
|
|
var handler = {'crash': function() {
|
|
gScript.sendAsyncMessage("crashreporter-status", {});
|
|
|
|
getCrashReporterStatus(function(enable) {
|
|
if (enable) {
|
|
SimpleTest.expectChildProcessCrash();
|
|
}
|
|
crashChildProcess(APP_IFRAME_ID);
|
|
});
|
|
}
|
|
};
|
|
|
|
receiveMessageFromChildFrame(APP_IFRAME_ID, handler);
|
|
}
|
|
|
|
// Setup the prefrences and permissions.
|
|
// This function should be called before any tests
|
|
function setupPrefsAndPermissions() {
|
|
SpecialPowers.pushPrefEnv({"set": [
|
|
["dom.mozBrowserFramesEnabled", true],
|
|
["dom.ipc.tabs.nested.enabled", true],
|
|
["dom.ipc.tabs.disabled", false]]},
|
|
function() {
|
|
var autoManageApp = function () {
|
|
SpecialPowers.setAllAppsLaunchable(true);
|
|
// No confirmation needed when an app is installed and uninstalled.
|
|
SpecialPowers.autoConfirmAppInstall(() => {
|
|
// This callback should trigger the first test
|
|
SpecialPowers.autoConfirmAppUninstall(runTests);
|
|
});
|
|
};
|
|
|
|
setupOpenAppPermission(document, autoManageApp);
|
|
}
|
|
);
|
|
}
|
|
|
|
function setupOpenAppPermission(ctx, callback) {
|
|
SpecialPowers.pushPermissions([
|
|
{ "type": "browser", "allow": true, "context": ctx}, // for mozbrowser
|
|
{ "type": "embed-apps", "allow": true, "context": ctx }, // for mozapp
|
|
{ "type": "webapps-manage", "allow": true, "context": ctx }], // for (un)installing apps
|
|
function checkPermissions() {
|
|
if (SpecialPowers.hasPermission("browser", ctx) &&
|
|
SpecialPowers.hasPermission("embed-apps", ctx) &&
|
|
SpecialPowers.hasPermission("webapps-manage", ctx)) {
|
|
callback();
|
|
} else {
|
|
errorHandler(">> At least one of required permissions to open app is disallowed!\n");
|
|
}
|
|
});
|
|
}
|
|
|
|
function installApp() {
|
|
// Install App from manifest
|
|
var request = navigator.mozApps.install(embedAppHostedManifestURL);
|
|
request.onerror = cbError;
|
|
request.onsuccess = function() {
|
|
// Get installed app
|
|
embedApp = request.result; // Assign to global variable
|
|
runTests();
|
|
}
|
|
}
|
|
|
|
function uninstallApp() {
|
|
var request = navigator.mozApps.mgmt.uninstall(embedApp);
|
|
request.onerror = cbError;
|
|
request.onsuccess = function() {
|
|
info("uninstall app susseccfully!");
|
|
runTests();
|
|
}
|
|
}
|
|
|
|
function removeAppFrame(id) {
|
|
var ifr = document.getElementById(id);
|
|
ifr.remove();
|
|
}
|
|
|
|
function allocateAppFrame(id, parentNode, appSRC, manifestURL, useRemote = false) {
|
|
var ifr = document.createElement('iframe');
|
|
ifr.setAttribute('id', id);
|
|
ifr.setAttribute('remote', useRemote? "true" : "false");
|
|
ifr.setAttribute('mozbrowser', 'true');
|
|
ifr.setAttribute('mozapp', manifestURL);
|
|
ifr.setAttribute('src', appSRC);
|
|
parentNode.appendChild(ifr);
|
|
}
|
|
|
|
function receiveMessageFromChildFrame(id, handlers) {
|
|
var ifr = document.getElementById(id);
|
|
ifr.addEventListener('mozbrowsershowmodalprompt', function (recvMsg) {
|
|
var msg = recvMsg.detail.message;
|
|
handlers[msg]();
|
|
});
|
|
}
|
|
|
|
function addPermissionToApp(appURL, manifestURL) {
|
|
var appId = gAppsService.getAppLocalIdByManifestURL(manifestURL);
|
|
|
|
// Get the time now. This is used for permission manager's expire_time
|
|
var now = Number(Date.now());
|
|
|
|
// Add app's permission asynchronously
|
|
SpecialPowers.pushPermissions([
|
|
{ "type":PERMISSION_TYPE,
|
|
"allow": 1,
|
|
"expireType":permManager.EXPIRE_SESSION,
|
|
"expireTime":now + SESSION_PERSIST_MINUTES*60*1000,
|
|
"context": { url: appURL,
|
|
originAttributes: { appId: appId } }
|
|
}
|
|
], function() {
|
|
runTests();
|
|
});
|
|
}
|
|
|
|
function runNextIfAppHasPermission(round, expect, appURL, manifestURL) {
|
|
var appId = gAppsService.getAppLocalIdByManifestURL(manifestURL);
|
|
|
|
var hasPerm = SpecialPowers.hasPermission(PERMISSION_TYPE,
|
|
{ url: appURL,
|
|
originAttributes: { appId: appId }});
|
|
var result = (expect==hasPerm);
|
|
if (result) {
|
|
runTests();
|
|
} else {
|
|
errorHandler( '[test ' + round + '] App should ' + ((expect)? '':'NOT ') +
|
|
'have permission: ' + PERMISSION_TYPE);
|
|
}
|
|
}
|
|
|
|
function afterContentShutdown(times, callback) {
|
|
// handle the message from test_permission_framescript.js
|
|
var num = 0;
|
|
gScript.addMessageListener('content-shutdown', function onShutdown(data) {
|
|
num += 1;
|
|
if (num >= times) {
|
|
gScript.removeMessageListener('content-shutdown', onShutdown);
|
|
callback();
|
|
}
|
|
});
|
|
}
|
|
|
|
function getCrashReporterStatus(callback) {
|
|
gScript.addMessageListener('crashreporter-enable', function getStatus(data) {
|
|
gScript.removeMessageListener('crashreporter-enable', getStatus);
|
|
callback(data);
|
|
});
|
|
}
|
|
|
|
// Inject a frame script that crashes the content process
|
|
function crashChildProcess(frameId) {
|
|
var child = document.getElementById(frameId);
|
|
var mm = SpecialPowers.getBrowserFrameMessageManager(child);
|
|
var childFrameScriptStr =
|
|
'function ContentScriptScope() {' +
|
|
'var Cu = Components.utils;' +
|
|
'Cu.import("resource://gre/modules/ctypes.jsm");' +
|
|
'var crash = function() {' +
|
|
'var zero = new ctypes.intptr_t(8);' +
|
|
'var badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t));' +
|
|
'badptr.contents;' +
|
|
'};' +
|
|
'privateNoteIntentionalCrash();' +
|
|
'crash();' +
|
|
'}';
|
|
mm.loadFrameScript('data:,new ' + childFrameScriptStr, false);
|
|
}
|
|
|
|
function errorHandler(errMsg) {
|
|
ok(false, errMsg);
|
|
SimpleTest.finish();
|
|
}
|
|
|
|
function cbError(e) {
|
|
errorHandler("Error callback invoked: " + this.error.name);
|
|
}
|