mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1149868 - Move permissionObserver to SpecialPowersObserver to listen all perm-changed signals. r=jmaher
This commit is contained in:
parent
874588c43a
commit
e7ffccf507
9
testing/mochitest/tests/Harness_sanity/app.html
Normal file
9
testing/mochitest/tests/Harness_sanity/app.html
Normal file
@ -0,0 +1,9 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>empty app</title>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
55
testing/mochitest/tests/Harness_sanity/file_app.sjs
Normal file
55
testing/mochitest/tests/Harness_sanity/file_app.sjs
Normal file
@ -0,0 +1,55 @@
|
||||
var gBasePath = "tests/testing/mochitest/tests/Harness_sanity/";
|
||||
|
||||
function handleRequest(request, response) {
|
||||
var query = getQuery(request);
|
||||
|
||||
var testToken = '';
|
||||
if ('testToken' in query) {
|
||||
testToken = query.testToken;
|
||||
}
|
||||
|
||||
var template = '';
|
||||
if ('template' in query) {
|
||||
template = query.template;
|
||||
}
|
||||
var template = gBasePath + template;
|
||||
response.setHeader("Content-Type", "application/x-web-app-manifest+json", false);
|
||||
response.write(readTemplate(template).replace(/TESTTOKEN/g, testToken));
|
||||
}
|
||||
|
||||
// Copy-pasted incantations. There ought to be a better way to synchronously read
|
||||
// a file into a string, but I guess we're trying to discourage that.
|
||||
function readTemplate(path) {
|
||||
var file = Components.classes["@mozilla.org/file/directory_service;1"].
|
||||
getService(Components.interfaces.nsIProperties).
|
||||
get("CurWorkD", Components.interfaces.nsILocalFile);
|
||||
var fis = Components.classes['@mozilla.org/network/file-input-stream;1'].
|
||||
createInstance(Components.interfaces.nsIFileInputStream);
|
||||
var cis = Components.classes["@mozilla.org/intl/converter-input-stream;1"].
|
||||
createInstance(Components.interfaces.nsIConverterInputStream);
|
||||
var split = path.split("/");
|
||||
for(var i = 0; i < split.length; ++i) {
|
||||
file.append(split[i]);
|
||||
}
|
||||
fis.init(file, -1, -1, false);
|
||||
cis.init(fis, "UTF-8", 0, 0);
|
||||
|
||||
var data = "";
|
||||
let str = {};
|
||||
let read = 0;
|
||||
do {
|
||||
read = cis.readString(0xffffffff, str); // read as much as we can and put it in str.value
|
||||
data += str.value;
|
||||
} while (read != 0);
|
||||
cis.close();
|
||||
return data;
|
||||
}
|
||||
|
||||
function getQuery(request) {
|
||||
var query = {};
|
||||
request.queryString.split('&').forEach(function (val) {
|
||||
var [name, value] = val.split('=');
|
||||
query[name] = unescape(value);
|
||||
});
|
||||
return query;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "EMPTY-APP",
|
||||
"description": "Empty app for Harness_sanity.",
|
||||
"launch_path": "/tests/testing/mochitest/tests/Harness_sanity/TESTTOKEN",
|
||||
"icons": { "128": "default_icon" }
|
||||
}
|
@ -12,6 +12,11 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
|
||||
[test_SpecialPowersExtension2.html]
|
||||
support-files = file_SpecialPowersFrame1.html
|
||||
[test_SpecialPowersPushPermissions.html]
|
||||
[test_SpecialPowersPushAppPermissions.html]
|
||||
support-files =
|
||||
file_app.sjs
|
||||
file_app.template.webapp
|
||||
app.html
|
||||
[test_SpecialPowersPushPrefEnv.html]
|
||||
[test_SimpletestGetTestFileURL.html]
|
||||
[test_SpecialPowersLoadChromeScript.html]
|
||||
|
@ -0,0 +1,111 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for SpecialPowers extension</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="pushPermissionsToSelf();">
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
// Used to access App's information like appId
|
||||
const gAppsService = SpecialPowers.Cc["@mozilla.org/AppsService;1"]
|
||||
.getService(SpecialPowers.Ci.nsIAppsService);
|
||||
var gApp;
|
||||
const gAppSource = 'app.html';
|
||||
const FILE_APP = 'file_app.sjs';
|
||||
const WEBAPP_TEMPLATE = 'file_app.template.webapp';
|
||||
const DIR_PATH = 'testing/mochitest/tests/Harness_sanity/';
|
||||
// The base path must be same as the gBasePath in file_app.sjs and the
|
||||
// launch_path before TESTTOKEN in file_app.template.webapp
|
||||
const BASE_PATH = '/tests/' + DIR_PATH;
|
||||
const FILE_APP_PATH = BASE_PATH + FILE_APP;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function cbError(e) {
|
||||
ok(false, "Error callback invoked: " + this.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function pushPermissionsToSelf() {
|
||||
SpecialPowers.pushPermissions([
|
||||
{ "type": "pAppPermission", "allow": true, "context": document }
|
||||
], allowManagingApps);
|
||||
}
|
||||
|
||||
// Setup the prefrences and permissions
|
||||
function allowManagingApps() {
|
||||
SpecialPowers.pushPermissions([
|
||||
{ "type": "webapps-manage", "allow": true, "context": document }
|
||||
], function() {
|
||||
SpecialPowers.setAllAppsLaunchable(true);
|
||||
// No confirmation needed when an app is installed and uninstalled.
|
||||
SpecialPowers.autoConfirmAppInstall(() => {
|
||||
SpecialPowers.autoConfirmAppUninstall(
|
||||
function() {
|
||||
installApp(gAppSource, WEBAPP_TEMPLATE);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function installApp(aTestToken, aTemplate) {
|
||||
// Install App from manifest
|
||||
var hostedManifestURL = window.location.origin + '/' + FILE_APP_PATH +
|
||||
'?testToken=' + aTestToken + '&template=' + aTemplate;
|
||||
var request = navigator.mozApps.install(hostedManifestURL);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = function() {
|
||||
// Get installed app
|
||||
gApp = request.result; // Assign to global variable
|
||||
pushPermissionsToApp();
|
||||
}
|
||||
}
|
||||
|
||||
function pushPermissionsToApp() {
|
||||
var appId = gAppsService.getAppLocalIdByManifestURL(gApp.manifestURL);
|
||||
var context = { url: gApp.origin,
|
||||
appId: appId,
|
||||
isInBrowserElement: false };
|
||||
SpecialPowers.pushPermissions([
|
||||
{ "type": "pAppPermission", "allow": true, "context": context }
|
||||
], testPermissionsForApp);
|
||||
}
|
||||
|
||||
function testPermissionsForApp() {
|
||||
var appId = gAppsService.getAppLocalIdByManifestURL(gApp.manifestURL);
|
||||
var context = { url: gApp.origin,
|
||||
appId: appId,
|
||||
isInBrowserElement: false };
|
||||
ok(SpecialPowers.hasPermission('pAppPermission', context), 'pAppPermission should have permission');
|
||||
uninstallApp();
|
||||
}
|
||||
|
||||
function uninstallApp() {
|
||||
var request = navigator.mozApps.mgmt.uninstall(gApp);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = function() {
|
||||
testPermissionsForSelfAndApp();
|
||||
}
|
||||
}
|
||||
|
||||
function testPermissionsForSelfAndApp() {
|
||||
var appId = gAppsService.getAppLocalIdByManifestURL(gApp.manifestURL);
|
||||
var context = { url: gApp.origin,
|
||||
appId: appId,
|
||||
isInBrowserElement: false };
|
||||
ok(!SpecialPowers.hasPermission('pAppPermission', context), 'pAppPermission should not have permission');
|
||||
|
||||
ok(SpecialPowers.hasPermission('pAppPermission', document), 'pAppPermission should have permission');
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -146,6 +146,9 @@ SpecialPowersObserver.prototype = new SpecialPowersObserverAPI();
|
||||
obs.removeObserver(this, "chrome-document-global-created");
|
||||
obs.removeObserver(this, "http-on-modify-request");
|
||||
obs.removeObserver(this, "xpcom-shutdown");
|
||||
this._registerObservers._topics.forEach(function(element) {
|
||||
obs.removeObserver(this._registerObservers, element);
|
||||
});
|
||||
this._removeProcessCrashObservers();
|
||||
|
||||
if (this._isFrameScriptLoaded) {
|
||||
@ -200,6 +203,27 @@ SpecialPowersObserver.prototype = new SpecialPowersObserverAPI();
|
||||
this._processCrashObserversRegistered = false;
|
||||
};
|
||||
|
||||
SpecialPowersObserver.prototype._registerObservers = {
|
||||
_self: null,
|
||||
_topics: [],
|
||||
_add: function(topic) {
|
||||
if (this._topics.indexOf(topic) < 0) {
|
||||
this._topics.push(topic);
|
||||
Services.obs.addObserver(this, topic, false);
|
||||
}
|
||||
},
|
||||
observe: function (aSubject, aTopic, aData) {
|
||||
var msg = { aData: aData };
|
||||
switch (aTopic) {
|
||||
case "perm-changed":
|
||||
var permission = aSubject.QueryInterface(Ci.nsIPermission);
|
||||
msg.permission = { appId: permission.appId, type: permission.type };
|
||||
default:
|
||||
this._self._sendAsyncMessage("specialpowers-" + aTopic, msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* messageManager callback function
|
||||
* This will get requests from our API in the window and process them in chrome for it
|
||||
|
@ -409,12 +409,16 @@ SpecialPowersObserverAPI.prototype = {
|
||||
}
|
||||
|
||||
case "SPObserverService": {
|
||||
let topic = aMessage.json.observerTopic;
|
||||
switch (aMessage.json.op) {
|
||||
case "notify":
|
||||
let topic = aMessage.json.observerTopic;
|
||||
let data = aMessage.json.observerData
|
||||
Services.obs.notifyObservers(null, topic, data);
|
||||
break;
|
||||
case "add":
|
||||
this._registerObservers._self = this;
|
||||
this._registerObservers._add(topic);
|
||||
break;
|
||||
default:
|
||||
throw new SpecialPowersError("Invalid operation for SPObserverervice");
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ function SpecialPowersAPI() {
|
||||
this._permissionsUndoStack = [];
|
||||
this._pendingPermissions = [];
|
||||
this._applyingPermissions = false;
|
||||
this._observingPermissions = false;
|
||||
this._fm = null;
|
||||
this._cb = null;
|
||||
this._quotaManagerCallbackInfos = null;
|
||||
@ -830,6 +831,21 @@ SpecialPowersAPI.prototype = {
|
||||
// that the callback checks for. The second delay is because pref
|
||||
// observers often defer making their changes by posting an event to the
|
||||
// event loop.
|
||||
if (!this._observingPermissions) {
|
||||
this._observingPermissions = true;
|
||||
// If specialpowers is in main-process, then we can add a observer
|
||||
// to get all 'perm-changed' signals. Otherwise, it can't receive
|
||||
// all signals, so we register a observer in specialpowersobserver(in
|
||||
// main-process) and get signals from it.
|
||||
if (this.isMainProcess()) {
|
||||
this.permissionObserverProxy._specialPowersAPI = this;
|
||||
Services.obs.addObserver(this.permissionObserverProxy, "perm-changed", false);
|
||||
} else {
|
||||
this.registerObservers("perm-changed");
|
||||
// bind() is used to set 'this' to SpecialPowersAPI itself.
|
||||
this._addMessageListener("specialpowers-perm-changed", this.permChangedProxy.bind(this));
|
||||
}
|
||||
}
|
||||
this._permissionsUndoStack.push(cleanupPermissions);
|
||||
this._pendingPermissions.push([pendingPermissions,
|
||||
this._delayCallbackTwice(callback)]);
|
||||
@ -839,6 +855,51 @@ SpecialPowersAPI.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* This function should be used when specialpowers is in content process but
|
||||
* it want to get the notification from chrome space.
|
||||
*
|
||||
* This function will call Services.obs.addObserver in SpecialPowersObserver
|
||||
* (that is in chrome process) and forward the data received to SpecialPowers
|
||||
* via messageManager.
|
||||
* You can use this._addMessageListener("specialpowers-YOUR_TOPIC") to fire
|
||||
* the callback.
|
||||
*
|
||||
* To get the expected data, you should modify
|
||||
* SpecialPowersObserver.prototype._registerObservers.observe. Or the message
|
||||
* you received from messageManager will only contain 'aData' from Service.obs.
|
||||
*
|
||||
* NOTICE: there is no implementation of _addMessageListener in
|
||||
* ChromePowers.js
|
||||
*/
|
||||
registerObservers: function(topic) {
|
||||
var msg = {
|
||||
'op': 'add',
|
||||
'observerTopic': topic,
|
||||
};
|
||||
this._sendSyncMessage("SPObserverService", msg);
|
||||
},
|
||||
|
||||
permChangedProxy: function(aMessage) {
|
||||
let permission = aMessage.json.permission;
|
||||
let aData = aMessage.json.aData;
|
||||
this._permissionObserver.observe(permission, aData);
|
||||
},
|
||||
|
||||
permissionObserverProxy: {
|
||||
// 'this' in permChangedObserverProxy is the permChangedObserverProxy
|
||||
// object itself. The '_specialPowersAPI' will be set to the 'SpecialPowersAPI'
|
||||
// object to call the member function in SpecialPowersAPI.
|
||||
_specialPowersAPI: null,
|
||||
observe: function (aSubject, aTopic, aData)
|
||||
{
|
||||
if (aTopic == "perm-changed") {
|
||||
var permission = aSubject.QueryInterface(Ci.nsIPermission);
|
||||
this._specialPowersAPI._permissionObserver.observe(permission, aData);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
popPermissions: function(callback) {
|
||||
if (this._permissionsUndoStack.length > 0) {
|
||||
// See pushPermissions comment regarding delay.
|
||||
@ -847,7 +908,11 @@ SpecialPowersAPI.prototype = {
|
||||
this._pendingPermissions.push([this._permissionsUndoStack.pop(), cb]);
|
||||
this._applyPermissions();
|
||||
} else {
|
||||
this._setTimeout(callback);
|
||||
if (this._observingPermissions) {
|
||||
this._observingPermissions = false;
|
||||
this._removeMessageListener("specialpowers-perm-changed", this.permChangedProxy.bind(this));
|
||||
}
|
||||
this._setTimeout(callback);
|
||||
}
|
||||
},
|
||||
|
||||
@ -870,15 +935,39 @@ SpecialPowersAPI.prototype = {
|
||||
_lastPermission: {},
|
||||
_callBack: null,
|
||||
_nextCallback: null,
|
||||
|
||||
observe: function (aSubject, aTopic, aData)
|
||||
_obsDataMap: {
|
||||
'deleted':'remove',
|
||||
'added':'add'
|
||||
},
|
||||
observe: function (permission, aData)
|
||||
{
|
||||
if (aTopic == "perm-changed") {
|
||||
var permission = aSubject.QueryInterface(Ci.nsIPermission);
|
||||
if (this._self._applyingPermissions) {
|
||||
if (permission.type == this._lastPermission.type) {
|
||||
Services.obs.removeObserver(this, "perm-changed");
|
||||
this._self._setTimeout(this._callback);
|
||||
this._self._setTimeout(this._nextCallback);
|
||||
this._callback = null;
|
||||
this._nextCallback = null;
|
||||
}
|
||||
} else {
|
||||
var found = false;
|
||||
for (var i = 0; !found && i < this._self._permissionsUndoStack.length; i++) {
|
||||
var undos = this._self._permissionsUndoStack[i];
|
||||
for (var j = 0; j < undos.length; j++) {
|
||||
var undo = undos[j];
|
||||
if (undo.op == this._obsDataMap[aData] &&
|
||||
undo.appId == permission.appId &&
|
||||
undo.type == permission.type) {
|
||||
// Remove this undo item if it has been done by others(not
|
||||
// specialpowers itself.)
|
||||
undos.splice(j,1);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!undos.length) {
|
||||
// Remove the empty row in permissionsUndoStack
|
||||
this._self._permissionsUndoStack.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -910,8 +999,6 @@ SpecialPowersAPI.prototype = {
|
||||
self._applyPermissions();
|
||||
}
|
||||
|
||||
Services.obs.addObserver(this._permissionObserver, "perm-changed", false);
|
||||
|
||||
for (var idx in pendingActions) {
|
||||
var perm = pendingActions[idx];
|
||||
this._sendSyncMessage('SPPermissionManager', perm)[0];
|
||||
|
Loading…
Reference in New Issue
Block a user