Backed out 4 changesets (bug 853356) for breaking permission prompts.

This commit is contained in:
Reuben Morais 2013-11-06 01:32:42 -02:00
Родитель 8462256861
Коммит 1d3b24a4d5
28 изменённых файлов: 343 добавлений и 721 удалений

Просмотреть файл

@ -5,7 +5,7 @@
"use strict"
function debug(str) {
//dump("-*- ContentPermissionPrompt: " + str + "\n");
//dump("-*- ContentPermissionPrompt: " + s + "\n");
}
const Ci = Components.interfaces;
@ -13,14 +13,11 @@ const Cr = Components.results;
const Cu = Components.utils;
const Cc = Components.classes;
const PROMPT_FOR_UNKNOWN = ["audio-capture",
"desktop-notification",
"geolocation",
"video-capture"];
const PROMPT_FOR_UNKNOWN = ["geolocation", "desktop-notification",
"audio-capture"];
// Due to privary issue, permission requests like GetUserMedia should prompt
// every time instead of providing session persistence.
const PERMISSION_NO_SESSION = ["audio-capture", "video-capture"];
const ALLOW_MULTIPLE_REQUESTS = ["audio-capture", "video-capture"];
const PERMISSION_NO_SESSION = ["audio-capture"];
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
@ -44,21 +41,7 @@ XPCOMUtils.defineLazyServiceGetter(this,
"@mozilla.org/telephony/audiomanager;1",
"nsIAudioManager");
/**
* 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 rememberPermission(aPermission, aPrincipal, aSession)
{
function convertPermToAllow(aPerm, aPrincipal)
{
@ -66,13 +49,12 @@ function rememberPermission(aTypesInfo, aPrincipal, aSession)
permissionManager.testExactPermissionFromPrincipal(aPrincipal, aPerm);
if (type == Ci.nsIPermissionManager.PROMPT_ACTION ||
(type == Ci.nsIPermissionManager.UNKNOWN_ACTION &&
PROMPT_FOR_UNKNOWN.indexOf(aPerm) >= 0)) {
debug("add " + aPerm + " to permission manager with ALLOW_ACTION");
PROMPT_FOR_UNKNOWN.indexOf(aPermission) >= 0)) {
if (!aSession) {
permissionManager.addFromPrincipal(aPrincipal,
aPerm,
Ci.nsIPermissionManager.ALLOW_ACTION);
} else if (PERMISSION_NO_SESSION.indexOf(aPerm) < 0) {
} else if (PERMISSION_NO_SESSION.indexOf(aPermission) < 0) {
permissionManager.addFromPrincipal(aPrincipal,
aPerm,
Ci.nsIPermissionManager.ALLOW_ACTION,
@ -81,18 +63,14 @@ function rememberPermission(aTypesInfo, aPrincipal, aSession)
}
}
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);
// 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);
}
} else {
convertPermToAllow(aPermission, aPrincipal);
}
}
@ -100,63 +78,23 @@ function ContentPermissionPrompt() {}
ContentPermissionPrompt.prototype = {
handleExistingPermission: function handleExistingPermission(request,
typesInfo) {
typesInfo.forEach(function(type) {
type.action =
Services.perms.testExactPermissionFromPrincipal(request.principal,
type.access);
});
// 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");
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) {
request.allow();
return true;
}
// 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 &&
PROMPT_FOR_UNKNOWN.indexOf(type.access) < 0) {
return true;
}
return false;
}
if (typesInfo.every(checkDenyPermission)) {
debug("all permission requests are denied");
if (result == Ci.nsIPermissionManager.DENY_ACTION ||
result == Ci.nsIPermissionManager.UNKNOWN_ACTION && PROMPT_FOR_UNKNOWN.indexOf(access) < 0) {
request.cancel();
return true;
}
return false;
},
// 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) {
handledByApp: function handledByApp(request) {
if (request.principal.appId == Ci.nsIScriptSecurityManager.NO_APP_ID ||
request.principal.appId == Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID) {
// This should not really happen
@ -168,94 +106,49 @@ ContentPermissionPrompt.prototype = {
.getService(Ci.nsIAppsService);
let app = appsService.getAppByLocalId(request.principal.appId);
// Check each permission if it's denied by permission manager with app's
// URL.
let checkIfDenyAppPrincipal = 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);
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);
if (result == Ci.nsIPermissionManager.ALLOW_ACTION ||
result == Ci.nsIPermissionManager.PROMPT_ACTION) {
type.deny = false;
}
return type.deny;
}
if (typesInfo.every(checkIfDenyAppPrincipal)) {
request.cancel();
return true;
if (result == Ci.nsIPermissionManager.ALLOW_ACTION ||
result == Ci.nsIPermissionManager.PROMPT_ACTION) {
return false;
}
return false;
request.cancel();
return true;
},
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;
handledByPermissionType: function handledByPermissionType(request) {
return permissionSpecificChecker.hasOwnProperty(request.type)
? permissionSpecificChecker[request.type](request)
: false;
},
_id: 0,
prompt: function(request) {
if (secMan.isSystemPrincipal(request.principal)) {
request.allow();
return;
return true;
}
// 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)) {
if (this.handledByApp(request) ||
this.handledByPermissionType(request)) {
return;
}
// returns true if the request was handled
if (this.handleExistingPermission(request, typesInfo)) {
if (this.handleExistingPermission(request))
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, typesInfo);
this.delegatePrompt(request, requestId);
return;
}
@ -270,7 +163,7 @@ ContentPermissionPrompt.prototype = {
if (evt.detail.visible === true)
return;
self.cancelPrompt(request, requestId, typesInfo);
self.cancelPrompt(request, requestId);
cancelRequest();
}
@ -287,7 +180,7 @@ ContentPermissionPrompt.prototype = {
// away but the request is still here.
frame.addEventListener("mozbrowservisibilitychange", onVisibilityChange);
self.delegatePrompt(request, requestId, typesInfo, function onCallback() {
self.delegatePrompt(request, requestId, function onCallback() {
frame.removeEventListener("mozbrowservisibilitychange", onVisibilityChange);
});
};
@ -298,17 +191,22 @@ ContentPermissionPrompt.prototype = {
}
},
cancelPrompt: function(request, requestId, typesInfo) {
this.sendToBrowserWindow("cancel-permission-prompt", request, requestId,
typesInfo);
cancelPrompt: function(request, requestId) {
this.sendToBrowserWindow("cancel-permission-prompt", request, requestId);
},
delegatePrompt: function(request, requestId, typesInfo, callback) {
delegatePrompt: function(request, requestId, callback) {
let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
request.type;
let principal = request.principal;
this.sendToBrowserWindow("permission-prompt", request, requestId, typesInfo,
function(type, remember) {
this._permission = access;
this._uri = principal.URI.spec;
this._origin = principal.origin;
this.sendToBrowserWindow("permission-prompt", request, requestId, function(type, remember) {
if (type == "permission-allow") {
rememberPermission(typesInfo, request.principal, !remember);
rememberPermission(request.type, principal, !remember);
if (callback) {
callback();
}
@ -316,20 +214,14 @@ ContentPermissionPrompt.prototype = {
return;
}
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 {
Services.perms.addFromPrincipal(request.principal, type.access,
Ci.nsIPermissionManager.DENY_ACTION,
Ci.nsIPermissionManager.EXPIRE_SESSION,
0);
}
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);
}
typesInfo.forEach(addDenyPermission);
if (callback) {
callback();
@ -338,7 +230,7 @@ ContentPermissionPrompt.prototype = {
});
},
sendToBrowserWindow: function(type, request, requestId, typesInfo, callback) {
sendToBrowserWindow: function(type, request, requestId, callback) {
let browser = Services.wm.getMostRecentWindow("navigator:browser");
let content = browser.getContentWindow();
if (!content)
@ -361,15 +253,10 @@ 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.push(typesInfo[i].permission);
}
let details = {
type: type,
permissions: permissions,
permission: request.type,
id: requestId,
origin: principal.origin,
isApp: isApp,
@ -402,5 +289,6 @@ ContentPermissionPrompt.prototype = {
};
})();
//module initialization
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentPermissionPrompt]);

Просмотреть файл

@ -1995,21 +1995,13 @@ 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 (!(perm.type in kFeatureKeys)) {
if (!(request.type in kFeatureKeys)) {
return;
}
@ -2021,7 +2013,7 @@ ContentPermissionPrompt.prototype = {
return;
var autoAllow = false;
var permissionKey = kFeatureKeys[perm.type];
var permissionKey = kFeatureKeys[request.type];
var result = Services.perms.testExactPermissionFromPrincipal(requestingPrincipal, permissionKey);
if (result == Ci.nsIPermissionManager.DENY_ACTION) {
@ -2032,14 +2024,14 @@ ContentPermissionPrompt.prototype = {
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
autoAllow = true;
// For pointerLock, we still want to show a warning prompt.
if (perm.type != "pointerLock") {
if (request.type != "pointerLock") {
request.allow();
return;
}
}
// Show the prompt.
switch (perm.type) {
switch (request.type) {
case "geolocation":
this._promptGeo(request);
break;

Просмотреть файл

@ -44,8 +44,6 @@ let IndexedDB = {
}
let prompt = Cc["@mozilla.org/content-permission/prompt;1"].createInstance(Ci.nsIContentPermissionPrompt);
let types = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
types.appendElement({type: type, access: "unused"}, false);
// If the user waits a long time before responding, we default to UNKNOWN_ACTION.
let timeoutId = setTimeout(function() {
@ -62,7 +60,7 @@ let IndexedDB = {
}
prompt.prompt({
types: types,
type: type,
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, type) {
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, type);
handleExistingPermission: function handleExistingPermission(request) {
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, request.type);
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
request.allow();
return true;
@ -70,28 +70,20 @@ 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, perm.type))
if (this.handleExistingPermission(request))
return;
let pm = Services.perms;
let notificationBox = this.getNotificationBoxForRequest(request);
let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
let notification = notificationBox.getNotificationWithValue(perm.type);
let notification = notificationBox.getNotificationWithValue(request.type);
if (notification)
return;
let entityName = kEntities[perm.type];
let icon = kIcons[perm.type] || "";
let entityName = kEntities[request.type];
let icon = kIcons[request.type] || "";
let buttons = [{
label: browserBundle.GetStringFromName(entityName + ".allow"),
@ -104,7 +96,7 @@ ContentPermissionPrompt.prototype = {
label: browserBundle.GetStringFromName("contentPermissions.alwaysForSite"),
accessKey: "",
callback: function(notification) {
Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.ALLOW_ACTION);
Services.perms.addFromPrincipal(request.principal, request.type, Ci.nsIPermissionManager.ALLOW_ACTION);
request.allow();
}
},
@ -112,7 +104,7 @@ ContentPermissionPrompt.prototype = {
label: browserBundle.GetStringFromName("contentPermissions.neverForSite"),
accessKey: "",
callback: function(notification) {
Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.DENY_ACTION);
Services.perms.addFromPrincipal(request.principal, request.type, Ci.nsIPermissionManager.DENY_ACTION);
request.cancel();
}
}];
@ -120,12 +112,12 @@ ContentPermissionPrompt.prototype = {
let message = browserBundle.formatStringFromName(entityName + ".wantsTo",
[request.principal.URI.host], 1);
let newBar = notificationBox.appendNotification(message,
perm.type,
request.type,
icon,
notificationBox.PRIORITY_WARNING_MEDIUM,
buttons);
if (perm.type == "geolocation") {
if (request.type == "geolocation") {
// Add the "learn more" link.
let link = newBar.ownerDocument.createElement("label");
link.setAttribute("value", browserBundle.GetStringFromName("geolocation.learnMore"));

Просмотреть файл

@ -215,8 +215,6 @@
#include "mozilla/dom/XPathEvaluator.h"
#include "nsIDocumentEncoder.h"
#include "nsIStructuredCloneContainer.h"
#include "nsIMutableArray.h"
#include "nsContentPermissionHelper.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -10649,11 +10647,17 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsPointerLockPermissionRequest,
nsIContentPermissionRequest)
NS_IMETHODIMP
nsPointerLockPermissionRequest::GetTypes(nsIArray** aTypes)
nsPointerLockPermissionRequest::GetType(nsACString& aType)
{
return CreatePermissionArray(NS_LITERAL_CSTRING("pointerLock"),
NS_LITERAL_CSTRING("unused"),
aTypes);
aType = "pointerLock";
return NS_OK;
}
NS_IMETHODIMP
nsPointerLockPermissionRequest::GetAccess(nsACString& aAccess)
{
aAccess = "unused";
return NS_OK;
}
NS_IMETHODIMP

Просмотреть файл

@ -302,11 +302,6 @@ this.PermissionsTable = { geolocation: {
privileged: PROMPT_ACTION,
certified: PROMPT_ACTION
},
"video-capture": {
app: PROMPT_ACTION,
privileged: PROMPT_ACTION,
certified: PROMPT_ACTION
},
};
/**

Просмотреть файл

@ -2,155 +2,19 @@
* 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/. */
#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;
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);
@ -162,12 +26,14 @@ nsContentPermissionRequestProxy::~nsContentPermissionRequestProxy()
}
nsresult
nsContentPermissionRequestProxy::Init(const nsTArray<PermissionRequest>& requests,
nsContentPermissionRequestProxy::Init(const nsACString & type,
const nsACString & access,
ContentPermissionRequestParent* parent)
{
NS_ASSERTION(parent, "null parent");
mParent = parent;
mPermissionRequests = requests;
mType = type;
mAccess = access;
nsCOMPtr<nsIContentPermissionPrompt> prompt = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
if (!prompt) {
@ -187,14 +53,17 @@ nsContentPermissionRequestProxy::OnParentDestroyed()
NS_IMPL_ISUPPORTS1(nsContentPermissionRequestProxy, nsIContentPermissionRequest)
NS_IMETHODIMP
nsContentPermissionRequestProxy::GetTypes(nsIArray** aTypes)
nsContentPermissionRequestProxy::GetType(nsACString & aType)
{
nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
if (ConvertPermissionRequestToArray(mPermissionRequests, types)) {
types.forget(aTypes);
return NS_OK;
}
return NS_ERROR_FAILURE;
aType = mType;
return NS_OK;
}
NS_IMETHODIMP
nsContentPermissionRequestProxy::GetAccess(nsACString & aAccess)
{
aAccess = mAccess;
return NS_OK;
}
NS_IMETHODIMP
@ -265,3 +134,55 @@ 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,75 +6,60 @@
#define nsContentPermissionHelper_h
#include "nsIContentPermissionPrompt.h"
#include "nsTArray.h"
#include "nsIMutableArray.h"
#include "nsString.h"
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/PContentPermissionRequestParent.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 ContentPermissionType : public nsIContentPermissionType
class ContentPermissionRequestParent : public PContentPermissionRequestParent
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICONTENTPERMISSIONTYPE
public:
ContentPermissionRequestParent(const nsACString& type,
const nsACString& access,
Element* element,
const IPC::Principal& principal);
virtual ~ContentPermissionRequestParent();
ContentPermissionType(const nsACString& aType, const nsACString& aAccess);
virtual ~ContentPermissionType();
bool IsBeingDestroyed();
protected:
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<Element> mElement;
nsCOMPtr<nsContentPermissionRequestProxy> mProxy;
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 nsTArray<mozilla::dom::PermissionRequest>& requests,
mozilla::dom::ContentPermissionRequestParent* parent);
nsresult Init(const nsACString& type, const nsACString& access, 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;
nsTArray<mozilla::dom::PermissionRequest> mPermissionRequests;
nsCString mType;
nsCString mAccess;
};
#endif // nsContentPermissionHelper_h

Просмотреть файл

@ -49,7 +49,6 @@
#include "nsIStringBundle.h"
#include "nsIDocument.h"
#include <algorithm>
#include "nsContentPermissionHelper.h"
#include "mozilla/dom/DeviceStorageBinding.h"
@ -1696,14 +1695,17 @@ nsDOMDeviceStorageCursor::GetStorageType(nsAString & aType)
}
NS_IMETHODIMP
nsDOMDeviceStorageCursor::GetTypes(nsIArray** aTypes)
nsDOMDeviceStorageCursor::GetType(nsACString & aType)
{
nsCString type;
nsresult rv =
DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, type);
NS_ENSURE_SUCCESS(rv, rv);
return DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType,
aType);
}
return CreatePermissionArray(type, NS_LITERAL_CSTRING("read"), aTypes);
NS_IMETHODIMP
nsDOMDeviceStorageCursor::GetAccess(nsACString & aAccess)
{
aAccess = NS_LITERAL_CSTRING("read");
return NS_OK;
}
NS_IMETHODIMP
@ -2178,10 +2180,8 @@ public:
if (NS_FAILED(rv)) {
return rv;
}
nsTArray<PermissionRequest> permArray;
permArray.AppendElement(PermissionRequest(type, access));
child->SendPContentPermissionRequestConstructor(
this, permArray, IPC::Principal(mPrincipal));
this, type, access, IPC::Principal(mPrincipal));
Sendprompt();
return NS_OK;
@ -2195,23 +2195,26 @@ public:
return NS_OK;
}
NS_IMETHODIMP GetTypes(nsIArray** aTypes)
NS_IMETHOD GetType(nsACString & aType)
{
nsCString type;
nsresult rv =
DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, type);
nsresult rv
= DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType,
aType);
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}
nsCString access;
rv = DeviceStorageTypeChecker::GetAccessForRequest(
DeviceStorageRequestType(mRequestType), access);
NS_IMETHOD GetAccess(nsACString & aAccess)
{
nsresult rv = DeviceStorageTypeChecker::GetAccessForRequest(
DeviceStorageRequestType(mRequestType), aAccess);
if (NS_FAILED(rv)) {
return rv;
}
return CreatePermissionArray(type, access, aTypes);
return NS_OK;
}
NS_IMETHOD GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
@ -3188,10 +3191,8 @@ nsDOMDeviceStorage::EnumerateInternal(const nsAString& aPath,
if (aRv.Failed()) {
return nullptr;
}
nsTArray<PermissionRequest> permArray;
permArray.AppendElement(PermissionRequest(type, NS_LITERAL_CSTRING("read")));
child->SendPContentPermissionRequestConstructor(r,
permArray,
child->SendPContentPermissionRequestConstructor(r, type,
NS_LITERAL_CSTRING("read"),
IPC::Principal(mPrincipal));
r->Sendprompt();

Просмотреть файл

@ -7,13 +7,15 @@
interface nsIPrincipal;
interface nsIDOMWindow;
interface nsIDOMElement;
interface nsIArray;
/**
* Interface provides the request type and its access.
* Interface allows access to a content to request
* permission to perform a privileged operation such as
* geolocation.
*/
[scriptable, builtinclass, uuid(384b6cc4-a66b-4bea-98e0-eb10562a9ba4)]
interface nsIContentPermissionType : nsISupports {
[scriptable, uuid(1de67000-2de8-11e2-81c1-0800200c9a66)]
interface nsIContentPermissionRequest : nsISupports {
/**
* The type of the permission request, such as
* "geolocation".
@ -25,22 +27,8 @@ interface nsIContentPermissionType : 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,7 +16,6 @@ include protocol PIndexedDB;
include DOMTypes;
include JavaScriptTypes;
include URIParams;
include PContentPermission;
using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h";
@ -203,8 +202,10 @@ parent:
* Initiates an asynchronous request for permission for the
* provided principal.
*
* @param aRequests
* The array of permissions to request.
* @param aType
* The type of permission to request.
* @param aAccess
* Access type. "read" for example.
* @param aPrincipal
* The principal of the request.
*
@ -212,7 +213,7 @@ parent:
* principals that can live in the content process should
* provided.
*/
PContentPermissionRequest(PermissionRequest[] aRequests, Principal aPrincipal);
PContentPermissionRequest(nsCString aType, nsCString aAccess, Principal principal);
PContentDialog(uint32_t aType, nsCString aName, nsCString aFeatures,
int32_t[] aIntParams, nsString[] aStringParams);

Просмотреть файл

@ -1,14 +0,0 @@
/* 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

Просмотреть файл

@ -1148,11 +1148,12 @@ TabChild::ArraysToParams(const InfallibleTArray<int>& aIntParams,
#ifdef DEBUG
PContentPermissionRequestChild*
TabChild:: SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
const InfallibleTArray<PermissionRequest>& aRequests,
const nsCString& aType,
const nsCString& aAccess,
const IPC::Principal& aPrincipal)
{
PCOMContentPermissionRequestChild* child = static_cast<PCOMContentPermissionRequestChild*>(aActor);
PContentPermissionRequestChild* request = PBrowserChild::SendPContentPermissionRequestConstructor(aActor, aRequests, aPrincipal);
PContentPermissionRequestChild* request = PBrowserChild::SendPContentPermissionRequestConstructor(aActor, aType, aAccess, aPrincipal);
child->mIPCOpen = true;
return request;
}
@ -2007,8 +2008,7 @@ TabChild::DeallocPContentDialogChild(PContentDialogChild* aDialog)
}
PContentPermissionRequestChild*
TabChild::AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,
const IPC::Principal& aPrincipal)
TabChild::AllocPContentPermissionRequestChild(const nsCString& aType, const nsCString& aAccess, const IPC::Principal&)
{
NS_RUNTIMEABORT("unused");
return nullptr;

Просмотреть файл

@ -269,11 +269,13 @@ public:
#ifdef DEBUG
virtual PContentPermissionRequestChild*
SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
const InfallibleTArray<PermissionRequest>& aRequests,
const nsCString& aType,
const nsCString& aAccess,
const IPC::Principal& aPrincipal);
#endif /* DEBUG */
virtual PContentPermissionRequestChild* AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,
virtual PContentPermissionRequestChild* AllocPContentPermissionRequestChild(const nsCString& aType,
const nsCString& aAccess,
const IPC::Principal& aPrincipal);
virtual bool DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor);

Просмотреть файл

@ -14,7 +14,6 @@
#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"
@ -571,10 +570,9 @@ TabParent::DeallocPDocumentRendererParent(PDocumentRendererParent* actor)
}
PContentPermissionRequestParent*
TabParent::AllocPContentPermissionRequestParent(const InfallibleTArray<PermissionRequest>& aRequests,
const IPC::Principal& aPrincipal)
TabParent::AllocPContentPermissionRequestParent(const nsCString& type, const nsCString& access, const IPC::Principal& principal)
{
return CreateContentPermissionRequestParent(aRequests, mFrameElement, aPrincipal);
return new ContentPermissionRequestParent(type, access, mFrameElement, principal);
}
bool

Просмотреть файл

@ -215,8 +215,7 @@ public:
virtual bool DeallocPDocumentRendererParent(PDocumentRendererParent* actor);
virtual PContentPermissionRequestParent*
AllocPContentPermissionRequestParent(const InfallibleTArray<PermissionRequest>& aRequests,
const IPC::Principal& aPrincipal);
AllocPContentPermissionRequestParent(const nsCString& aType, const nsCString& aAccess, const IPC::Principal& aPrincipal);
virtual bool DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor);
virtual POfflineCacheUpdateParent* AllocPOfflineCacheUpdateParent(

Просмотреть файл

@ -64,7 +64,6 @@ IPDL_SOURCES += [
'PBrowser.ipdl',
'PContent.ipdl',
'PContentDialog.ipdl',
'PContentPermission.ipdlh',
'PContentPermissionRequest.ipdl',
'PCrashReporter.ipdl',
'PDocumentRenderer.ipdl',

Просмотреть файл

@ -43,7 +43,7 @@
#include "MediaEngineWebRTC.h"
#endif
#ifdef MOZ_B2G
#ifdef MOZ_WIDGET_GONK
#include "MediaPermissionGonk.h"
#endif
@ -810,6 +810,7 @@ public:
, mListener(aListener)
, mPrefs(aPrefs)
, mDeviceChosen(false)
, mBackendChosen(false)
, mManager(MediaManager::GetInstance())
{}
@ -831,11 +832,15 @@ public:
, mListener(aListener)
, mPrefs(aPrefs)
, mDeviceChosen(false)
, mBackendChosen(true)
, mBackend(aBackend)
, mManager(MediaManager::GetInstance())
{}
~GetUserMediaRunnable() {
if (mBackendChosen) {
delete mBackend;
}
}
NS_IMETHOD
@ -843,7 +848,10 @@ public:
{
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
mBackend = mManager->GetBackend(mWindowID);
// Was a backend provided?
if (!mBackendChosen) {
mBackend = mManager->GetBackend(mWindowID);
}
// Was a device provided?
if (!mDeviceChosen) {
@ -1030,6 +1038,7 @@ private:
MediaEnginePrefs mPrefs;
bool mDeviceChosen;
bool mBackendChosen;
MediaEngine* mBackend;
nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
@ -1247,10 +1256,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_B2G
#ifdef MOZ_WIDGET_GONK
// Initialize MediaPermissionManager before send out any permission request.
(void) MediaPermissionManager::GetInstance();
#endif //MOZ_B2G
#endif //MOZ_WIDGET_GONK
}
// Store the WindowID in a hash table and mark as active. The entry is removed
@ -1302,7 +1311,7 @@ MediaManager::GetUserMedia(JSContext* aCx, bool aPrivileged,
if (c.mFake) {
// Fake stream from default backend.
gUMRunnable = new GetUserMediaRunnable(c, onSuccess.forget(),
onError.forget(), windowID, listener, mPrefs, GetBackend(windowID, true));
onError.forget(), windowID, listener, mPrefs, new MediaEngineDefault());
} else {
// Stream from default device from WebRTC backend.
gUMRunnable = new GetUserMediaRunnable(c, onSuccess.forget(),
@ -1383,26 +1392,22 @@ MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
}
MediaEngine*
MediaManager::GetBackend(uint64_t aWindowId, bool aFake)
MediaManager::GetBackend(uint64_t aWindowId)
{
// Plugin backends as appropriate. The default engine also currently
// includes picture support for Android.
// This IS called off main-thread.
MutexAutoLock lock(mMutex);
if (!mBackend) {
if (aFake) {
mBackend = new MediaEngineDefault();
} else {
#if defined(MOZ_WEBRTC)
#ifndef MOZ_B2G_CAMERA
mBackend = new MediaEngineWebRTC();
#ifndef MOZ_B2G_CAMERA
mBackend = new MediaEngineWebRTC();
#else
mBackend = new MediaEngineWebRTC(mCameraManager, aWindowId);
#endif
#else
mBackend = new MediaEngineWebRTC(mCameraManager, aWindowId);
mBackend = new MediaEngineDefault();
#endif
#else
mBackend = new MediaEngineDefault();
#endif
}
}
return mBackend;
}

Просмотреть файл

@ -405,7 +405,7 @@ public:
NS_DECL_NSIOBSERVER
NS_DECL_NSIMEDIAMANAGERSERVICE
MediaEngine* GetBackend(uint64_t aWindowId = 0, bool aFake = false);
MediaEngine* GetBackend(uint64_t aWindowId = 0);
StreamListeners *GetWindowListeners(uint64_t aWindowId) {
NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
@ -469,7 +469,7 @@ private:
static StaticRefPtr<MediaManager> sSingleton;
#ifdef MOZ_B2G_CAMERA
#ifdef MOZ_WIDGET_GONK
nsRefPtr<nsDOMCameraManager> mCameraManager;
#endif
};

Просмотреть файл

@ -20,36 +20,14 @@
#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)
@ -115,7 +93,6 @@ 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
};
@ -131,7 +108,6 @@ 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]);
@ -140,34 +116,10 @@ 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)
{
@ -183,6 +135,24 @@ 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)
{
@ -308,12 +278,13 @@ MediaDeviceSuccessCallback::DoPrompt(nsRefPtr<MediaPermissionRequest> &req)
dom::TabChild* child = dom::TabChild::GetFrom(window->GetDocShell());
NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
nsCOMPtr<nsIArray> typeArray;
rv = req->GetTypes(getter_AddRefs(typeArray));
nsAutoCString type;
rv = req->GetType(type);
NS_ENSURE_SUCCESS(rv, rv);
nsTArray<PermissionRequest> permArray;
ConvertArrayToPermissionRequest(typeArray, permArray);
nsAutoCString access;
rv = req->GetAccess(access);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> principal;
rv = req->GetPrincipal(getter_AddRefs(principal));
@ -321,7 +292,8 @@ MediaDeviceSuccessCallback::DoPrompt(nsRefPtr<MediaPermissionRequest> &req)
req->AddRef();
child->SendPContentPermissionRequestConstructor(req,
permArray,
type,
access,
IPC::Principal(principal));
req->Sendprompt();

Просмотреть файл

@ -7,9 +7,3 @@ ifdef MOZ_WEBRTC_LEAKING_TESTS
MOCHITEST_FILES += \
$(NULL)
endif
ifdef MOZ_B2G_CAMERA
MOCHITEST_FILES += \
test_getUserMedia_permission.html \
$(NULL)
endif

Просмотреть файл

@ -1,77 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=853356
-->
<head>
<meta charset="utf-8">
<title>mozGetUserMedia Permission Test</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=853356">Display camera/microphone permission acquisition prompt</a>
<script type="application/javascript">
var MockPermissionPrompt = SpecialPowers.MockPermissionPrompt;
MockPermissionPrompt.init();
var gCount = 0;
var gTests = [
{
constraints: {video: true, audio: false}
}
,
{
constraints: {video: false, audio: true}
}
,
{
constraints: {video: true, audio: true},
}
];
function gUM(data) {
var gum_success = function (stream) {
SimpleTest.info("TEST-INFO | Got succss callback for " + JSON.stringify(data.constraints));
var hasAudioTrack = stream.getAudioTracks().length > 0;
var hasVideoTrack = stream.getVideoTracks().length > 0;
is(data.constraints.audio, hasAudioTrack, "Request audio track:" +
data.constraints.audio + " contain audio track:" + hasAudioTrack);
is(data.constraints.video, hasVideoTrack, "Request video track:" +
data.constraints.video + " contain audio track:" + hasVideoTrack);
gCount++;
if (gCount < gTests.length) {
gUM(gTests[gCount]);
} else {
SimpleTest.finish();
}
}
var gum_fail = function () {
ok(false, "permission not granted for " + JSON.stringify(data.constraints));
SimpleTest.finish();
}
SimpleTest.info("TEST-INFO | Call getUserMedia for " + JSON.stringify(data.constraints));
navigator.mozGetUserMedia(data.constraints, gum_success, gum_fail);
}
SpecialPowers.pushPrefEnv({"set": [["media.navigator.permission.disabled", false]]},
function () {
SpecialPowers.addPermission('video-capture',
Ci.nsIPermissionManager.ALLOW_ACTION, document);
SpecialPowers.addPermission('audio-capture',
Ci.nsIPermissionManager.ALLOW_ACTION, document);
gUM(gTests[gCount]);
});
SimpleTest.waitForExplicitFinish();
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -15,7 +15,6 @@
#include "nsServiceManagerUtils.h"
#include "nsContentUtils.h"
#include "nsCxPusher.h"
#include "nsContentPermissionHelper.h"
#include "nsIDocument.h"
#include "nsIObserverService.h"
#include "nsPIDOMWindow.h"
@ -386,11 +385,17 @@ nsGeolocationRequest::GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
}
NS_IMETHODIMP
nsGeolocationRequest::GetTypes(nsIArray** aTypes)
nsGeolocationRequest::GetType(nsACString & aType)
{
return CreatePermissionArray(NS_LITERAL_CSTRING("geolocation"),
NS_LITERAL_CSTRING("unused"),
aTypes);
aType = "geolocation";
return NS_OK;
}
NS_IMETHODIMP
nsGeolocationRequest::GetAccess(nsACString & aAccess)
{
aAccess = "unused";
return NS_OK;
}
NS_IMETHODIMP
@ -1447,15 +1452,12 @@ 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,
permArray,
NS_LITERAL_CSTRING("geolocation"),
NS_LITERAL_CSTRING("unused"),
IPC::Principal(mPrincipal));
request->Sendprompt();

