mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 853356 - gUM video permisson prompt. r=fabrice, felipc, wjohnston, mrbkap, jimm, jesup, khuey, jsmith
This commit is contained in:
parent
5c683a0aa1
commit
3853c6783a
@ -5,7 +5,7 @@
|
||||
"use strict"
|
||||
|
||||
function debug(str) {
|
||||
//dump("-*- ContentPermissionPrompt: " + s + "\n");
|
||||
//dump("-*- ContentPermissionPrompt: " + str + "\n");
|
||||
}
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
@ -13,11 +13,14 @@ const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
|
||||
const PROMPT_FOR_UNKNOWN = ["geolocation", "desktop-notification",
|
||||
"audio-capture"];
|
||||
const PROMPT_FOR_UNKNOWN = ["audio-capture",
|
||||
"desktop-notification",
|
||||
"geolocation",
|
||||
"video-capture"];
|
||||
// Due to privary issue, permission requests like GetUserMedia should prompt
|
||||
// every time instead of providing session persistence.
|
||||
const PERMISSION_NO_SESSION = ["audio-capture"];
|
||||
const PERMISSION_NO_SESSION = ["audio-capture", "video-capture"];
|
||||
const ALLOW_MULTIPLE_REQUESTS = ["audio-capture", "video-capture"];
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
@ -41,7 +44,21 @@ XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"@mozilla.org/telephony/audiomanager;1",
|
||||
"nsIAudioManager");
|
||||
|
||||
function rememberPermission(aPermission, aPrincipal, aSession)
|
||||
/**
|
||||
* aTypesInfo is an array of {permission, access, action, deny} which keeps
|
||||
* the information of each permission. This arrary is initialized in
|
||||
* ContentPermissionPrompt.prompt and used among functions.
|
||||
*
|
||||
* aTypesInfo[].permission : permission name
|
||||
* aTypesInfo[].access : permission name + request.access
|
||||
* aTypesInfo[].action : the default action of this permission
|
||||
* aTypesInfo[].deny : true if security manager denied this app's origin
|
||||
* principal.
|
||||
* Note:
|
||||
* aTypesInfo[].permission will be sent to prompt only when
|
||||
* aTypesInfo[].action is PROMPT_ACTION and aTypesInfo[].deny is false.
|
||||
*/
|
||||
function rememberPermission(aTypesInfo, aPrincipal, aSession)
|
||||
{
|
||||
function convertPermToAllow(aPerm, aPrincipal)
|
||||
{
|
||||
@ -49,12 +66,13 @@ function rememberPermission(aPermission, aPrincipal, aSession)
|
||||
permissionManager.testExactPermissionFromPrincipal(aPrincipal, aPerm);
|
||||
if (type == Ci.nsIPermissionManager.PROMPT_ACTION ||
|
||||
(type == Ci.nsIPermissionManager.UNKNOWN_ACTION &&
|
||||
PROMPT_FOR_UNKNOWN.indexOf(aPermission) >= 0)) {
|
||||
PROMPT_FOR_UNKNOWN.indexOf(aPerm) >= 0)) {
|
||||
debug("add " + aPerm + " to permission manager with ALLOW_ACTION");
|
||||
if (!aSession) {
|
||||
permissionManager.addFromPrincipal(aPrincipal,
|
||||
aPerm,
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
} else if (PERMISSION_NO_SESSION.indexOf(aPermission) < 0) {
|
||||
} else if (PERMISSION_NO_SESSION.indexOf(aPerm) < 0) {
|
||||
permissionManager.addFromPrincipal(aPrincipal,
|
||||
aPerm,
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
@ -63,14 +81,18 @@ function rememberPermission(aPermission, aPrincipal, aSession)
|
||||
}
|
||||
}
|
||||
|
||||
// Expand the permission to see if we have multiple access properties to convert
|
||||
let access = PermissionsTable[aPermission].access;
|
||||
if (access) {
|
||||
for (let idx in access) {
|
||||
convertPermToAllow(aPermission + "-" + access[idx], aPrincipal);
|
||||
for (let i in aTypesInfo) {
|
||||
// Expand the permission to see if we have multiple access properties
|
||||
// to convert
|
||||
let perm = aTypesInfo[i].permission;
|
||||
let access = PermissionsTable[perm].access;
|
||||
if (access) {
|
||||
for (let idx in access) {
|
||||
convertPermToAllow(perm + "-" + access[idx], aPrincipal);
|
||||
}
|
||||
} else {
|
||||
convertPermToAllow(perm, aPrincipal);
|
||||
}
|
||||
} else {
|
||||
convertPermToAllow(aPermission, aPrincipal);
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,23 +100,66 @@ function ContentPermissionPrompt() {}
|
||||
|
||||
ContentPermissionPrompt.prototype = {
|
||||
|
||||
handleExistingPermission: function handleExistingPermission(request) {
|
||||
let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
|
||||
request.type;
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, access);
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
handleExistingPermission: function handleExistingPermission(request,
|
||||
typesInfo) {
|
||||
typesInfo.forEach(function(type) {
|
||||
type.action =
|
||||
Services.perms.testExactPermissionFromPrincipal(request.principal,
|
||||
type.access);
|
||||
if (type.action == Ci.nsIPermissionManager.UNKNOWN_ACTION &&
|
||||
PROMPT_FOR_UNKNOWN.indexOf(type.access) >= 0) {
|
||||
type.action = Ci.nsIPermissionManager.PROMPT_ACTION;
|
||||
}
|
||||
});
|
||||
|
||||
// If all permissions are allowed already, call allow() without prompting.
|
||||
let checkAllowPermission = function(type) {
|
||||
if (type.action == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (typesInfo.every(checkAllowPermission)) {
|
||||
debug("all permission requests are allowed");
|
||||
request.allow();
|
||||
return true;
|
||||
}
|
||||
if (result == Ci.nsIPermissionManager.DENY_ACTION ||
|
||||
result == Ci.nsIPermissionManager.UNKNOWN_ACTION && PROMPT_FOR_UNKNOWN.indexOf(access) < 0) {
|
||||
|
||||
// If all permissions are DENY_ACTION or UNKNOWN_ACTION, call cancel()
|
||||
// without prompting.
|
||||
let checkDenyPermission = function(type) {
|
||||
if (type.action == Ci.nsIPermissionManager.DENY_ACTION ||
|
||||
type.action == Ci.nsIPermissionManager.UNKNOWN_ACTION) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (typesInfo.every(checkDenyPermission)) {
|
||||
debug("all permission requests are denied");
|
||||
request.cancel();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
handledByApp: function handledByApp(request) {
|
||||
// multiple requests should be audio and video
|
||||
checkMultipleRequest: function checkMultipleRequest(typesInfo) {
|
||||
if (typesInfo.length == 1) {
|
||||
return true;
|
||||
} else if (typesInfo.length > 1) {
|
||||
let checkIfAllowMultiRequest = function(type) {
|
||||
return (ALLOW_MULTIPLE_REQUESTS.indexOf(type.access) !== -1);
|
||||
}
|
||||
if (typesInfo.every(checkIfAllowMultiRequest)) {
|
||||
debug("legal multiple requests");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
handledByApp: function handledByApp(request, typesInfo) {
|
||||
if (request.principal.appId == Ci.nsIScriptSecurityManager.NO_APP_ID ||
|
||||
request.principal.appId == Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID) {
|
||||
// This should not really happen
|
||||
@ -106,49 +171,94 @@ ContentPermissionPrompt.prototype = {
|
||||
.getService(Ci.nsIAppsService);
|
||||
let app = appsService.getAppByLocalId(request.principal.appId);
|
||||
|
||||
let url = Services.io.newURI(app.origin, null, null);
|
||||
let principal = secMan.getAppCodebasePrincipal(url, request.principal.appId,
|
||||
/*mozbrowser*/false);
|
||||
let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
|
||||
request.type;
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(principal, access);
|
||||
// Check each permission if it's denied by permission manager with app's
|
||||
// URL.
|
||||
let notDenyAppPrincipal = function(type) {
|
||||
let url = Services.io.newURI(app.origin, null, null);
|
||||
let principal = secMan.getAppCodebasePrincipal(url,
|
||||
request.principal.appId,
|
||||
/*mozbrowser*/false);
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(principal,
|
||||
type.access);
|
||||
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION ||
|
||||
result == Ci.nsIPermissionManager.PROMPT_ACTION) {
|
||||
return false;
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION ||
|
||||
result == Ci.nsIPermissionManager.PROMPT_ACTION) {
|
||||
type.deny = false;
|
||||
}
|
||||
return !type.deny;
|
||||
}
|
||||
if (typesInfo.filter(notDenyAppPrincipal).length === 0) {
|
||||
request.cancel();
|
||||
return true;
|
||||
}
|
||||
|
||||
request.cancel();
|
||||
return true;
|
||||
return false;
|
||||
},
|
||||
|
||||
handledByPermissionType: function handledByPermissionType(request) {
|
||||
return permissionSpecificChecker.hasOwnProperty(request.type)
|
||||
? permissionSpecificChecker[request.type](request)
|
||||
: false;
|
||||
handledByPermissionType: function handledByPermissionType(request, typesInfo) {
|
||||
for (let i in typesInfo) {
|
||||
if (permissionSpecificChecker.hasOwnProperty(typesInfo[i].permission) &&
|
||||
permissionSpecificChecker[typesInfo[i].permission](request)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
_id: 0,
|
||||
prompt: function(request) {
|
||||
if (secMan.isSystemPrincipal(request.principal)) {
|
||||
request.allow();
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.handledByApp(request) ||
|
||||
this.handledByPermissionType(request)) {
|
||||
// Initialize the typesInfo and set the default value.
|
||||
let typesInfo = [];
|
||||
let perms = request.types.QueryInterface(Ci.nsIArray);
|
||||
for (let idx = 0; idx < perms.length; idx++) {
|
||||
let perm = perms.queryElementAt(idx, Ci.nsIContentPermissionType);
|
||||
let tmp = {
|
||||
permission: perm.type,
|
||||
access: (perm.access && perm.access !== "unused") ?
|
||||
perm.type + "-" + perm.access : perm.type,
|
||||
deny: true,
|
||||
action: Ci.nsIPermissionManager.UNKNOWN_ACTION
|
||||
};
|
||||
typesInfo.push(tmp);
|
||||
}
|
||||
if (typesInfo.length == 0) {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
if(!this.checkMultipleRequest(typesInfo)) {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.handledByApp(request, typesInfo) ||
|
||||
this.handledByPermissionType(request, typesInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// returns true if the request was handled
|
||||
if (this.handleExistingPermission(request))
|
||||
if (this.handleExistingPermission(request, typesInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// prompt PROMPT_ACTION request only.
|
||||
typesInfo.forEach(function(aType, aIndex) {
|
||||
if (aType.action != Ci.nsIPermissionManager.PROMPT_ACTION || aType.deny) {
|
||||
typesInfo.splice(aIndex);
|
||||
}
|
||||
});
|
||||
|
||||
let frame = request.element;
|
||||
let requestId = this._id++;
|
||||
|
||||
if (!frame) {
|
||||
this.delegatePrompt(request, requestId);
|
||||
this.delegatePrompt(request, requestId, typesInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -163,7 +273,7 @@ ContentPermissionPrompt.prototype = {
|
||||
if (evt.detail.visible === true)
|
||||
return;
|
||||
|
||||
self.cancelPrompt(request, requestId);
|
||||
self.cancelPrompt(request, requestId, typesInfo);
|
||||
cancelRequest();
|
||||
}
|
||||
|
||||
@ -180,7 +290,7 @@ ContentPermissionPrompt.prototype = {
|
||||
// away but the request is still here.
|
||||
frame.addEventListener("mozbrowservisibilitychange", onVisibilityChange);
|
||||
|
||||
self.delegatePrompt(request, requestId, function onCallback() {
|
||||
self.delegatePrompt(request, requestId, typesInfo, function onCallback() {
|
||||
frame.removeEventListener("mozbrowservisibilitychange", onVisibilityChange);
|
||||
});
|
||||
};
|
||||
@ -191,22 +301,17 @@ ContentPermissionPrompt.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
cancelPrompt: function(request, requestId) {
|
||||
this.sendToBrowserWindow("cancel-permission-prompt", request, requestId);
|
||||
cancelPrompt: function(request, requestId, typesInfo) {
|
||||
this.sendToBrowserWindow("cancel-permission-prompt", request, requestId,
|
||||
typesInfo);
|
||||
},
|
||||
|
||||
delegatePrompt: function(request, requestId, callback) {
|
||||
let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
|
||||
request.type;
|
||||
let principal = request.principal;
|
||||
delegatePrompt: function(request, requestId, typesInfo, callback) {
|
||||
|
||||
this._permission = access;
|
||||
this._uri = principal.URI.spec;
|
||||
this._origin = principal.origin;
|
||||
|
||||
this.sendToBrowserWindow("permission-prompt", request, requestId, function(type, remember) {
|
||||
this.sendToBrowserWindow("permission-prompt", request, requestId, typesInfo,
|
||||
function(type, remember) {
|
||||
if (type == "permission-allow") {
|
||||
rememberPermission(request.type, principal, !remember);
|
||||
rememberPermission(typesInfo, request.principal, !remember);
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
@ -214,14 +319,20 @@ ContentPermissionPrompt.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
if (remember) {
|
||||
Services.perms.addFromPrincipal(principal, access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION);
|
||||
} else {
|
||||
Services.perms.addFromPrincipal(principal, access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION,
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION, 0);
|
||||
let addDenyPermission = function(type) {
|
||||
debug("add " + type.permission +
|
||||
" to permission manager with DENY_ACTION");
|
||||
if (remember) {
|
||||
Services.perms.addFromPrincipal(request.principal, type.access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION);
|
||||
} else if (PERMISSION_NO_SESSION.indexOf(aPerm) < 0) {
|
||||
Services.perms.addFromPrincipal(request.principal, type.access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION,
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION,
|
||||
0);
|
||||
}
|
||||
}
|
||||
typesInfo.forEach(addDenyPermission);
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
@ -230,7 +341,7 @@ ContentPermissionPrompt.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
sendToBrowserWindow: function(type, request, requestId, callback) {
|
||||
sendToBrowserWindow: function(type, request, requestId, typesInfo, callback) {
|
||||
let browser = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let content = browser.getContentWindow();
|
||||
if (!content)
|
||||
@ -253,10 +364,15 @@ ContentPermissionPrompt.prototype = {
|
||||
principal.appStatus == Ci.nsIPrincipal.APP_STATUS_CERTIFIED)
|
||||
? true
|
||||
: request.remember;
|
||||
let permissions = {};
|
||||
for (let i in typesInfo) {
|
||||
debug("prompt " + typesInfo[i].permission);
|
||||
permissions[typesInfo[i].permission] = [];
|
||||
}
|
||||
|
||||
let details = {
|
||||
type: type,
|
||||
permission: request.type,
|
||||
permissions: permissions,
|
||||
id: requestId,
|
||||
origin: principal.origin,
|
||||
isApp: isApp,
|
||||
@ -289,6 +405,5 @@ ContentPermissionPrompt.prototype = {
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
//module initialization
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentPermissionPrompt]);
|
||||
|
@ -1902,7 +1902,16 @@ ContentPermissionPrompt.prototype = {
|
||||
popupNotificationActions[0] : null;
|
||||
var secondaryActions = popupNotificationActions.splice(1);
|
||||
|
||||
if (aRequest.type == "pointerLock") {
|
||||
// Only allow exactly one permission rquest here.
|
||||
let types = aRequest.types.QueryInterface(Ci.nsIArray);
|
||||
if (types.length != 1) {
|
||||
aRequest.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
let perm = types.queryElementAt(0, Ci.nsIContentPermissionType);
|
||||
|
||||
if (perm.type == "pointerLock") {
|
||||
// If there's no mainAction, this is the autoAllow warning prompt.
|
||||
let autoAllow = !mainAction;
|
||||
aOptions = {
|
||||
@ -1920,7 +1929,7 @@ ContentPermissionPrompt.prototype = {
|
||||
|
||||
var popup = chromeWin.PopupNotifications.show(browser, aNotificationId, aMessage, aAnchorId,
|
||||
mainAction, secondaryActions, aOptions);
|
||||
if (aRequest.type == "pointerLock") {
|
||||
if (perm.type == "pointerLock") {
|
||||
// pointerLock is automatically allowed in fullscreen mode (and revoked
|
||||
// upon exit), so if the page enters fullscreen mode after requesting
|
||||
// pointerLock (but before the user has granted permission), we should
|
||||
@ -2058,13 +2067,21 @@ ContentPermissionPrompt.prototype = {
|
||||
|
||||
prompt: function CPP_prompt(request) {
|
||||
|
||||
// Only allow exactly one permission rquest here.
|
||||
let types = request.types.QueryInterface(Ci.nsIArray);
|
||||
if (types.length != 1) {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
let perm = types.queryElementAt(0, Ci.nsIContentPermissionType);
|
||||
|
||||
const kFeatureKeys = { "geolocation" : "geo",
|
||||
"desktop-notification" : "desktop-notification",
|
||||
"pointerLock" : "pointerLock",
|
||||
};
|
||||
|
||||
// Make sure that we support the request.
|
||||
if (!(request.type in kFeatureKeys)) {
|
||||
if (!(perm.type in kFeatureKeys)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2076,7 +2093,7 @@ ContentPermissionPrompt.prototype = {
|
||||
return;
|
||||
|
||||
var autoAllow = false;
|
||||
var permissionKey = kFeatureKeys[request.type];
|
||||
var permissionKey = kFeatureKeys[perm.type];
|
||||
var result = Services.perms.testExactPermissionFromPrincipal(requestingPrincipal, permissionKey);
|
||||
|
||||
if (result == Ci.nsIPermissionManager.DENY_ACTION) {
|
||||
@ -2087,7 +2104,7 @@ ContentPermissionPrompt.prototype = {
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
autoAllow = true;
|
||||
// For pointerLock, we still want to show a warning prompt.
|
||||
if (request.type != "pointerLock") {
|
||||
if (perm.type != "pointerLock") {
|
||||
request.allow();
|
||||
return;
|
||||
}
|
||||
@ -2101,7 +2118,7 @@ ContentPermissionPrompt.prototype = {
|
||||
return;
|
||||
|
||||
// Show the prompt.
|
||||
switch (request.type) {
|
||||
switch (perm.type) {
|
||||
case "geolocation":
|
||||
this._promptGeo(request);
|
||||
break;
|
||||
|
@ -44,6 +44,13 @@ let IndexedDB = {
|
||||
}
|
||||
|
||||
let prompt = Cc["@mozilla.org/content-permission/prompt;1"].createInstance(Ci.nsIContentPermissionPrompt);
|
||||
let types = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
|
||||
let promptType = {
|
||||
type: type,
|
||||
access: "unused",
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionType])
|
||||
};
|
||||
types.appendElement(promptType, false);
|
||||
|
||||
// If the user waits a long time before responding, we default to UNKNOWN_ACTION.
|
||||
let timeoutId = setTimeout(function() {
|
||||
@ -60,7 +67,7 @@ let IndexedDB = {
|
||||
}
|
||||
|
||||
prompt.prompt({
|
||||
type: type,
|
||||
types: types,
|
||||
uri: Services.io.newURI(payload.location, null, null),
|
||||
window: null,
|
||||
element: aMessage.target,
|
||||
|
@ -56,8 +56,8 @@ ContentPermissionPrompt.prototype = {
|
||||
return chromeWin.Browser.getNotificationBox(request.element);
|
||||
},
|
||||
|
||||
handleExistingPermission: function handleExistingPermission(request) {
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, request.type);
|
||||
handleExistingPermission: function handleExistingPermission(request, type) {
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, type);
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
request.allow();
|
||||
return true;
|
||||
@ -70,20 +70,28 @@ ContentPermissionPrompt.prototype = {
|
||||
},
|
||||
|
||||
prompt: function(request) {
|
||||
// Only allow exactly one permission rquest here.
|
||||
let types = request.types.QueryInterface(Ci.nsIArray);
|
||||
if (types.length != 1) {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
let perm = types.queryElementAt(0, Ci.nsIContentPermissionType);
|
||||
|
||||
// returns true if the request was handled
|
||||
if (this.handleExistingPermission(request))
|
||||
if (this.handleExistingPermission(request, perm.type))
|
||||
return;
|
||||
|
||||
let pm = Services.perms;
|
||||
let notificationBox = this.getNotificationBoxForRequest(request);
|
||||
let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
|
||||
|
||||
let notification = notificationBox.getNotificationWithValue(request.type);
|
||||
let notification = notificationBox.getNotificationWithValue(perm.type);
|
||||
if (notification)
|
||||
return;
|
||||
|
||||
let entityName = kEntities[request.type];
|
||||
let icon = kIcons[request.type] || "";
|
||||
let entityName = kEntities[perm.type];
|
||||
let icon = kIcons[perm.type] || "";
|
||||
|
||||
let buttons = [{
|
||||
label: browserBundle.GetStringFromName(entityName + ".allow"),
|
||||
@ -96,7 +104,7 @@ ContentPermissionPrompt.prototype = {
|
||||
label: browserBundle.GetStringFromName("contentPermissions.alwaysForSite"),
|
||||
accessKey: "",
|
||||
callback: function(notification) {
|
||||
Services.perms.addFromPrincipal(request.principal, request.type, Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
request.allow();
|
||||
}
|
||||
},
|
||||
@ -104,7 +112,7 @@ ContentPermissionPrompt.prototype = {
|
||||
label: browserBundle.GetStringFromName("contentPermissions.neverForSite"),
|
||||
accessKey: "",
|
||||
callback: function(notification) {
|
||||
Services.perms.addFromPrincipal(request.principal, request.type, Ci.nsIPermissionManager.DENY_ACTION);
|
||||
Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.DENY_ACTION);
|
||||
request.cancel();
|
||||
}
|
||||
}];
|
||||
@ -112,12 +120,12 @@ ContentPermissionPrompt.prototype = {
|
||||
let message = browserBundle.formatStringFromName(entityName + ".wantsTo",
|
||||
[request.principal.URI.host], 1);
|
||||
let newBar = notificationBox.appendNotification(message,
|
||||
request.type,
|
||||
perm.type,
|
||||
icon,
|
||||
notificationBox.PRIORITY_WARNING_MEDIUM,
|
||||
buttons);
|
||||
|
||||
if (request.type == "geolocation") {
|
||||
if (perm.type == "geolocation") {
|
||||
// Add the "learn more" link.
|
||||
let link = newBar.ownerDocument.createElement("label");
|
||||
link.setAttribute("value", browserBundle.GetStringFromName("geolocation.learnMore"));
|
||||
|
@ -217,6 +217,8 @@
|
||||
#include "mozilla/dom/XPathEvaluator.h"
|
||||
#include "nsIDocumentEncoder.h"
|
||||
#include "nsIStructuredCloneContainer.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsContentPermissionHelper.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -10771,17 +10773,11 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsPointerLockPermissionRequest,
|
||||
nsIContentPermissionRequest)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPointerLockPermissionRequest::GetType(nsACString& aType)
|
||||
nsPointerLockPermissionRequest::GetTypes(nsIArray** aTypes)
|
||||
{
|
||||
aType = "pointerLock";
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPointerLockPermissionRequest::GetAccess(nsACString& aAccess)
|
||||
{
|
||||
aAccess = "unused";
|
||||
return NS_OK;
|
||||
return CreatePermissionArray(NS_LITERAL_CSTRING("pointerLock"),
|
||||
NS_LITERAL_CSTRING("unused"),
|
||||
aTypes);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -5,6 +5,7 @@
|
||||
#ifndef MEDIAENGINE_H_
|
||||
#define MEDIAENGINE_H_
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsIDOMFile.h"
|
||||
#include "DOMMediaStream.h"
|
||||
#include "MediaStreamGraph.h"
|
||||
@ -35,7 +36,7 @@ enum {
|
||||
kAudioTrack = 2
|
||||
};
|
||||
|
||||
class MediaEngine
|
||||
class MediaEngine : public RefCounted<MediaEngine>
|
||||
{
|
||||
public:
|
||||
virtual ~MediaEngine() {}
|
||||
|
@ -321,6 +321,11 @@ this.PermissionsTable = { geolocation: {
|
||||
privileged: DENY_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
},
|
||||
"video-capture": {
|
||||
app: PROMPT_ACTION,
|
||||
privileged: PROMPT_ACTION,
|
||||
certified: PROMPT_ACTION
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -6,20 +6,156 @@
|
||||
#include "GonkPermission.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#endif // MOZ_WIDGET_GONK
|
||||
#include "nsContentPermissionHelper.h"
|
||||
#include "nsIContentPermissionPrompt.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/PContentPermission.h"
|
||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||
#include "mozilla/dom/PContentPermissionRequestParent.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsContentPermissionHelper.h"
|
||||
|
||||
using mozilla::unused; // <snicker>
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ContentPermissionRequestParent : public PContentPermissionRequestParent
|
||||
{
|
||||
public:
|
||||
ContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
|
||||
Element* element,
|
||||
const IPC::Principal& principal);
|
||||
virtual ~ContentPermissionRequestParent();
|
||||
|
||||
bool IsBeingDestroyed();
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<Element> mElement;
|
||||
nsCOMPtr<nsContentPermissionRequestProxy> mProxy;
|
||||
nsTArray<PermissionRequest> mRequests;
|
||||
|
||||
private:
|
||||
virtual bool Recvprompt();
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
};
|
||||
|
||||
ContentPermissionRequestParent::ContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
|
||||
Element* aElement,
|
||||
const IPC::Principal& aPrincipal)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ContentPermissionRequestParent);
|
||||
|
||||
mPrincipal = aPrincipal;
|
||||
mElement = aElement;
|
||||
mRequests = aRequests;
|
||||
}
|
||||
|
||||
ContentPermissionRequestParent::~ContentPermissionRequestParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(ContentPermissionRequestParent);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentPermissionRequestParent::Recvprompt()
|
||||
{
|
||||
mProxy = new nsContentPermissionRequestProxy();
|
||||
NS_ASSERTION(mProxy, "Alloc of request proxy failed");
|
||||
if (NS_FAILED(mProxy->Init(mRequests, this))) {
|
||||
mProxy->Cancel();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ContentPermissionRequestParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (mProxy) {
|
||||
mProxy->OnParentDestroyed();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ContentPermissionRequestParent::IsBeingDestroyed()
|
||||
{
|
||||
// When TabParent::Destroy() is called, we are being destroyed. It's unsafe
|
||||
// to send out any message now.
|
||||
TabParent* tabParent = static_cast<TabParent*>(Manager());
|
||||
return tabParent->IsDestroyed();
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(ContentPermissionType, nsIContentPermissionType)
|
||||
|
||||
ContentPermissionType::ContentPermissionType(const nsACString& aType,
|
||||
const nsACString& aAccess)
|
||||
{
|
||||
mType = aType;
|
||||
mAccess = aAccess;
|
||||
}
|
||||
|
||||
ContentPermissionType::~ContentPermissionType()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContentPermissionType::GetType(nsACString& aType)
|
||||
{
|
||||
aType = mType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContentPermissionType::GetAccess(nsACString& aAccess)
|
||||
{
|
||||
aAccess = mAccess;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ConvertPermissionRequestToArray(nsTArray<PermissionRequest>& aSrcArray,
|
||||
nsIMutableArray* aDesArray)
|
||||
{
|
||||
uint32_t len = aSrcArray.Length();
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
nsRefPtr<ContentPermissionType> cpt =
|
||||
new ContentPermissionType(aSrcArray[i].type(), aSrcArray[i].access());
|
||||
aDesArray->AppendElement(cpt, false);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CreatePermissionArray(const nsACString& aType,
|
||||
const nsACString& aAccess,
|
||||
nsIArray** aTypesArray)
|
||||
{
|
||||
nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
nsRefPtr<ContentPermissionType> permType = new ContentPermissionType(aType,
|
||||
aAccess);
|
||||
types->AppendElement(permType, false);
|
||||
types.forget(aTypesArray);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PContentPermissionRequestParent*
|
||||
CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
|
||||
Element* element,
|
||||
const IPC::Principal& principal)
|
||||
{
|
||||
return new ContentPermissionRequestParent(aRequests, element, principal);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
nsContentPermissionRequestProxy::nsContentPermissionRequestProxy()
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsContentPermissionRequestProxy);
|
||||
@ -31,14 +167,12 @@ nsContentPermissionRequestProxy::~nsContentPermissionRequestProxy()
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsContentPermissionRequestProxy::Init(const nsACString & type,
|
||||
const nsACString & access,
|
||||
nsContentPermissionRequestProxy::Init(const nsTArray<PermissionRequest>& requests,
|
||||
ContentPermissionRequestParent* parent)
|
||||
{
|
||||
NS_ASSERTION(parent, "null parent");
|
||||
mParent = parent;
|
||||
mType = type;
|
||||
mAccess = access;
|
||||
mPermissionRequests = requests;
|
||||
|
||||
nsCOMPtr<nsIContentPermissionPrompt> prompt = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
|
||||
if (!prompt) {
|
||||
@ -58,17 +192,14 @@ nsContentPermissionRequestProxy::OnParentDestroyed()
|
||||
NS_IMPL_ISUPPORTS1(nsContentPermissionRequestProxy, nsIContentPermissionRequest)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsContentPermissionRequestProxy::GetType(nsACString & aType)
|
||||
nsContentPermissionRequestProxy::GetTypes(nsIArray** aTypes)
|
||||
{
|
||||
aType = mType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsContentPermissionRequestProxy::GetAccess(nsACString & aAccess)
|
||||
{
|
||||
aAccess = mAccess;
|
||||
return NS_OK;
|
||||
nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
if (ConvertPermissionRequestToArray(mPermissionRequests, types)) {
|
||||
types.forget(aTypes);
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -136,10 +267,18 @@ nsContentPermissionRequestProxy::Allow()
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (mType.Equals("audio-capture")) {
|
||||
GonkPermissionService::GetInstance()->addGrantInfo(
|
||||
"android.permission.RECORD_AUDIO",
|
||||
static_cast<TabParent*>(mParent->Manager())->Manager()->Pid());
|
||||
uint32_t len = mPermissionRequests.Length();
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
if (mPermissionRequests[i].type().Equals("audio-capture")) {
|
||||
GonkPermissionService::GetInstance()->addGrantInfo(
|
||||
"android.permission.RECORD_AUDIO",
|
||||
static_cast<TabParent*>(mParent->Manager())->Manager()->Pid());
|
||||
}
|
||||
if (mPermissionRequests[i].type().Equals("video-capture")) {
|
||||
GonkPermissionService::GetInstance()->addGrantInfo(
|
||||
"android.permission.CAMERA",
|
||||
static_cast<TabParent*>(mParent->Manager())->Manager()->Pid());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -147,55 +286,3 @@ nsContentPermissionRequestProxy::Allow()
|
||||
mParent = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
ContentPermissionRequestParent::ContentPermissionRequestParent(const nsACString& aType,
|
||||
const nsACString& aAccess,
|
||||
Element* aElement,
|
||||
const IPC::Principal& aPrincipal)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ContentPermissionRequestParent);
|
||||
|
||||
mPrincipal = aPrincipal;
|
||||
mElement = aElement;
|
||||
mType = aType;
|
||||
mAccess = aAccess;
|
||||
}
|
||||
|
||||
ContentPermissionRequestParent::~ContentPermissionRequestParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(ContentPermissionRequestParent);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentPermissionRequestParent::Recvprompt()
|
||||
{
|
||||
mProxy = new nsContentPermissionRequestProxy();
|
||||
NS_ASSERTION(mProxy, "Alloc of request proxy failed");
|
||||
if (NS_FAILED(mProxy->Init(mType, mAccess, this))) {
|
||||
mProxy->Cancel();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ContentPermissionRequestParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (mProxy) {
|
||||
mProxy->OnParentDestroyed();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ContentPermissionRequestParent::IsBeingDestroyed()
|
||||
{
|
||||
// When TabParent::Destroy() is called, we are being destroyed. It's unsafe
|
||||
// to send out any message now.
|
||||
TabParent* tabParent = static_cast<TabParent*>(Manager());
|
||||
return tabParent->IsDestroyed();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -6,60 +6,75 @@
|
||||
#define nsContentPermissionHelper_h
|
||||
|
||||
#include "nsIContentPermissionPrompt.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||
#include "mozilla/dom/PContentPermissionRequestParent.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIMutableArray.h"
|
||||
|
||||
class nsContentPermissionRequestProxy;
|
||||
|
||||
// Forward declare IPC::Principal here which is defined in
|
||||
// PermissionMessageUtils.h. Include this file will transitively includes
|
||||
// "windows.h" and it defines
|
||||
// #define CreateEvent CreateEventW
|
||||
// #define LoadImage LoadImageW
|
||||
// That will mess up windows build.
|
||||
namespace IPC {
|
||||
class Principal;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class Element;
|
||||
class PermissionRequest;
|
||||
class ContentPermissionRequestParent;
|
||||
class PContentPermissionRequestParent;
|
||||
|
||||
class ContentPermissionRequestParent : public PContentPermissionRequestParent
|
||||
class ContentPermissionType : public nsIContentPermissionType
|
||||
{
|
||||
public:
|
||||
ContentPermissionRequestParent(const nsACString& type,
|
||||
const nsACString& access,
|
||||
Element* element,
|
||||
const IPC::Principal& principal);
|
||||
virtual ~ContentPermissionRequestParent();
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICONTENTPERMISSIONTYPE
|
||||
|
||||
bool IsBeingDestroyed();
|
||||
ContentPermissionType(const nsACString& aType, const nsACString& aAccess);
|
||||
virtual ~ContentPermissionType();
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<Element> mElement;
|
||||
nsCOMPtr<nsContentPermissionRequestProxy> mProxy;
|
||||
protected:
|
||||
nsCString mType;
|
||||
nsCString mAccess;
|
||||
|
||||
private:
|
||||
virtual bool Recvprompt();
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
};
|
||||
|
||||
uint32_t ConvertPermissionRequestToArray(nsTArray<PermissionRequest>& aSrcArray,
|
||||
nsIMutableArray* aDesArray);
|
||||
|
||||
nsresult CreatePermissionArray(const nsACString& aType,
|
||||
const nsACString& aAccess,
|
||||
nsIArray** aTypesArray);
|
||||
|
||||
PContentPermissionRequestParent*
|
||||
CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
|
||||
Element* element,
|
||||
const IPC::Principal& principal);
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsContentPermissionRequestProxy : public nsIContentPermissionRequest
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICONTENTPERMISSIONREQUEST
|
||||
|
||||
nsContentPermissionRequestProxy();
|
||||
virtual ~nsContentPermissionRequestProxy();
|
||||
|
||||
nsresult Init(const nsACString& type, const nsACString& access, mozilla::dom::ContentPermissionRequestParent* parent);
|
||||
nsresult Init(const nsTArray<mozilla::dom::PermissionRequest>& requests,
|
||||
mozilla::dom::ContentPermissionRequestParent* parent);
|
||||
void OnParentDestroyed();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICONTENTPERMISSIONREQUEST
|
||||
|
||||
private:
|
||||
// Non-owning pointer to the ContentPermissionRequestParent object which owns this proxy.
|
||||
mozilla::dom::ContentPermissionRequestParent* mParent;
|
||||
nsCString mType;
|
||||
nsCString mAccess;
|
||||
nsTArray<mozilla::dom::PermissionRequest> mPermissionRequests;
|
||||
};
|
||||
#endif // nsContentPermissionHelper_h
|
||||
|
||||
#endif // nsContentPermissionHelper_h
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "nsIDocument.h"
|
||||
#include <algorithm>
|
||||
#include "private/pprio.h"
|
||||
#include "nsContentPermissionHelper.h"
|
||||
|
||||
#include "mozilla/dom/DeviceStorageBinding.h"
|
||||
|
||||
@ -1771,17 +1772,14 @@ nsDOMDeviceStorageCursor::GetStorageType(nsAString & aType)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorageCursor::GetType(nsACString & aType)
|
||||
nsDOMDeviceStorageCursor::GetTypes(nsIArray** aTypes)
|
||||
{
|
||||
return DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType,
|
||||
aType);
|
||||
}
|
||||
nsCString type;
|
||||
nsresult rv =
|
||||
DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorageCursor::GetAccess(nsACString & aAccess)
|
||||
{
|
||||
aAccess = NS_LITERAL_CSTRING("read");
|
||||
return NS_OK;
|
||||
return CreatePermissionArray(type, NS_LITERAL_CSTRING("read"), aTypes);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -2386,8 +2384,10 @@ public:
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsTArray<PermissionRequest> permArray;
|
||||
permArray.AppendElement(PermissionRequest(type, access));
|
||||
child->SendPContentPermissionRequestConstructor(
|
||||
this, type, access, IPC::Principal(mPrincipal));
|
||||
this, permArray, IPC::Principal(mPrincipal));
|
||||
|
||||
Sendprompt();
|
||||
return NS_OK;
|
||||
@ -2401,26 +2401,23 @@ public:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetType(nsACString & aType)
|
||||
NS_IMETHODIMP GetTypes(nsIArray** aTypes)
|
||||
{
|
||||
nsCString type;
|
||||
nsresult rv
|
||||
= DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType,
|
||||
aType);
|
||||
nsresult rv =
|
||||
DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, type);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetAccess(nsACString & aAccess)
|
||||
{
|
||||
nsresult rv = DeviceStorageTypeChecker::GetAccessForRequest(
|
||||
DeviceStorageRequestType(mRequestType), aAccess);
|
||||
nsCString access;
|
||||
rv = DeviceStorageTypeChecker::GetAccessForRequest(
|
||||
DeviceStorageRequestType(mRequestType), access);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
|
||||
return CreatePermissionArray(type, access, aTypes);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
|
||||
@ -3557,8 +3554,10 @@ nsDOMDeviceStorage::EnumerateInternal(const nsAString& aPath,
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
child->SendPContentPermissionRequestConstructor(r, type,
|
||||
NS_LITERAL_CSTRING("read"),
|
||||
nsTArray<PermissionRequest> permArray;
|
||||
permArray.AppendElement(PermissionRequest(type, NS_LITERAL_CSTRING("read")));
|
||||
child->SendPContentPermissionRequestConstructor(r,
|
||||
permArray,
|
||||
IPC::Principal(mPrincipal));
|
||||
|
||||
r->Sendprompt();
|
||||
|
@ -7,15 +7,13 @@
|
||||
interface nsIPrincipal;
|
||||
interface nsIDOMWindow;
|
||||
interface nsIDOMElement;
|
||||
interface nsIArray;
|
||||
|
||||
/**
|
||||
* Interface allows access to a content to request
|
||||
* permission to perform a privileged operation such as
|
||||
* geolocation.
|
||||
* Interface provides the request type and its access.
|
||||
*/
|
||||
[scriptable, uuid(1de67000-2de8-11e2-81c1-0800200c9a66)]
|
||||
interface nsIContentPermissionRequest : nsISupports {
|
||||
|
||||
[scriptable, uuid(384b6cc4-a66b-4bea-98e0-eb10562a9ba4)]
|
||||
interface nsIContentPermissionType : nsISupports {
|
||||
/**
|
||||
* The type of the permission request, such as
|
||||
* "geolocation".
|
||||
@ -27,8 +25,22 @@ interface nsIContentPermissionRequest : nsISupports {
|
||||
* "read".
|
||||
*/
|
||||
readonly attribute ACString access;
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface allows access to a content to request
|
||||
* permission to perform a privileged operation such as
|
||||
* geolocation.
|
||||
*/
|
||||
[scriptable, uuid(69a39d88-d1c4-4ba9-9b19-bafc7a1bb783)]
|
||||
interface nsIContentPermissionRequest : nsISupports {
|
||||
/**
|
||||
* The array will include the request types. Elements of this array are
|
||||
* nsIContentPermissionType object.
|
||||
*/
|
||||
readonly attribute nsIArray types;
|
||||
|
||||
/*
|
||||
* The principal of the permission request.
|
||||
*/
|
||||
readonly attribute nsIPrincipal principal;
|
||||
|
@ -16,6 +16,7 @@ include protocol PIndexedDB;
|
||||
include DOMTypes;
|
||||
include JavaScriptTypes;
|
||||
include URIParams;
|
||||
include PContentPermission;
|
||||
|
||||
|
||||
using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h";
|
||||
@ -222,10 +223,8 @@ parent:
|
||||
* Initiates an asynchronous request for permission for the
|
||||
* provided principal.
|
||||
*
|
||||
* @param aType
|
||||
* The type of permission to request.
|
||||
* @param aAccess
|
||||
* Access type. "read" for example.
|
||||
* @param aRequests
|
||||
* The array of permissions to request.
|
||||
* @param aPrincipal
|
||||
* The principal of the request.
|
||||
*
|
||||
@ -233,7 +232,7 @@ parent:
|
||||
* principals that can live in the content process should
|
||||
* provided.
|
||||
*/
|
||||
PContentPermissionRequest(nsCString aType, nsCString aAccess, Principal principal);
|
||||
PContentPermissionRequest(PermissionRequest[] aRequests, Principal aPrincipal);
|
||||
|
||||
PContentDialog(uint32_t aType, nsCString aName, nsCString aFeatures,
|
||||
int32_t[] aIntParams, nsString[] aStringParams);
|
||||
|
14
dom/ipc/PContentPermission.ipdlh
Normal file
14
dom/ipc/PContentPermission.ipdlh
Normal file
@ -0,0 +1,14 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct PermissionRequest {
|
||||
nsCString type;
|
||||
nsCString access;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
@ -1128,12 +1128,11 @@ TabChild::ArraysToParams(const InfallibleTArray<int>& aIntParams,
|
||||
#ifdef DEBUG
|
||||
PContentPermissionRequestChild*
|
||||
TabChild:: SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
|
||||
const nsCString& aType,
|
||||
const nsCString& aAccess,
|
||||
const InfallibleTArray<PermissionRequest>& aRequests,
|
||||
const IPC::Principal& aPrincipal)
|
||||
{
|
||||
PCOMContentPermissionRequestChild* child = static_cast<PCOMContentPermissionRequestChild*>(aActor);
|
||||
PContentPermissionRequestChild* request = PBrowserChild::SendPContentPermissionRequestConstructor(aActor, aType, aAccess, aPrincipal);
|
||||
PContentPermissionRequestChild* request = PBrowserChild::SendPContentPermissionRequestConstructor(aActor, aRequests, aPrincipal);
|
||||
child->mIPCOpen = true;
|
||||
return request;
|
||||
}
|
||||
@ -2066,7 +2065,8 @@ TabChild::DeallocPContentDialogChild(PContentDialogChild* aDialog)
|
||||
}
|
||||
|
||||
PContentPermissionRequestChild*
|
||||
TabChild::AllocPContentPermissionRequestChild(const nsCString& aType, const nsCString& aAccess, const IPC::Principal&)
|
||||
TabChild::AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,
|
||||
const IPC::Principal& aPrincipal)
|
||||
{
|
||||
NS_RUNTIMEABORT("unused");
|
||||
return nullptr;
|
||||
|
@ -295,14 +295,12 @@ public:
|
||||
#ifdef DEBUG
|
||||
virtual PContentPermissionRequestChild*
|
||||
SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
|
||||
const nsCString& aType,
|
||||
const nsCString& aAccess,
|
||||
const InfallibleTArray<PermissionRequest>& aRequests,
|
||||
const IPC::Principal& aPrincipal);
|
||||
#endif /* DEBUG */
|
||||
|
||||
virtual PContentPermissionRequestChild*
|
||||
AllocPContentPermissionRequestChild(const nsCString& aType,
|
||||
const nsCString& aAccess,
|
||||
AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,
|
||||
const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
|
||||
virtual bool
|
||||
DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor) MOZ_OVERRIDE;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "mozilla/BrowserElementParent.h"
|
||||
#include "mozilla/docshell/OfflineCacheUpdateParent.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/PContentPermissionRequestParent.h"
|
||||
#include "mozilla/Hal.h"
|
||||
#include "mozilla/ipc/DocumentRendererParent.h"
|
||||
#include "mozilla/layers/CompositorParent.h"
|
||||
@ -623,9 +624,10 @@ TabParent::DeallocPDocumentRendererParent(PDocumentRendererParent* actor)
|
||||
}
|
||||
|
||||
PContentPermissionRequestParent*
|
||||
TabParent::AllocPContentPermissionRequestParent(const nsCString& type, const nsCString& access, const IPC::Principal& principal)
|
||||
TabParent::AllocPContentPermissionRequestParent(const InfallibleTArray<PermissionRequest>& aRequests,
|
||||
const IPC::Principal& aPrincipal)
|
||||
{
|
||||
return new ContentPermissionRequestParent(type, access, mFrameElement, principal);
|
||||
return CreateContentPermissionRequestParent(aRequests, mFrameElement, aPrincipal);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -253,8 +253,7 @@ public:
|
||||
virtual bool DeallocPDocumentRendererParent(PDocumentRendererParent* actor) MOZ_OVERRIDE;
|
||||
|
||||
virtual PContentPermissionRequestParent*
|
||||
AllocPContentPermissionRequestParent(const nsCString& aType,
|
||||
const nsCString& aAccess,
|
||||
AllocPContentPermissionRequestParent(const InfallibleTArray<PermissionRequest>& aRequests,
|
||||
const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
|
||||
virtual bool
|
||||
DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor) MOZ_OVERRIDE;
|
||||
|
@ -68,6 +68,7 @@ IPDL_SOURCES += [
|
||||
'PBrowser.ipdl',
|
||||
'PContent.ipdl',
|
||||
'PContentDialog.ipdl',
|
||||
'PContentPermission.ipdlh',
|
||||
'PContentPermissionRequest.ipdl',
|
||||
'PCrashReporter.ipdl',
|
||||
'PDocumentRenderer.ipdl',
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include "MediaEngineWebRTC.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#ifdef MOZ_B2G
|
||||
#include "MediaPermissionGonk.h"
|
||||
#endif
|
||||
|
||||
@ -780,7 +780,7 @@ public:
|
||||
, mListener(aListener)
|
||||
, mPrefs(aPrefs)
|
||||
, mDeviceChosen(false)
|
||||
, mBackendChosen(false)
|
||||
, mBackend(nullptr)
|
||||
, mManager(MediaManager::GetInstance())
|
||||
{}
|
||||
|
||||
@ -804,15 +804,11 @@ public:
|
||||
, mListener(aListener)
|
||||
, mPrefs(aPrefs)
|
||||
, mDeviceChosen(false)
|
||||
, mBackendChosen(true)
|
||||
, mBackend(aBackend)
|
||||
, mManager(MediaManager::GetInstance())
|
||||
{}
|
||||
|
||||
~GetUserMediaRunnable() {
|
||||
if (mBackendChosen) {
|
||||
delete mBackend;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -834,14 +830,15 @@ public:
|
||||
MOZ_ASSERT(mSuccess.mRawPtr);
|
||||
MOZ_ASSERT(mError.mRawPtr);
|
||||
|
||||
MediaEngine* backend = mBackend;
|
||||
// Was a backend provided?
|
||||
if (!mBackendChosen) {
|
||||
mBackend = mManager->GetBackend(mWindowID);
|
||||
if (!backend) {
|
||||
backend = mManager->GetBackend(mWindowID);
|
||||
}
|
||||
|
||||
// Was a device provided?
|
||||
if (!mDeviceChosen) {
|
||||
nsresult rv = SelectDevice();
|
||||
nsresult rv = SelectDevice(backend);
|
||||
if (rv != NS_OK) {
|
||||
return rv;
|
||||
}
|
||||
@ -917,12 +914,12 @@ public:
|
||||
}
|
||||
|
||||
nsresult
|
||||
SelectDevice()
|
||||
SelectDevice(MediaEngine* backend)
|
||||
{
|
||||
MOZ_ASSERT(mSuccess.mRawPtr);
|
||||
MOZ_ASSERT(mError.mRawPtr);
|
||||
if (mConstraints.mPicture || mConstraints.mVideo) {
|
||||
ScopedDeletePtr<SourceSet> sources (GetSources(mBackend,
|
||||
ScopedDeletePtr<SourceSet> sources (GetSources(backend,
|
||||
mConstraints.mVideom, &MediaEngine::EnumerateVideoDevices));
|
||||
|
||||
if (!sources->Length()) {
|
||||
@ -936,7 +933,7 @@ public:
|
||||
}
|
||||
|
||||
if (mConstraints.mAudio) {
|
||||
ScopedDeletePtr<SourceSet> sources (GetSources(mBackend,
|
||||
ScopedDeletePtr<SourceSet> sources (GetSources(backend,
|
||||
mConstraints.mAudiom, &MediaEngine::EnumerateAudioDevices));
|
||||
|
||||
if (!sources->Length()) {
|
||||
@ -1036,9 +1033,8 @@ private:
|
||||
MediaEnginePrefs mPrefs;
|
||||
|
||||
bool mDeviceChosen;
|
||||
bool mBackendChosen;
|
||||
|
||||
MediaEngine* mBackend;
|
||||
RefPtr<MediaEngine> mBackend;
|
||||
nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
|
||||
};
|
||||
|
||||
@ -1328,10 +1324,10 @@ MediaManager::GetUserMedia(JSContext* aCx, bool aPrivileged,
|
||||
// Force MediaManager to startup before we try to access it from other threads
|
||||
// Hack: should init singleton earlier unless it's expensive (mem or CPU)
|
||||
(void) MediaManager::Get();
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#ifdef MOZ_B2G
|
||||
// Initialize MediaPermissionManager before send out any permission request.
|
||||
(void) MediaPermissionManager::GetInstance();
|
||||
#endif //MOZ_WIDGET_GONK
|
||||
#endif //MOZ_B2G
|
||||
}
|
||||
|
||||
// Store the WindowID in a hash table and mark as active. The entry is removed
|
||||
|
@ -514,9 +514,7 @@ private:
|
||||
// Make private because we want only one instance of this class
|
||||
MediaManager();
|
||||
|
||||
~MediaManager() {
|
||||
delete mBackend;
|
||||
}
|
||||
~MediaManager() {}
|
||||
|
||||
nsresult MediaCaptureWindowStateInternal(nsIDOMWindow* aWindow, bool* aVideo,
|
||||
bool* aAudio);
|
||||
@ -532,11 +530,11 @@ private:
|
||||
|
||||
Mutex mMutex;
|
||||
// protected with mMutex:
|
||||
MediaEngine* mBackend;
|
||||
RefPtr<MediaEngine> mBackend;
|
||||
|
||||
static StaticRefPtr<MediaManager> sSingleton;
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#ifdef MOZ_B2G_CAMERA
|
||||
nsRefPtr<nsDOMCameraManager> mCameraManager;
|
||||
#endif
|
||||
};
|
||||
|
@ -20,14 +20,36 @@
|
||||
#include "mozilla/dom/MediaStreamTrackBinding.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsContentPermissionHelper.h"
|
||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||
|
||||
#define AUDIO_PERMISSION_NAME "audio-capture"
|
||||
#define VIDEO_PERMISSION_NAME "video-capture"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
static MediaPermissionManager *gMediaPermMgr = nullptr;
|
||||
|
||||
static uint32_t
|
||||
ConvertArrayToPermissionRequest(nsIArray* aSrcArray,
|
||||
nsTArray<PermissionRequest>& aDesArray)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
aSrcArray->GetLength(&len);
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
nsCOMPtr<nsIContentPermissionType> cpt = do_QueryElementAt(aSrcArray, i);
|
||||
nsAutoCString type;
|
||||
nsAutoCString access;
|
||||
cpt->GetType(type);
|
||||
cpt->GetAccess(access);
|
||||
aDesArray.AppendElement(PermissionRequest(type, access));
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
// Helper function for notifying permission granted
|
||||
static nsresult
|
||||
NotifyPermissionAllow(const nsAString &aCallID, nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices)
|
||||
@ -93,6 +115,7 @@ public:
|
||||
|
||||
private:
|
||||
bool mAudio; // Request for audio permission
|
||||
bool mVideo; // Request for video permission
|
||||
nsRefPtr<dom::GetUserMediaRequest> mRequest;
|
||||
nsTArray<nsCOMPtr<nsIMediaDevice> > mDevices; // candiate device list
|
||||
};
|
||||
@ -108,6 +131,7 @@ MediaPermissionRequest::MediaPermissionRequest(nsRefPtr<dom::GetUserMediaRequest
|
||||
mRequest->GetConstraints(constraints);
|
||||
|
||||
mAudio = constraints.mAudio;
|
||||
mVideo = constraints.mVideo;
|
||||
|
||||
for (uint32_t i = 0; i < aDevices.Length(); ++i) {
|
||||
nsCOMPtr<nsIMediaDevice> device(aDevices[i]);
|
||||
@ -116,10 +140,34 @@ MediaPermissionRequest::MediaPermissionRequest(nsRefPtr<dom::GetUserMediaRequest
|
||||
if (mAudio && deviceType.EqualsLiteral("audio")) {
|
||||
mDevices.AppendElement(device);
|
||||
}
|
||||
if (mVideo && deviceType.EqualsLiteral("video")) {
|
||||
mDevices.AppendElement(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// nsIContentPermissionRequest methods
|
||||
NS_IMETHODIMP
|
||||
MediaPermissionRequest::GetTypes(nsIArray** aTypes)
|
||||
{
|
||||
nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
if (mAudio) {
|
||||
nsCOMPtr<ContentPermissionType> AudioType =
|
||||
new ContentPermissionType(NS_LITERAL_CSTRING(AUDIO_PERMISSION_NAME),
|
||||
NS_LITERAL_CSTRING("unused"));
|
||||
types->AppendElement(AudioType, false);
|
||||
}
|
||||
if (mVideo) {
|
||||
nsCOMPtr<ContentPermissionType> VideoType =
|
||||
new ContentPermissionType(NS_LITERAL_CSTRING(VIDEO_PERMISSION_NAME),
|
||||
NS_LITERAL_CSTRING("unused"));
|
||||
types->AppendElement(VideoType, false);
|
||||
}
|
||||
NS_IF_ADDREF(*aTypes = types);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MediaPermissionRequest::GetPrincipal(nsIPrincipal **aRequestingPrincipal)
|
||||
{
|
||||
@ -135,24 +183,6 @@ MediaPermissionRequest::GetPrincipal(nsIPrincipal **aRequestingPrincipal)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MediaPermissionRequest::GetType(nsACString &aType)
|
||||
{
|
||||
if (mAudio) {
|
||||
aType = AUDIO_PERMISSION_NAME;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MediaPermissionRequest::GetAccess(nsACString &aAccess)
|
||||
{
|
||||
aAccess = "unused";
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MediaPermissionRequest::GetWindow(nsIDOMWindow** aRequestingWindow)
|
||||
{
|
||||
@ -278,13 +308,12 @@ MediaDeviceSuccessCallback::DoPrompt(nsRefPtr<MediaPermissionRequest> &req)
|
||||
dom::TabChild* child = dom::TabChild::GetFrom(window->GetDocShell());
|
||||
NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
|
||||
|
||||
nsAutoCString type;
|
||||
rv = req->GetType(type);
|
||||
nsCOMPtr<nsIArray> typeArray;
|
||||
rv = req->GetTypes(getter_AddRefs(typeArray));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString access;
|
||||
rv = req->GetAccess(access);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsTArray<PermissionRequest> permArray;
|
||||
ConvertArrayToPermissionRequest(typeArray, permArray);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
rv = req->GetPrincipal(getter_AddRefs(principal));
|
||||
@ -292,8 +321,7 @@ MediaDeviceSuccessCallback::DoPrompt(nsRefPtr<MediaPermissionRequest> &req)
|
||||
|
||||
req->AddRef();
|
||||
child->SendPContentPermissionRequestConstructor(req,
|
||||
type,
|
||||
access,
|
||||
permArray,
|
||||
IPC::Principal(principal));
|
||||
|
||||
req->Sendprompt();
|
||||
|
@ -379,17 +379,11 @@ nsGeolocationRequest::GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGeolocationRequest::GetType(nsACString & aType)
|
||||
nsGeolocationRequest::GetTypes(nsIArray** aTypes)
|
||||
{
|
||||
aType = "geolocation";
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGeolocationRequest::GetAccess(nsACString & aAccess)
|
||||
{
|
||||
aAccess = "unused";
|
||||
return NS_OK;
|
||||
return CreatePermissionArray(NS_LITERAL_CSTRING("geolocation"),
|
||||
NS_LITERAL_CSTRING("unused"),
|
||||
aTypes);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1477,12 +1471,15 @@ Geolocation::RegisterRequestWithPrompt(nsGeolocationRequest* request)
|
||||
return false;
|
||||
}
|
||||
|
||||
nsTArray<PermissionRequest> permArray;
|
||||
permArray.AppendElement(PermissionRequest(NS_LITERAL_CSTRING("geolocation"),
|
||||
NS_LITERAL_CSTRING("unused")));
|
||||
|
||||
// Retain a reference so the object isn't deleted without IPDL's knowledge.
|
||||
// Corresponding release occurs in DeallocPContentPermissionRequest.
|
||||
request->AddRef();
|
||||
child->SendPContentPermissionRequestConstructor(request,
|
||||
NS_LITERAL_CSTRING("geolocation"),
|
||||
NS_LITERAL_CSTRING("unused"),
|
||||
permArray,
|
||||
IPC::Principal(mPrincipal));
|
||||
|
||||
request->Sendprompt();
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "PCOMContentPermissionRequestChild.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "PermissionMessageUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -177,9 +178,12 @@ DesktopNotification::Init()
|
||||
// Corresponding release occurs in DeallocPContentPermissionRequest.
|
||||
nsRefPtr<DesktopNotificationRequest> copy = request;
|
||||
|
||||
nsTArray<PermissionRequest> permArray;
|
||||
permArray.AppendElement(PermissionRequest(
|
||||
NS_LITERAL_CSTRING("desktop-notification"),
|
||||
NS_LITERAL_CSTRING("unused")));
|
||||
child->SendPContentPermissionRequestConstructor(copy.forget().get(),
|
||||
NS_LITERAL_CSTRING("desktop-notification"),
|
||||
NS_LITERAL_CSTRING("unused"),
|
||||
permArray,
|
||||
IPC::Principal(mPrincipal));
|
||||
|
||||
request->Sendprompt();
|
||||
@ -351,17 +355,11 @@ DesktopNotificationRequest::Allow()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DesktopNotificationRequest::GetType(nsACString & aType)
|
||||
DesktopNotificationRequest::GetTypes(nsIArray** aTypes)
|
||||
{
|
||||
aType = "desktop-notification";
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DesktopNotificationRequest::GetAccess(nsACString & aAccess)
|
||||
{
|
||||
aAccess = "unused";
|
||||
return NS_OK;
|
||||
return CreatePermissionArray(NS_LITERAL_CSTRING("desktop-notification"),
|
||||
NS_LITERAL_CSTRING("unused"),
|
||||
aTypes);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "nsDOMJSUtils.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||
#include "nsContentPermissionHelper.h"
|
||||
#ifdef MOZ_B2G
|
||||
#include "nsIDOMDesktopNotification.h"
|
||||
#endif
|
||||
@ -267,9 +268,11 @@ NotificationPermissionRequest::Run()
|
||||
// Corresponding release occurs in DeallocPContentPermissionRequest.
|
||||
AddRef();
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(type, "desktop-notification");
|
||||
NS_NAMED_LITERAL_CSTRING(access, "unused");
|
||||
child->SendPContentPermissionRequestConstructor(this, type, access,
|
||||
nsTArray<PermissionRequest> permArray;
|
||||
permArray.AppendElement(PermissionRequest(
|
||||
NS_LITERAL_CSTRING("desktop-notification"),
|
||||
NS_LITERAL_CSTRING("unused")));
|
||||
child->SendPContentPermissionRequestConstructor(this, permArray,
|
||||
IPC::Principal(mPrincipal));
|
||||
|
||||
Sendprompt();
|
||||
@ -342,17 +345,11 @@ NotificationPermissionRequest::CallCallback()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NotificationPermissionRequest::GetAccess(nsACString& aAccess)
|
||||
NotificationPermissionRequest::GetTypes(nsIArray** aTypes)
|
||||
{
|
||||
aAccess.AssignLiteral("unused");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NotificationPermissionRequest::GetType(nsACString& aType)
|
||||
{
|
||||
aType.AssignLiteral("desktop-notification");
|
||||
return NS_OK;
|
||||
return CreatePermissionArray(NS_LITERAL_CSTRING("desktop-notification"),
|
||||
NS_LITERAL_CSTRING("unused"),
|
||||
aTypes);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -21,8 +21,8 @@ ContentPermissionPrompt.prototype = {
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionPrompt]),
|
||||
|
||||
handleExistingPermission: function handleExistingPermission(request, isApp) {
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, request.type);
|
||||
handleExistingPermission: function handleExistingPermission(request, type, isApp) {
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, type);
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
request.allow();
|
||||
return true;
|
||||
@ -32,7 +32,7 @@ ContentPermissionPrompt.prototype = {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isApp && (result == Ci.nsIPermissionManager.UNKNOWN_ACTION && !!kEntities[request.type])) {
|
||||
if (isApp && (result == Ci.nsIPermissionManager.UNKNOWN_ACTION && !!kEntities[type])) {
|
||||
request.cancel();
|
||||
return true;
|
||||
}
|
||||
@ -62,8 +62,16 @@ ContentPermissionPrompt.prototype = {
|
||||
prompt: function(request) {
|
||||
let isApp = request.principal.appId !== Ci.nsIScriptSecurityManager.NO_APP_ID && request.principal.appId !== Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID;
|
||||
|
||||
// Only allow exactly one permission rquest here.
|
||||
let types = request.types.QueryInterface(Ci.nsIArray);
|
||||
if (types.length != 1) {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
let perm = types.queryElementAt(0, Ci.nsIContentPermissionType);
|
||||
|
||||
// Returns true if the request was handled
|
||||
if (this.handleExistingPermission(request, isApp))
|
||||
if (this.handleExistingPermission(request, perm.type, isApp))
|
||||
return;
|
||||
|
||||
let chromeWin = this.getChromeForRequest(request);
|
||||
@ -72,17 +80,17 @@ ContentPermissionPrompt.prototype = {
|
||||
return;
|
||||
|
||||
let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
|
||||
let entityName = kEntities[request.type];
|
||||
let entityName = kEntities[perm.type];
|
||||
|
||||
let buttons = [{
|
||||
label: browserBundle.GetStringFromName(entityName + ".allow"),
|
||||
callback: function(aChecked) {
|
||||
// If the user checked "Don't ask again", make a permanent exception
|
||||
if (aChecked) {
|
||||
Services.perms.addFromPrincipal(request.principal, request.type, Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
} else if (isApp || entityName == "desktopNotification") {
|
||||
// Otherwise allow the permission for the current session (if the request comes from an app or if it's a desktop-notification request)
|
||||
Services.perms.addFromPrincipal(request.principal, request.type, Ci.nsIPermissionManager.ALLOW_ACTION, Ci.nsIPermissionManager.EXPIRE_SESSION);
|
||||
Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.ALLOW_ACTION, Ci.nsIPermissionManager.EXPIRE_SESSION);
|
||||
}
|
||||
|
||||
request.allow();
|
||||
@ -93,7 +101,7 @@ ContentPermissionPrompt.prototype = {
|
||||
callback: function(aChecked) {
|
||||
// If the user checked "Don't ask again", make a permanent exception
|
||||
if (aChecked)
|
||||
Services.perms.addFromPrincipal(request.principal, request.type, Ci.nsIPermissionManager.DENY_ACTION);
|
||||
Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.DENY_ACTION);
|
||||
|
||||
request.cancel();
|
||||
}
|
||||
|
@ -34,9 +34,18 @@ this.MockPermissionPrompt = {
|
||||
init: function() {
|
||||
this.reset();
|
||||
if (!registrar.isCIDRegistered(newClassID)) {
|
||||
oldClassID = registrar.contractIDToCID(CONTRACT_ID);
|
||||
oldFactory = Cm.getClassObject(Cc[CONTRACT_ID], Ci.nsIFactory);
|
||||
registrar.unregisterFactory(oldClassID, oldFactory);
|
||||
try {
|
||||
oldClassID = registrar.contractIDToCID(CONTRACT_ID);
|
||||
oldFactory = Cm.getClassObject(Cc[CONTRACT_ID], Ci.nsIFactory);
|
||||
} catch (ex) {
|
||||
oldClassID = "";
|
||||
oldFactory = null;
|
||||
dump("TEST-INFO | can't get permission prompt registered component, " +
|
||||
"assuming there is none");
|
||||
}
|
||||
if (oldFactory) {
|
||||
registrar.unregisterFactory(oldClassID, oldFactory);
|
||||
}
|
||||
registrar.registerFactory(newClassID, "", CONTRACT_ID, newFactory);
|
||||
}
|
||||
},
|
||||
@ -61,14 +70,17 @@ MockPermissionPromptInstance.prototype = {
|
||||
|
||||
prompt: function(request) {
|
||||
|
||||
this.promptResult = Services.perms.testExactPermissionFromPrincipal(request.principal,
|
||||
request.type);
|
||||
if (this.promptResult == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
request.allow();
|
||||
}
|
||||
else {
|
||||
request.cancel();
|
||||
let perms = request.types.QueryInterface(Ci.nsIArray);
|
||||
for (let idx = 0; idx < perms.length; idx++) {
|
||||
let perm = perms.queryElementAt(idx, Ci.nsIContentPermissionType);
|
||||
if (Services.perms.testExactPermissionFromPrincipal(
|
||||
request.principal, perm.type) != Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
request.allow();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -30,17 +30,25 @@ ContentPermission.prototype = {
|
||||
},
|
||||
|
||||
prompt: function(request) {
|
||||
// Only allow exactly one permission rquest here.
|
||||
let types = request.types.QueryInterface(Ci.nsIArray);
|
||||
if (types.length != 1) {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
let perm = types.queryElementAt(0, Ci.nsIContentPermissionType);
|
||||
|
||||
// Reuse any remembered permission preferences
|
||||
let result =
|
||||
Services.perms.testExactPermissionFromPrincipal(request.principal,
|
||||
request.type);
|
||||
perm.type);
|
||||
|
||||
// We used to use the name "geo" for the geolocation permission, now we're
|
||||
// using "geolocation". We need to check both to support existing
|
||||
// installations.
|
||||
if ((result == Ci.nsIPermissionManager.UNKNOWN_ACTION ||
|
||||
result == Ci.nsIPermissionManager.PROMPT_ACTION) &&
|
||||
request.type == "geolocation") {
|
||||
perm.type == "geolocation") {
|
||||
let geoResult = Services.perms.testExactPermission(request.principal.URI,
|
||||
"geo");
|
||||
// We override the result only if the "geo" permission was allowed or
|
||||
@ -56,7 +64,7 @@ ContentPermission.prototype = {
|
||||
return;
|
||||
} else if (result == Ci.nsIPermissionManager.DENY_ACTION ||
|
||||
(result == Ci.nsIPermissionManager.UNKNOWN_ACTION &&
|
||||
UNKNOWN_FAIL.indexOf(request.type) >= 0)) {
|
||||
UNKNOWN_FAIL.indexOf(perm.type) >= 0)) {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
@ -71,16 +79,16 @@ ContentPermission.prototype = {
|
||||
let remember = {value: false};
|
||||
let choice = Services.prompt.confirmEx(
|
||||
chromeWin,
|
||||
bundle.formatStringFromName(request.type + ".title", [name], 1),
|
||||
bundle.GetStringFromName(request.type + ".description"),
|
||||
bundle.formatStringFromName(perm.type + ".title", [name], 1),
|
||||
bundle.GetStringFromName(perm.type + ".description"),
|
||||
// Set both buttons to strings with the cancel button being default
|
||||
Ci.nsIPromptService.BUTTON_POS_1_DEFAULT |
|
||||
Ci.nsIPromptService.BUTTON_TITLE_IS_STRING * Ci.nsIPromptService.BUTTON_POS_0 |
|
||||
Ci.nsIPromptService.BUTTON_TITLE_IS_STRING * Ci.nsIPromptService.BUTTON_POS_1,
|
||||
bundle.GetStringFromName(request.type + ".allow"),
|
||||
bundle.GetStringFromName(request.type + ".deny"),
|
||||
bundle.GetStringFromName(perm.type + ".allow"),
|
||||
bundle.GetStringFromName(perm.type + ".deny"),
|
||||
null,
|
||||
bundle.GetStringFromName(request.type + ".remember"),
|
||||
bundle.GetStringFromName(perm.type + ".remember"),
|
||||
remember);
|
||||
|
||||
let action = Ci.nsIPermissionManager.ALLOW_ACTION;
|
||||
@ -90,10 +98,10 @@ ContentPermission.prototype = {
|
||||
|
||||
if (remember.value) {
|
||||
// Persist the choice if the user wants to remember
|
||||
Services.perms.addFromPrincipal(request.principal, request.type, action);
|
||||
Services.perms.addFromPrincipal(request.principal, perm.type, action);
|
||||
} else {
|
||||
// Otherwise allow the permission for the current session
|
||||
Services.perms.addFromPrincipal(request.principal, request.type, action,
|
||||
Services.perms.addFromPrincipal(request.principal, perm.type, action,
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user