Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Commit

Permalink
Merge pull request #11944 from gasolin/issue-887669
Browse files Browse the repository at this point in the history
Bug 887669 - [Test][System] Unit test for Permission Manager, r=alive
  • Loading branch information
gasolin committed Sep 7, 2013
2 parents ba2bc4e + c272503 commit cf6272f
Show file tree
Hide file tree
Showing 2 changed files with 296 additions and 133 deletions.
281 changes: 148 additions & 133 deletions apps/system/js/permission_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,68 +3,110 @@

'use strict';

var PermissionManager = (function() {
var _ = navigator.mozL10n.get;

window.addEventListener('mozChromeEvent', function pm_chromeEventHandler(e) {
var detail = e.detail;
switch (detail.type) {
case 'permission-prompt':
overlay.dataset.type = detail.permission;
handlePermissionPrompt(detail);
break;
case 'cancel-permission-prompt':
discardPermissionRequest();
break;
case 'fullscreenoriginchange':
delete overlay.dataset.type;
handleFullscreenOriginChange(detail);
break;
}
});
var PermissionManager = {

var fullscreenRequest = undefined;
// Div over in which the permission UI resides.
overlay: document.getElementById('permission-screen'),
dialog: document.getElementById('permission-dialog'),
message: document.getElementById('permission-message'),
moreInfo: document.getElementById('permission-more-info'),
moreInfoLink: document.getElementById('permission-more-info-link'),
moreInfoBox: document.getElementById('permission-more-info-box'),

var handleFullscreenOriginChange = function(detail) {
// "Yes"/"No" buttons on the permission UI.
yes: document.getElementById('permission-yes'),
no: document.getElementById('permission-no'),

// Remember the choice checkbox
remember: document.getElementById('permission-remember-checkbox'),
rememberSection: document.getElementById('permission-remember-section'),

init: function pm_init() {
var self = this;

window.addEventListener('mozChromeEvent',
function pm_chromeEventHandler(evt) {
var detail = evt.detail;
switch (detail.type) {
case 'permission-prompt':
self.overlay.dataset.type = detail.permission;
self.handlePermissionPrompt(detail).bind(self);
break;
case 'cancel-permission-prompt':
self.discardPermissionRequest().bind(self);
break;
case 'fullscreenoriginchange':
delete self.overlay.dataset.type;
self.handleFullscreenOriginChange(detail).bind(self);
break;
}
});

this.rememberSection.addEventListener('click',
function onLabelClick() {
self.remember.checked = !self.remember.checked;
});

// On home/holdhome pressed, discard permission request.
// XXX: We should make permission dialog be embededd in appWindow
// Gaia bug is https://bugzilla.mozilla.org/show_bug.cgi?id=853711
// Gecko bug is https://bugzilla.mozilla.org/show_bug.cgi?id=852013
window.addEventListener('home', this.discardPermissionRequest).bind(this);
window.addEventListener('holdhome',
this.discardPermissionRequest).bind(this);
},


fullscreenRequest: undefined,

handleFullscreenOriginChange:
function pm_handleFullscreenOriginChange(detail) {
// If there's already a fullscreen request visible, cancel it,
// we'll show the request for the new domain.
if (fullscreenRequest != undefined) {
cancelRequest(fullscreenRequest);
fullscreenRequest = undefined;
if (this.fullscreenRequest != undefined) {
this.cancelRequest(this.fullscreenRequest);
this.fullscreenRequest = undefined;
}
if (detail.fullscreenorigin != WindowManager.getDisplayedApp()) {
var _ = navigator.mozL10n.get;
// The message to be displayed on the approval UI.
var message =
_('fullscreen-request', { 'origin': detail.fullscreenorigin });
fullscreenRequest = requestPermission(message, '',
this.fullscreenRequest =
this.requestPermission(message, '',
/* yesCallback */ null,
/* noCallback */ function() {
document.mozCancelFullScreen();
});
}).bind(this);
}
};
},

var handlePermissionPrompt = function pm_handlePermissionPrompt(detail) {
remember.checked = detail.remember ? true : false;
handlePermissionPrompt: function pm_handlePermissionPrompt(detail) {
this.remember.checked = detail.remember ? true : false;
var str = '';

var permissionID = 'perm-' + detail.permission.replace(':', '-');
var _ = navigator.mozL10n.get;

if (detail.isApp) { // App
str = _(permissionID + '-appRequest', { 'app': detail.appName });
} else { // Web content
str = _(permissionID + '-webRequest', { 'site': detail.origin });
}

var moreInfoText = _(permissionID + '-more-info');

requestPermission(str, moreInfoText, function pm_permYesCB() {
dispatchResponse(detail.id, 'permission-allow', remember.checked);
}, function pm_permNoCB() {
dispatchResponse(detail.id, 'permission-deny', remember.checked);
var self = this;
this.requestPermission(str, moreInfoText,
function pm_permYesCB() {
self.dispatchResponse(detail.id, 'permission-allow',
self.remember.checked);
},
function pm_permNoCB() {
self.dispatchResponse(detail.id, 'permission-deny',
self.remember.checked);
});
};
},

var dispatchResponse = function pm_dispatchResponse(id, type, remember) {
dispatchResponse: function pm_dispatchResponse(id, type, remember) {
var event = document.createEvent('CustomEvent');
remember = remember ? true : false;

Expand All @@ -74,89 +116,75 @@ var PermissionManager = (function() {
remember: remember
});
window.dispatchEvent(event);
};
},

// A queue of pending requests. Callers of requestPermission() must be
// careful not to create an infinite loop!
var pending = [];

// Div over in which the permission UI resides.
var overlay = document.getElementById('permission-screen');
var dialog = document.getElementById('permission-dialog');
var message = document.getElementById('permission-message');
var moreInfo = document.getElementById('permission-more-info');
var moreInfoLink = document.getElementById('permission-more-info-link');
var moreInfoBox = document.getElementById('permission-more-info-box');

// "Yes"/"No" buttons on the permission UI.
var yes = document.getElementById('permission-yes');
var no = document.getElementById('permission-no');

// Remember the choice checkbox
var remember = document.getElementById('permission-remember-checkbox');
var rememberSection = document.getElementById('permission-remember-section');
pending: [],

// The ID of the next permission request. This is incremented by one
// on every request, modulo some large number to prevent overflow problems.
var nextRequestID = 0;
nextRequestID: 0,

// The ID of the request currently visible on the screen. This has the value
// "undefined" when there is no request visible on the screen.
var currentRequestId = undefined;
currentRequestId: undefined,

var hidePermissionPrompt = function() {
overlay.classList.remove('visible');
currentRequestId = undefined;
hidePermissionPrompt: function pm_hidePermissionPrompt() {
this.overlay.classList.remove('visible');
this.currentRequestId = undefined;
// Cleanup the event handlers.
yes.removeEventListener('click', clickHandler);
yes.callback = null;
no.removeEventListener('click', clickHandler);
no.callback = null;

moreInfoLink.removeEventListener('click', clickHandler);
moreInfo.classList.add('hidden');
};
this.yes.removeEventListener('click',
this.clickHandler.bind(this));
this.yes.callback = null;
this.no.removeEventListener('click',
this.clickHandler.bind(this));
this.no.callback = null;

this.moreInfoLink.removeEventListener('click',
this.clickHandler.bind(this));
this.moreInfo.classList.add('hidden');
},

// Show the next request, if we have one.
var showNextPendingRequest = function() {
if (pending.length == 0)
showNextPendingRequest: function pm_showNextPendingRequest() {
if (this.pending.length == 0)
return;
var request = pending.shift();
showPermissionPrompt(request.id,
var request = this.pending.shift();
this.showPermissionPrompt(request.id,
request.message,
request.moreInfoText,
request.yescallback,
request.nocallback);
};
},

// This is the event listener function for the yes/no buttons.
var clickHandler = function(evt) {
clickHandler: function pm_clickHandler(evt) {
var callback = null;
if (evt.target === yes && yes.callback) {
callback = yes.callback;
} else if (evt.target === no && no.callback) {
callback = no.callback;
} else if (evt.target === moreInfoLink) {
moreInfoBox.classList.toggle('hidden');
if (evt.target === this.yes && this.yes.callback) {
callback = this.yes.callback;
} else if (evt.target === this.no && this.no.callback) {
callback = this.no.callback;
} else if (evt.target === this.moreInfoLink) {
this.moreInfoBox.classList.toggle('hidden');
return;
}
hidePermissionPrompt();
this.hidePermissionPrompt();

// Call the appropriate callback, if it is defined.
if (callback)
window.setTimeout(callback, 0);
this.showNextPendingRequest();
},

showNextPendingRequest();
};

var requestPermission = function(msg, moreInfoText,
requestPermission: function pm_requestPermission(msg, moreInfoText,
yescallback, nocallback) {
var id = nextRequestID;
nextRequestID = (nextRequestID + 1) % 1000000;
var id = this.nextRequestID;
this.nextRequestID = (this.nextRequestID + 1) % 1000000;

if (currentRequestId != undefined) {
if (this.currentRequestId != undefined) {
// There is already a permission request being shown, queue this one.
pending.push({
this.pending.push({
id: id,
message: msg,
moreInfoText: moreInfoText,
Expand All @@ -165,78 +193,65 @@ var PermissionManager = (function() {
});
return id;
}

showPermissionPrompt(id, msg, moreInfoText, yescallback, nocallback);
this.showPermissionPrompt(id, msg, moreInfoText,
yescallback, nocallback).bind(this);

return id;
};
},

var showPermissionPrompt = function(id, msg, moreInfoText,
showPermissionPrompt: function pm_showPermissionPrompt(id, msg, moreInfoText,
yescallback, nocallback) {
// Put the message in the dialog.
// Note plain text since this may include text from
// untrusted app manifests, for example.
message.textContent = msg;

this.message.textContent = msg;
if (moreInfoText) {
// Show the "More info… " link.
moreInfo.classList.remove('hidden');
moreInfoLink.addEventListener('click', clickHandler);
moreInfoBox.textContent = moreInfoText;
this.moreInfo.classList.remove('hidden');
this.moreInfoLink.addEventListener('click',
this.clickHandler.bind(this));
this.moreInfoBox.textContent = moreInfoText;
}

currentRequestId = id;

this.currentRequestId = id;
// Make the screen visible
overlay.classList.add('visible');
this.overlay.classList.add('visible');

// Set event listeners for the yes and no buttons
yes.addEventListener('click', clickHandler);
yes.callback = yescallback;
this.yes.addEventListener('click', this.clickHandler.bind(this));
this.yes.callback = yescallback;

no.addEventListener('click', clickHandler);
no.callback = nocallback;
};
this.no.addEventListener('click', this.clickHandler.bind(this));
this.no.callback = nocallback;
},

// Cancels a request with a specfied id. Request can either be
// currently showing, or pending. If there are further pending requests,
// the next is shown.
var cancelRequest = function(id) {
if (currentRequestId === id) {
cancelRequest: function pm_cancelRequest(id) {
if (this.currentRequestId === id) {
// Request is currently being displayed. Hide the permission prompt,
// and show the next request, if we have any.
hidePermissionPrompt();
showNextPendingRequest();
this.hidePermissionPrompt();
this.showNextPendingRequest();
} else {
// The request is currently not being displayed. Search through the
// list of pending requests, and remove it from the list if present.
for (var i = 0; i < pending.length; i++) {
if (pending[i].id === id) {
pending.splice(i, 1);
for (var i = 0; i < this.pending.length; i++) {
if (this.pending[i].id === id) {
this.pending.splice(i, 1);
break;
}
}
}
};

rememberSection.addEventListener('click', function onLabelClick() {
remember.checked = !remember.checked;
});
},

function discardPermissionRequest() {
if (currentRequestId == undefined)
discardPermissionRequest: function pm_discardPermissionRequest() {
if (this.currentRequestId == undefined)
return;
this.dispatchResponse(this.currentRequestId, 'permission-deny', false);
this.hidePermissionPrompt();
}

dispatchResponse(currentRequestId, 'permission-deny', false);
hidePermissionPrompt();
};

// On home/holdhome pressed, discard permission request.
// XXX: We should make permission dialog be embededd in appWindow
// Gaia bug is https://bugzilla.mozilla.org/show_bug.cgi?id=853711
// Gecko bug is https://bugzilla.mozilla.org/show_bug.cgi?id=852013
window.addEventListener('home', discardPermissionRequest);
window.addEventListener('holdhome', discardPermissionRequest);

}());
};

PermissionManager.init();
Loading

0 comments on commit cf6272f

Please sign in to comment.