Просмотреть файл

@ -15,7 +15,6 @@
#include "PCOMContentPermissionRequestChild.h"
#include "nsIScriptSecurityManager.h"
#include "nsServiceManagerUtils.h"
#include "PermissionMessageUtils.h"
namespace mozilla {
namespace dom {
@ -178,12 +177,9 @@ 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(),
permArray,
NS_LITERAL_CSTRING("desktop-notification"),
NS_LITERAL_CSTRING("unused"),
IPC::Principal(mPrincipal));
request->Sendprompt();
@ -355,11 +351,17 @@ DesktopNotificationRequest::Allow()
}
NS_IMETHODIMP
DesktopNotificationRequest::GetTypes(nsIArray** aTypes)
DesktopNotificationRequest::GetType(nsACString & aType)
{
return CreatePermissionArray(NS_LITERAL_CSTRING("desktop-notification"),
NS_LITERAL_CSTRING("unused"),
aTypes);
aType = "desktop-notification";
return NS_OK;
}
NS_IMETHODIMP
DesktopNotificationRequest::GetAccess(nsACString & aAccess)
{
aAccess = "unused";
return NS_OK;
}
} // namespace dom

Просмотреть файл

@ -24,7 +24,6 @@
#include "nsDOMJSUtils.h"
#include "nsIScriptSecurityManager.h"
#include "mozilla/dom/PermissionMessageUtils.h"
#include "nsContentPermissionHelper.h"
#ifdef MOZ_B2G
#include "nsIDOMDesktopNotification.h"
#endif
@ -268,11 +267,9 @@ NotificationPermissionRequest::Run()
// Corresponding release occurs in DeallocPContentPermissionRequest.
AddRef();
nsTArray<PermissionRequest> permArray;
permArray.AppendElement(PermissionRequest(
NS_LITERAL_CSTRING("desktop-notification"),
NS_LITERAL_CSTRING("unused")));
child->SendPContentPermissionRequestConstructor(this, permArray,
NS_NAMED_LITERAL_CSTRING(type, "desktop-notification");
NS_NAMED_LITERAL_CSTRING(access, "unused");
child->SendPContentPermissionRequestConstructor(this, type, access,
IPC::Principal(mPrincipal));
Sendprompt();
@ -345,11 +342,17 @@ NotificationPermissionRequest::CallCallback()
}
NS_IMETHODIMP
NotificationPermissionRequest::GetTypes(nsIArray** aTypes)
NotificationPermissionRequest::GetAccess(nsACString& aAccess)
{
return CreatePermissionArray(NS_LITERAL_CSTRING("desktop-notification"),
NS_LITERAL_CSTRING("unused"),
aTypes);
aAccess.AssignLiteral("unused");
return NS_OK;
}
NS_IMETHODIMP
NotificationPermissionRequest::GetType(nsACString& aType)
{
aType.AssignLiteral("desktop-notification");
return NS_OK;
}
bool

Просмотреть файл

@ -21,8 +21,8 @@ ContentPermissionPrompt.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionPrompt]),
handleExistingPermission: function handleExistingPermission(request, type, isApp) {
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, type);
handleExistingPermission: function handleExistingPermission(request, isApp) {
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, request.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[type])) {
if (isApp && (result == Ci.nsIPermissionManager.UNKNOWN_ACTION && !!kEntities[request.type])) {
request.cancel();
return true;
}
@ -62,16 +62,8 @@ 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, perm.type, isApp))
if (this.handleExistingPermission(request, isApp))
return;
let chromeWin = this.getChromeForRequest(request);
@ -80,17 +72,17 @@ ContentPermissionPrompt.prototype = {
return;
let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
let entityName = kEntities[perm.type];
let entityName = kEntities[request.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, perm.type, Ci.nsIPermissionManager.ALLOW_ACTION);
Services.perms.addFromPrincipal(request.principal, request.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, perm.type, Ci.nsIPermissionManager.ALLOW_ACTION, Ci.nsIPermissionManager.EXPIRE_SESSION);
Services.perms.addFromPrincipal(request.principal, request.type, Ci.nsIPermissionManager.ALLOW_ACTION, Ci.nsIPermissionManager.EXPIRE_SESSION);
}
request.allow();
@ -101,7 +93,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, perm.type, Ci.nsIPermissionManager.DENY_ACTION);
Services.perms.addFromPrincipal(request.principal, request.type, Ci.nsIPermissionManager.DENY_ACTION);
request.cancel();
}

Просмотреть файл

@ -34,18 +34,9 @@ this.MockPermissionPrompt = {
init: function() {
this.reset();
if (!registrar.isCIDRegistered(newClassID)) {
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 != "" && oldFactory != null) {
registrar.unregisterFactory(oldClassID, oldFactory);
}
oldClassID = registrar.contractIDToCID(CONTRACT_ID);
oldFactory = Cm.getClassObject(Cc[CONTRACT_ID], Ci.nsIFactory);
registrar.unregisterFactory(oldClassID, oldFactory);
registrar.registerFactory(newClassID, "", CONTRACT_ID, newFactory);
}
},
@ -70,17 +61,14 @@ MockPermissionPromptInstance.prototype = {
prompt: function(request) {
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;
}
this.promptResult = Services.perms.testExactPermissionFromPrincipal(request.principal,
request.type);
if (this.promptResult == Ci.nsIPermissionManager.ALLOW_ACTION) {
request.allow();
}
else {
request.cancel();
}
request.allow();
}
};

Просмотреть файл

@ -30,25 +30,17 @@ 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,
perm.type);
request.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) &&
perm.type == "geolocation") {
request.type == "geolocation") {
let geoResult = Services.perms.testExactPermission(request.principal.URI,
"geo");
// We override the result only if the "geo" permission was allowed or
@ -64,7 +56,7 @@ ContentPermission.prototype = {
return;
} else if (result == Ci.nsIPermissionManager.DENY_ACTION ||
(result == Ci.nsIPermissionManager.UNKNOWN_ACTION &&
UNKNOWN_FAIL.indexOf(perm.type) >= 0)) {
UNKNOWN_FAIL.indexOf(request.type) >= 0)) {
request.cancel();
return;
}
@ -79,16 +71,16 @@ ContentPermission.prototype = {
let remember = {value: false};
let choice = Services.prompt.confirmEx(
chromeWin,
bundle.formatStringFromName(perm.type + ".title", [name], 1),
bundle.GetStringFromName(perm.type + ".description"),
bundle.formatStringFromName(request.type + ".title", [name], 1),
bundle.GetStringFromName(request.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(perm.type + ".allow"),
bundle.GetStringFromName(perm.type + ".deny"),
bundle.GetStringFromName(request.type + ".allow"),
bundle.GetStringFromName(request.type + ".deny"),
null,
bundle.GetStringFromName(perm.type + ".remember"),
bundle.GetStringFromName(request.type + ".remember"),
remember);
let action = Ci.nsIPermissionManager.ALLOW_ACTION;
@ -98,10 +90,10 @@ ContentPermission.prototype = {
if (remember.value) {
// Persist the choice if the user wants to remember
Services.perms.addFromPrincipal(request.principal, perm.type, action);
Services.perms.addFromPrincipal(request.principal, request.type, action);
} else {
// Otherwise allow the permission for the current session
Services.perms.addFromPrincipal(request.principal, perm.type, action,
Services.perms.addFromPrincipal(request.principal, request.type, action,
Ci.nsIPermissionManager.EXPIRE_SESSION);
}