mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge b2g-inbound to mozilla-central
This commit is contained in:
commit
81e43584e3
@ -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;
|
||||
// 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(perm + "-" + access[idx], aPrincipal);
|
||||
convertPermToAllow(aPermission + "-" + access[idx], aPrincipal);
|
||||
}
|
||||
} else {
|
||||
convertPermToAllow(perm, aPrincipal);
|
||||
}
|
||||
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,
|
||||
let principal = secMan.getAppCodebasePrincipal(url, request.principal.appId,
|
||||
/*mozbrowser*/false);
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(principal,
|
||||
type.access);
|
||||
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 false;
|
||||
}
|
||||
return type.deny;
|
||||
}
|
||||
if (typesInfo.every(checkIfDenyAppPrincipal)) {
|
||||
|
||||
request.cancel();
|
||||
return true;
|
||||
}
|
||||
|
||||
return 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;
|
||||
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,
|
||||
Services.perms.addFromPrincipal(principal, access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION);
|
||||
} else {
|
||||
Services.perms.addFromPrincipal(request.principal, type.access,
|
||||
Services.perms.addFromPrincipal(principal, access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION,
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION,
|
||||
0);
|
||||
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]);
|
||||
|
@ -1,12 +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/. */
|
||||
|
||||
#include "domstubs.idl"
|
||||
|
||||
[scriptable, uuid(3615a616-571d-4194-bf54-ccf546067b14)]
|
||||
interface nsIB2GCameraContent : nsISupports
|
||||
{
|
||||
/* temporary solution, waiting for getUserMedia */
|
||||
DOMString getCameraURI([optional] in jsval options);
|
||||
};
|
@ -6,10 +6,6 @@
|
||||
|
||||
TEST_DIRS += ['test']
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'b2g.idl',
|
||||
]
|
||||
|
||||
MODULE = 'B2GComponents'
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "fe012cdbca542f414a72b0cba9cfb50a4aaf62ae",
|
||||
"revision": "5cc807be4ece02c364c1d7f1cd2becbe1a1b441e",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -749,8 +749,6 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
|
||||
@BINPATH@/chrome/chrome@JAREXT@
|
||||
@BINPATH@/chrome/chrome.manifest
|
||||
@BINPATH@/components/B2GComponents.manifest
|
||||
@BINPATH@/components/B2GComponents.xpt
|
||||
@BINPATH@/components/CameraContent.js
|
||||
@BINPATH@/@DLL_PREFIX@omxplugin@DLL_SUFFIX@
|
||||
#ifdef ENABLE_MARIONETTE
|
||||
@BINPATH@/chrome/marionette@JAREXT@
|
||||
|
@ -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);
|
||||
aType = mType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsContentPermissionRequestProxy::GetAccess(nsACString & aAccess)
|
||||
{
|
||||
aAccess = mAccess;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
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,54 +6,39 @@
|
||||
#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
|
||||
|
||||
ContentPermissionType(const nsACString& aType, const nsACString& aAccess);
|
||||
virtual ~ContentPermissionType();
|
||||
|
||||
protected:
|
||||
nsCString mType;
|
||||
nsCString mAccess;
|
||||
};
|
||||
|
||||
uint32_t ConvertPermissionRequestToArray(nsTArray<PermissionRequest>& aSrcArray,
|
||||
nsIMutableArray* aDesArray);
|
||||
|
||||
nsresult CreatePermissionArray(const nsACString& aType,
|
||||
const nsACString& aAccess,
|
||||
nsIArray** aTypesArray);
|
||||
|
||||
PContentPermissionRequestParent*
|
||||
CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
|
||||
public:
|
||||
ContentPermissionRequestParent(const nsACString& type,
|
||||
const nsACString& access,
|
||||
Element* element,
|
||||
const IPC::Principal& principal);
|
||||
virtual ~ContentPermissionRequestParent();
|
||||
|
||||
bool IsBeingDestroyed();
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<Element> mElement;
|
||||
nsCOMPtr<nsContentPermissionRequestProxy> mProxy;
|
||||
nsCString mType;
|
||||
nsCString mAccess;
|
||||
|
||||
private:
|
||||
virtual bool Recvprompt();
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@ -61,20 +46,20 @@ CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequest
|
||||
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");
|
||||
|
||||
// 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,27 +1392,23 @@ 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
|
||||
#ifndef MOZ_B2G_CAMERA
|
||||
mBackend = new MediaEngineWebRTC();
|
||||
#else
|
||||
#else
|
||||
mBackend = new MediaEngineWebRTC(mCameraManager, aWindowId);
|
||||
#endif
|
||||
#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>
|
@ -11,7 +11,7 @@ interface nsIDOMDOMCursor;
|
||||
interface nsIDOMDOMRequest;
|
||||
interface nsIDOMBlob;
|
||||
|
||||
[scriptable, builtinclass, uuid(0e4ff35e-ab84-434a-96b4-46807798cc7e)]
|
||||
[scriptable, builtinclass, uuid(cfcc7067-083f-4e09-91aa-75067a721b70)]
|
||||
interface nsIDOMMozMobileMessageManager : nsIDOMEventTarget
|
||||
{
|
||||
nsIDOMDOMRequest getSegmentInfoForText(in DOMString text);
|
||||
@ -65,6 +65,9 @@ interface nsIDOMMozMobileMessageManager : nsIDOMEventTarget
|
||||
|
||||
nsIDOMDOMRequest retrieveMMS(in long id);
|
||||
|
||||
[optional_argc]
|
||||
nsIDOMDOMRequest getSmscAddress([optional] in unsigned long serviceId);
|
||||
|
||||
[implicit_jscontext] attribute jsval onreceived;
|
||||
[implicit_jscontext] attribute jsval onretrieving;
|
||||
[implicit_jscontext] attribute jsval onsending;
|
||||
|
@ -19,9 +19,11 @@ dictionary MmsDeliveryInfo
|
||||
{
|
||||
DOMString? receiver;
|
||||
DOMString? deliveryStatus;
|
||||
jsval deliveryTimestamp; // Date object; null if not available (e.g.,
|
||||
// |delivery| = "received" or not yet delivered).
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(85bfc639-0d8f-43fa-8c12-6bd2958bf219)]
|
||||
[scriptable, builtinclass, uuid(3593c914-420a-11e3-a297-a3bdd768257f)]
|
||||
interface nsIDOMMozMmsMessage : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -14,7 +14,7 @@ dictionary SmsThreadListItem
|
||||
unsigned long long unreadCount;
|
||||
};
|
||||
|
||||
[scriptable, uuid(58780660-4080-11e3-8397-a7bb1b58cf12)]
|
||||
[scriptable, uuid(0ee2ada1-fa98-40f1-adb3-0d7fd6df3f48)]
|
||||
interface nsIMobileMessageCallback : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -54,4 +54,10 @@ interface nsIMobileMessageCallback : nsISupports
|
||||
|
||||
void notifySegmentInfoForTextGot(in nsIDOMMozSmsSegmentInfo info);
|
||||
void notifyGetSegmentInfoForTextFailed(in long error);
|
||||
|
||||
/**
|
||||
* SMSC Address get/set result
|
||||
*/
|
||||
void notifyGetSmscAddress(in DOMString aSmscAddress);
|
||||
void notifyGetSmscAddressFailed(in long error);
|
||||
};
|
||||
|
@ -13,7 +13,7 @@ interface nsIMobileMessageCallback;
|
||||
#define SMS_SERVICE_CONTRACTID "@mozilla.org/sms/smsservice;1"
|
||||
%}
|
||||
|
||||
[scriptable, builtinclass, uuid(6ac68d50-3d60-11e3-a8ff-ab5ddef5f2ba)]
|
||||
[scriptable, builtinclass, uuid(0a28f55b-95fe-4b32-994f-b08fe8edf77a)]
|
||||
interface nsISmsService : nsISupports
|
||||
{
|
||||
readonly attribute unsigned long smsDefaultServiceId;
|
||||
@ -32,4 +32,7 @@ interface nsISmsService : nsISupports
|
||||
boolean isSilentNumber(in DOMString number);
|
||||
void addSilentNumber(in DOMString number);
|
||||
void removeSilentNumber(in DOMString number);
|
||||
|
||||
void getSmscAddress(in unsigned long serviceId,
|
||||
in nsIMobileMessageCallback request);
|
||||
};
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "mozilla/dom/mobilemessage/Constants.h" // For MessageType
|
||||
#include "mozilla/dom/mobilemessage/SmsTypes.h"
|
||||
#include "nsDOMFile.h"
|
||||
#include "nsCxPusher.h"
|
||||
|
||||
using namespace mozilla::idl;
|
||||
using namespace mozilla::dom::mobilemessage;
|
||||
@ -100,8 +101,11 @@ MmsMessage::MmsMessage(const mobilemessage::MmsMessageData& aData)
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
MmsDeliveryInfo info;
|
||||
const MmsDeliveryInfoData &infoData = aData.deliveryInfo()[i];
|
||||
|
||||
// Prepare |info.receiver|.
|
||||
info.receiver = infoData.receiver();
|
||||
|
||||
// Prepare |info.deliveryStatus|.
|
||||
nsString statusStr;
|
||||
switch (infoData.deliveryStatus()) {
|
||||
case eDeliveryStatus_NotApplicable:
|
||||
@ -127,6 +131,20 @@ MmsMessage::MmsMessage(const mobilemessage::MmsMessageData& aData)
|
||||
MOZ_CRASH("We shouldn't get any other delivery status!");
|
||||
}
|
||||
info.deliveryStatus = statusStr;
|
||||
|
||||
// Prepare |info.deliveryTimestamp|.
|
||||
info.deliveryTimestamp = JSVAL_NULL;
|
||||
if (infoData.deliveryTimestamp() != 0) {
|
||||
AutoJSContext cx;
|
||||
JS::Rooted<JSObject*>
|
||||
dateObj(cx, JS_NewDateObjectMsec(cx, infoData.deliveryTimestamp()));
|
||||
if (!dateObj) {
|
||||
NS_WARNING("MmsMessage: Unable to create Date for deliveryTimestamp.");
|
||||
} else {
|
||||
info.deliveryTimestamp = OBJECT_TO_JSVAL(dateObj);
|
||||
}
|
||||
}
|
||||
|
||||
mDeliveryInfo.AppendElement(info);
|
||||
}
|
||||
}
|
||||
@ -327,8 +345,11 @@ MmsMessage::GetData(ContentParent* aParent,
|
||||
for (uint32_t i = 0; i < mDeliveryInfo.Length(); i++) {
|
||||
MmsDeliveryInfoData infoData;
|
||||
const MmsDeliveryInfo &info = mDeliveryInfo[i];
|
||||
|
||||
// Prepare |infoData.receiver|.
|
||||
infoData.receiver().Assign(info.receiver);
|
||||
|
||||
// Prepare |infoData.deliveryStatus|.
|
||||
DeliveryStatus status;
|
||||
if (info.deliveryStatus.Equals(DELIVERY_STATUS_NOT_APPLICABLE)) {
|
||||
status = eDeliveryStatus_NotApplicable;
|
||||
@ -346,6 +367,15 @@ MmsMessage::GetData(ContentParent* aParent,
|
||||
return false;
|
||||
}
|
||||
infoData.deliveryStatus() = status;
|
||||
|
||||
// Prepare |infoData.deliveryTimestamp|.
|
||||
if (info.deliveryTimestamp == JSVAL_NULL) {
|
||||
infoData.deliveryTimestamp() = 0;
|
||||
} else {
|
||||
AutoJSContext cx;
|
||||
convertTimeToInt(cx, info.deliveryTimestamp, infoData.deliveryTimestamp());
|
||||
}
|
||||
|
||||
aData.deliveryInfo().AppendElement(infoData);
|
||||
}
|
||||
|
||||
@ -484,6 +514,13 @@ MmsMessage::GetDeliveryInfo(JSContext* aCx, JS::Value* aDeliveryInfo)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Get |info.deliveryTimestamp|.
|
||||
if (!JS_DefineProperty(aCx, infoJsObj,
|
||||
"deliveryTimestamp", info.deliveryTimestamp,
|
||||
NULL, NULL, JSPROP_ENUMERATE)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
tmpJsVal = OBJECT_TO_JSVAL(infoJsObj);
|
||||
if (!JS_SetElement(aCx, deliveryInfo, i, &tmpJsVal)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -210,6 +210,28 @@ MobileMessageCallback::NotifyGetSegmentInfoForTextFailed(int32_t aError)
|
||||
return NotifyError(aError, true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MobileMessageCallback::NotifyGetSmscAddress(const nsAString& aSmscAddress)
|
||||
{
|
||||
AutoJSContext cx;
|
||||
JSString* smsc = JS_NewUCStringCopyN(cx,
|
||||
static_cast<const jschar *>(aSmscAddress.BeginReading()),
|
||||
aSmscAddress.Length());
|
||||
|
||||
if (!smsc) {
|
||||
return NotifyError(nsIMobileMessageCallback::INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> val(cx, STRING_TO_JSVAL(smsc));
|
||||
return NotifySuccess(val);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MobileMessageCallback::NotifyGetSmscAddressFailed(int32_t aError)
|
||||
{
|
||||
return NotifyError(aError);
|
||||
}
|
||||
|
||||
} // namesapce mobilemessage
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -525,5 +525,27 @@ MobileMessageManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MobileMessageManager::GetSmscAddress(uint32_t aServiceId, uint8_t aArgc,
|
||||
nsIDOMDOMRequest** aRequest)
|
||||
{
|
||||
nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(smsService, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv;
|
||||
if (aArgc != 1) {
|
||||
rv = smsService->GetSmsDefaultServiceId(&aServiceId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner());
|
||||
nsCOMPtr<nsIMobileMessageCallback> msgCallback = new MobileMessageCallback(request);
|
||||
rv = smsService->GetSmscAddress(aServiceId, msgCallback);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
request.forget(aRequest);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -80,6 +80,14 @@ SmsService::RemoveSilentNumber(const nsAString& aNumber)
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsService::GetSmscAddress(uint32_t aServiceId,
|
||||
nsIMobileMessageCallback *aRequest)
|
||||
{
|
||||
// TODO: bug 878016 - Android backend: implement getSMSCAddress/setSMSCAddress
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace mobilemessage
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -68,6 +68,14 @@ SmsService::RemoveSilentNumber(const nsAString& aNumber)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsService::GetSmscAddress(uint32_t aServiceId,
|
||||
nsIMobileMessageCallback *aRequest)
|
||||
{
|
||||
NS_ERROR("We should not be here!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace mobilemessage
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -1588,7 +1588,7 @@ MobileMessageDatabaseService.prototype = {
|
||||
if (messageRecord.deliveryStatus != deliveryStatus) {
|
||||
messageRecord.deliveryStatus = deliveryStatus;
|
||||
|
||||
// Update the delivery timestamp if it's successfully delivered.
|
||||
// Update |deliveryTimestamp| if it's successfully delivered.
|
||||
if (deliveryStatus == DELIVERY_STATUS_SUCCESS) {
|
||||
messageRecord.deliveryTimestamp = Date.now();
|
||||
}
|
||||
@ -1601,6 +1601,12 @@ MobileMessageDatabaseService.prototype = {
|
||||
for (let i = 0; i < deliveryInfo.length; i++) {
|
||||
if (deliveryInfo[i].deliveryStatus != deliveryStatus) {
|
||||
deliveryInfo[i].deliveryStatus = deliveryStatus;
|
||||
|
||||
// Update |deliveryTimestamp| if it's successfully delivered.
|
||||
if (deliveryStatus == DELIVERY_STATUS_SUCCESS) {
|
||||
deliveryInfo[i].deliveryTimestamp = Date.now();
|
||||
}
|
||||
|
||||
isRecordUpdated = true;
|
||||
}
|
||||
}
|
||||
@ -1655,6 +1661,12 @@ MobileMessageDatabaseService.prototype = {
|
||||
}
|
||||
if (deliveryInfo[j].deliveryStatus != deliveryStatus) {
|
||||
deliveryInfo[j].deliveryStatus = deliveryStatus;
|
||||
|
||||
// Update |deliveryTimestamp| if it's successfully delivered.
|
||||
if (deliveryStatus == DELIVERY_STATUS_SUCCESS) {
|
||||
deliveryInfo[j].deliveryTimestamp = Date.now();
|
||||
}
|
||||
|
||||
isRecordUpdated = true;
|
||||
}
|
||||
}
|
||||
@ -1765,6 +1777,14 @@ MobileMessageDatabaseService.prototype = {
|
||||
if (aMessage.type == "mms") {
|
||||
aMessage.transactionIdIndex = aMessage.transactionId;
|
||||
aMessage.isReadReportSent = false;
|
||||
|
||||
// If |deliveryTimestamp| is not specified, use 0 as default.
|
||||
let deliveryInfo = aMessage.deliveryInfo;
|
||||
for (let i = 0; i < deliveryInfo.length; i++) {
|
||||
if (deliveryInfo[i].deliveryTimestamp == undefined) {
|
||||
deliveryInfo[i].deliveryTimestamp = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aMessage.type == "sms") {
|
||||
@ -1818,7 +1838,9 @@ MobileMessageDatabaseService.prototype = {
|
||||
aMessage.deliveryInfo = [];
|
||||
for (let i = 0; i < receivers.length; i++) {
|
||||
aMessage.deliveryInfo.push({
|
||||
receiver: receivers[i], deliveryStatus: deliveryStatus });
|
||||
receiver: receivers[i],
|
||||
deliveryStatus: deliveryStatus,
|
||||
deliveryTimestamp: 0 });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,6 +149,19 @@ SmsService::RemoveSilentNumber(const nsAString& aNumber)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsService::GetSmscAddress(uint32_t aServiceId,
|
||||
nsIMobileMessageCallback *aRequest)
|
||||
{
|
||||
nsCOMPtr<nsIRadioInterface> radioInterface;
|
||||
if (mRil) {
|
||||
mRil->GetRadioInterface(aServiceId, getter_AddRefs(radioInterface));
|
||||
}
|
||||
NS_ENSURE_TRUE(radioInterface, NS_ERROR_FAILURE);
|
||||
|
||||
return radioInterface->GetSmscAddress(aRequest);
|
||||
}
|
||||
|
||||
} // namespace mobilemessage
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -74,6 +74,11 @@ struct CreateThreadCursorRequest
|
||||
{
|
||||
};
|
||||
|
||||
struct GetSmscAddressRequest
|
||||
{
|
||||
uint32_t serviceId;
|
||||
};
|
||||
|
||||
union IPCSmsRequest
|
||||
{
|
||||
SendMessageRequest;
|
||||
@ -82,6 +87,7 @@ union IPCSmsRequest
|
||||
DeleteMessageRequest;
|
||||
MarkMessageReadRequest;
|
||||
GetSegmentInfoForTextRequest;
|
||||
GetSmscAddressRequest;
|
||||
};
|
||||
|
||||
union IPCMobileMessageCursor
|
||||
|
@ -73,6 +73,16 @@ struct ReplyGetSegmentInfoForTextFail
|
||||
int32_t error;
|
||||
};
|
||||
|
||||
struct ReplyGetSmscAddress
|
||||
{
|
||||
nsString smscAddress;
|
||||
};
|
||||
|
||||
struct ReplyGetSmscAddressFail
|
||||
{
|
||||
int32_t error;
|
||||
};
|
||||
|
||||
union MessageReply
|
||||
{
|
||||
ReplyMessageSend;
|
||||
@ -85,6 +95,8 @@ union MessageReply
|
||||
ReplyMarkeMessageReadFail;
|
||||
ReplyGetSegmentInfoForText;
|
||||
ReplyGetSegmentInfoForTextFail;
|
||||
ReplyGetSmscAddress;
|
||||
ReplyGetSmscAddressFail;
|
||||
};
|
||||
|
||||
} // namespace mobilemessage
|
||||
|
@ -216,6 +216,12 @@ SmsRequestChild::Recv__delete__(const MessageReply& aReply)
|
||||
mReplyRequest->NotifyGetSegmentInfoForTextFailed(
|
||||
aReply.get_ReplyGetSegmentInfoForTextFail().error());
|
||||
break;
|
||||
case MessageReply::TReplyGetSmscAddress:
|
||||
mReplyRequest->NotifyGetSmscAddress(aReply.get_ReplyGetSmscAddress().smscAddress());
|
||||
break;
|
||||
case MessageReply::TReplyGetSmscAddressFail:
|
||||
mReplyRequest->NotifyGetSmscAddressFailed(aReply.get_ReplyGetSmscAddressFail().error());
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Received invalid response parameters!");
|
||||
}
|
||||
|
@ -166,6 +166,13 @@ SmsIPCService::GetSegmentInfoForText(const nsAString& aText,
|
||||
aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsIPCService::GetSmscAddress(uint32_t aServiceId,
|
||||
nsIMobileMessageCallback* aRequest)
|
||||
{
|
||||
return SendRequest(GetSmscAddressRequest(aServiceId), aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsIPCService::Send(uint32_t aServiceId,
|
||||
const nsAString& aNumber,
|
||||
|
31
dom/mobilemessage/src/ipc/SmsParent.cpp
Executable file → Normal file
31
dom/mobilemessage/src/ipc/SmsParent.cpp
Executable file → Normal file
@ -367,6 +367,8 @@ SmsParent::RecvPSmsRequestConstructor(PSmsRequestParent* aActor,
|
||||
return actor->DoRequest(aRequest.get_MarkMessageReadRequest());
|
||||
case IPCSmsRequest::TGetSegmentInfoForTextRequest:
|
||||
return actor->DoRequest(aRequest.get_GetSegmentInfoForTextRequest());
|
||||
case IPCSmsRequest::TGetSmscAddressRequest:
|
||||
return actor->DoRequest(aRequest.get_GetSmscAddressRequest());
|
||||
default:
|
||||
MOZ_CRASH("Unknown type!");
|
||||
}
|
||||
@ -513,6 +515,23 @@ SmsRequestParent::DoRequest(const GetMessageRequest& aRequest)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SmsRequestParent::DoRequest(const GetSmscAddressRequest& aRequest)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
|
||||
if (smsService) {
|
||||
rv = smsService->GetSmscAddress(aRequest.serviceId(), this);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_SUCCEEDED(NotifyGetSmscAddressFailed(nsIMobileMessageCallback::INTERNAL_ERROR));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SmsRequestParent::DoRequest(const DeleteMessageRequest& aRequest)
|
||||
{
|
||||
@ -684,6 +703,18 @@ SmsRequestParent::NotifyGetSegmentInfoForTextFailed(int32_t aError)
|
||||
return SendReply(ReplyGetSegmentInfoForTextFail(aError));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsRequestParent::NotifyGetSmscAddress(const nsAString& aSmscAddress)
|
||||
{
|
||||
return SendReply(ReplyGetSmscAddress(nsString(aSmscAddress)));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsRequestParent::NotifyGetSmscAddressFailed(int32_t aError)
|
||||
{
|
||||
return SendReply(ReplyGetSmscAddressFail(aError));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* MobileMessageCursorParent
|
||||
******************************************************************************/
|
||||
|
@ -120,6 +120,9 @@ protected:
|
||||
bool
|
||||
DoRequest(const GetSegmentInfoForTextRequest& aRequest);
|
||||
|
||||
bool
|
||||
DoRequest(const GetSmscAddressRequest& aRequest);
|
||||
|
||||
nsresult
|
||||
SendReply(const MessageReply& aReply);
|
||||
};
|
||||
|
@ -50,6 +50,7 @@ struct MmsDeliveryInfoData
|
||||
{
|
||||
nsString receiver;
|
||||
DeliveryStatus deliveryStatus;
|
||||
uint64_t deliveryTimestamp;
|
||||
};
|
||||
|
||||
struct MmsMessageData
|
||||
|
@ -36,4 +36,5 @@ qemu = true
|
||||
[test_invalid_address.js]
|
||||
[test_mmsmessage_attachments.js]
|
||||
[test_getthreads.js]
|
||||
[test_smsc_address.js]
|
||||
[test_dsds_default_service_id.js]
|
||||
|
78
dom/mobilemessage/tests/marionette/test_smsc_address.js
Normal file
78
dom/mobilemessage/tests/marionette/test_smsc_address.js
Normal file
@ -0,0 +1,78 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
|
||||
SpecialPowers.addPermission("sms", true, document);
|
||||
|
||||
// Expected SMSC addresses of emulator
|
||||
const SMSC = "\"+123456789\",145";
|
||||
|
||||
let manager = window.navigator.mozMobileMessage;
|
||||
|
||||
let tasks = {
|
||||
// List of test fuctions. Each of them should call |tasks.next()| when
|
||||
// completed or |tasks.finish()| to jump to the last one.
|
||||
_tasks: [],
|
||||
_nextTaskIndex: 0,
|
||||
|
||||
push: function push(func) {
|
||||
this._tasks.push(func);
|
||||
},
|
||||
|
||||
next: function next() {
|
||||
let index = this._nextTaskIndex++;
|
||||
let task = this._tasks[index];
|
||||
try {
|
||||
task();
|
||||
} catch (ex) {
|
||||
ok(false, "test task[" + index + "] throws: " + ex);
|
||||
// Run last task as clean up if possible.
|
||||
if (index != this._tasks.length - 1) {
|
||||
this.finish();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
finish: function finish() {
|
||||
this._tasks[this._tasks.length - 1]();
|
||||
},
|
||||
|
||||
run: function run() {
|
||||
this.next();
|
||||
}
|
||||
};
|
||||
|
||||
tasks.push(function init() {
|
||||
log("Initialize test object.");
|
||||
ok(manager instanceof MozMobileMessageManager,
|
||||
"manager is instance of " + manager.constructor);
|
||||
tasks.next();
|
||||
});
|
||||
|
||||
tasks.push(function readSmscAddress() {
|
||||
log("read SMSC address");
|
||||
|
||||
let req = manager.getSmscAddress();
|
||||
ok(req, "DOMRequest object for getting smsc address");
|
||||
|
||||
req.onsuccess = function(e) {
|
||||
is(e.target.result, SMSC, "SMSC address");
|
||||
tasks.next();
|
||||
};
|
||||
|
||||
req.onerror = function(error) {
|
||||
ok(false, "readSmscAddress(): Received 'onerror'");
|
||||
tasks.finish();
|
||||
};
|
||||
});
|
||||
|
||||
// WARNING: All tasks should be pushed before this!!!
|
||||
tasks.push(function cleanUp() {
|
||||
manager.onreceived = null;
|
||||
SpecialPowers.removePermission("sms", document);
|
||||
finish();
|
||||
});
|
||||
|
||||
// Start the test
|
||||
tasks.run();
|
@ -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
|
||||
|
@ -271,7 +271,9 @@ MobileCellInfo.prototype = {
|
||||
cdmaNetworkId: -1
|
||||
};
|
||||
|
||||
function VoicemailStatus() {}
|
||||
function VoicemailStatus(clientId) {
|
||||
this.serviceId = clientId;
|
||||
}
|
||||
VoicemailStatus.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozVoicemailStatus]),
|
||||
classID: VOICEMAILSTATUS_CID,
|
||||
@ -284,8 +286,9 @@ VoicemailStatus.prototype = {
|
||||
|
||||
// nsIDOMMozVoicemailStatus
|
||||
|
||||
serviceId: -1,
|
||||
hasMessages: false,
|
||||
messageCount: Ci.nsIDOMMozVoicemailStatus.MESSAGE_COUNT_UNKNOWN,
|
||||
messageCount: -1, // Count unknown.
|
||||
returnNumber: null,
|
||||
returnMessage: null
|
||||
};
|
||||
@ -451,6 +454,8 @@ function RILContentHelper() {
|
||||
debug("Number of clients: " + this.numClients);
|
||||
|
||||
this.rilContexts = [];
|
||||
this.voicemailInfos = [];
|
||||
this.voicemailStatuses = [];
|
||||
for (let clientId = 0; clientId < this.numClients; clientId++) {
|
||||
this.rilContexts[clientId] = {
|
||||
cardState: RIL.GECKO_CARDSTATE_UNKNOWN,
|
||||
@ -459,9 +464,10 @@ function RILContentHelper() {
|
||||
voiceConnectionInfo: new MobileConnectionInfo(),
|
||||
dataConnectionInfo: new MobileConnectionInfo()
|
||||
};
|
||||
|
||||
this.voicemailInfos[clientId] = new VoicemailInfo();
|
||||
}
|
||||
|
||||
this.voicemailInfo = new VoicemailInfo();
|
||||
this.voicemailDefaultServiceId = this.getVoicemailDefaultServiceId();
|
||||
|
||||
this.initDOMRequestHelper(/* aWindow */ null, RIL_IPC_MSG_NAMES);
|
||||
@ -1361,7 +1367,8 @@ RILContentHelper.prototype = {
|
||||
_voicemailListeners: null,
|
||||
_iccListeners: null,
|
||||
|
||||
voicemailStatus: null,
|
||||
voicemailInfos: null,
|
||||
voicemailStatuses: null,
|
||||
|
||||
voicemailDefaultServiceId: 0,
|
||||
getVoicemailDefaultServiceId: function getVoicemailDefaultServiceId() {
|
||||
@ -1374,27 +1381,33 @@ RILContentHelper.prototype = {
|
||||
return id;
|
||||
},
|
||||
|
||||
getVoicemailInfo: function getVoicemailInfo() {
|
||||
getVoicemailInfo: function getVoicemailInfo(clientId) {
|
||||
// Get voicemail infomation by IPC only on first time.
|
||||
this.getVoicemailInfo = function getVoicemailInfo() {
|
||||
return this.voicemailInfo;
|
||||
this.getVoicemailInfo = function getVoicemailInfo(clientId) {
|
||||
return this.voicemailInfos[clientId];
|
||||
};
|
||||
|
||||
for (let cId = 0; cId < gNumRadioInterfaces; cId++) {
|
||||
let voicemailInfo =
|
||||
cpmm.sendSyncMessage("RIL:GetVoicemailInfo", {clientId: 0})[0];
|
||||
cpmm.sendSyncMessage("RIL:GetVoicemailInfo", {clientId: cId})[0];
|
||||
if (voicemailInfo) {
|
||||
this.updateInfo(voicemailInfo, this.voicemailInfo);
|
||||
this.updateInfo(voicemailInfo, this.voicemailInfos[cId]);
|
||||
}
|
||||
}
|
||||
|
||||
return this.voicemailInfo;
|
||||
return this.voicemailInfos[clientId];
|
||||
},
|
||||
|
||||
get voicemailNumber() {
|
||||
return this.getVoicemailInfo().number;
|
||||
getVoicemailNumber: function getVoicemailNumber(clientId) {
|
||||
return this.getVoicemailInfo(clientId).number;
|
||||
},
|
||||
|
||||
get voicemailDisplayName() {
|
||||
return this.getVoicemailInfo().displayName;
|
||||
getVoicemailDisplayName: function getVoicemailDisplayName(clientId) {
|
||||
return this.getVoicemailInfo(clientId).displayName;
|
||||
},
|
||||
|
||||
getVoicemailStatus: function getVoicemailStatus(clientId) {
|
||||
return this.voicemailStatuses[clientId];
|
||||
},
|
||||
|
||||
registerListener: function registerListener(listenerType, clientId, listener) {
|
||||
@ -1442,13 +1455,17 @@ RILContentHelper.prototype = {
|
||||
|
||||
registerVoicemailMsg: function registerVoicemailMsg(listener) {
|
||||
debug("Registering for voicemail-related messages");
|
||||
//TODO: Bug 814634 - WebVoicemail API: support multiple sim cards.
|
||||
// To follow the listener registration scheme, we add a dummy clientId 0.
|
||||
// All voicemail events are routed to listener for client id 0.
|
||||
// See |handleVoicemailNotification|.
|
||||
this.registerListener("_voicemailListeners", 0, listener);
|
||||
cpmm.sendAsyncMessage("RIL:RegisterVoicemailMsg");
|
||||
},
|
||||
|
||||
unregisterVoicemailMsg: function unregisteVoicemailMsg(listener) {
|
||||
//TODO: Bug 814634 - WebVoicemail API: support multiple sim cards.
|
||||
// To follow the listener unregistration scheme, we add a dummy clientId 0.
|
||||
// All voicemail events are routed to listener for client id 0.
|
||||
// See |handleVoicemailNotification|.
|
||||
this.unregisterListener("_voicemailListeners", 0, listener);
|
||||
},
|
||||
|
||||
@ -1619,7 +1636,7 @@ RILContentHelper.prototype = {
|
||||
this.handleVoicemailNotification(clientId, data);
|
||||
break;
|
||||
case "RIL:VoicemailInfoChanged":
|
||||
this.updateInfo(data, this.voicemailInfo);
|
||||
this.updateInfo(data, this.voicemailInfos[clientId]);
|
||||
break;
|
||||
case "RIL:CardLockResult": {
|
||||
let requestId = data.requestId;
|
||||
@ -1835,41 +1852,44 @@ RILContentHelper.prototype = {
|
||||
this.fireRequestSuccess(message.requestId, result);
|
||||
},
|
||||
|
||||
handleVoicemailNotification: function handleVoicemailNotification(clientId, message) {
|
||||
// Bug 814634 - WebVoicemail API: support multiple sim cards
|
||||
handleVoicemailNotification: function handleVoicemailNotification(clientId,
|
||||
message) {
|
||||
let changed = false;
|
||||
if (!this.voicemailStatus) {
|
||||
this.voicemailStatus = new VoicemailStatus();
|
||||
if (!this.voicemailStatuses[clientId]) {
|
||||
this.voicemailStatuses[clientId] = new VoicemailStatus(clientId);
|
||||
}
|
||||
|
||||
if (this.voicemailStatus.hasMessages != message.active) {
|
||||
let voicemailStatus = this.voicemailStatuses[clientId];
|
||||
if (voicemailStatus.hasMessages != message.active) {
|
||||
changed = true;
|
||||
this.voicemailStatus.hasMessages = message.active;
|
||||
voicemailStatus.hasMessages = message.active;
|
||||
}
|
||||
|
||||
if (this.voicemailStatus.messageCount != message.msgCount) {
|
||||
if (voicemailStatus.messageCount != message.msgCount) {
|
||||
changed = true;
|
||||
this.voicemailStatus.messageCount = message.msgCount;
|
||||
voicemailStatus.messageCount = message.msgCount;
|
||||
} else if (message.msgCount == -1) {
|
||||
// For MWI using DCS the message count is not available
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (this.voicemailStatus.returnNumber != message.returnNumber) {
|
||||
if (voicemailStatus.returnNumber != message.returnNumber) {
|
||||
changed = true;
|
||||
this.voicemailStatus.returnNumber = message.returnNumber;
|
||||
voicemailStatus.returnNumber = message.returnNumber;
|
||||
}
|
||||
|
||||
if (this.voicemailStatus.returnMessage != message.returnMessage) {
|
||||
if (voicemailStatus.returnMessage != message.returnMessage) {
|
||||
changed = true;
|
||||
this.voicemailStatus.returnMessage = message.returnMessage;
|
||||
voicemailStatus.returnMessage = message.returnMessage;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
this._deliverEvent(clientId,
|
||||
// To follow the event delivering scheme, we add a dummy clientId 0.
|
||||
// All voicemail events are routed to listener for client id 0.
|
||||
this._deliverEvent(0,
|
||||
"_voicemailListeners",
|
||||
"notifyStatusChanged",
|
||||
[this.voicemailStatus]);
|
||||
[voicemailStatus]);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -2925,6 +2925,18 @@ RadioInterface.prototype = {
|
||||
request.notifySegmentInfoForTextGot(result);
|
||||
},
|
||||
|
||||
getSmscAddress: function getSmscAddress(request) {
|
||||
this.workerMessenger.send("getSmscAddress",
|
||||
null,
|
||||
(function(response) {
|
||||
if (!response.errorMsg) {
|
||||
request.notifyGetSmscAddress(response.smscAddress);
|
||||
} else {
|
||||
request.notifyGetSmscAddressFailed(response.errorMsg);
|
||||
}
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
sendSMS: function sendSMS(number, message, silent, request) {
|
||||
let strict7BitEncoding;
|
||||
try {
|
||||
|
@ -97,7 +97,7 @@ interface nsIRilSendWorkerMessageCallback : nsISupports
|
||||
boolean handleResponse(in jsval response);
|
||||
};
|
||||
|
||||
[scriptable, uuid(61a8ca67-6113-4cd0-b443-e045f09863ed)]
|
||||
[scriptable, uuid(5b14cf79-2846-4226-b07f-9b9977b525fe)]
|
||||
interface nsIRadioInterface : nsISupports
|
||||
{
|
||||
readonly attribute nsIRilContext rilContext;
|
||||
@ -128,6 +128,8 @@ interface nsIRadioInterface : nsISupports
|
||||
void sendWorkerMessage(in DOMString type,
|
||||
[optional] in jsval message,
|
||||
[optional] in nsIRilSendWorkerMessageCallback callback);
|
||||
|
||||
void getSmscAddress(in nsIMobileMessageCallback request);
|
||||
};
|
||||
|
||||
[scriptable, uuid(70d3a18c-4063-11e3-89de-0f9ec19fd803)]
|
||||
|
@ -1793,19 +1793,30 @@ let RIL = {
|
||||
/**
|
||||
* Get the Short Message Service Center address.
|
||||
*/
|
||||
getSMSCAddress: function getSMSCAddress() {
|
||||
Buf.simpleRequest(REQUEST_GET_SMSC_ADDRESS);
|
||||
getSmscAddress: function getSmscAddress(options) {
|
||||
if (!this.SMSC) {
|
||||
Buf.simpleRequest(REQUEST_GET_SMSC_ADDRESS, options);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!options || options.rilMessageType !== "getSmscAddress") {
|
||||
return;
|
||||
}
|
||||
|
||||
options.smscAddress = this.SMSC;
|
||||
options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
|
||||
this.sendChromeMessage(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the Short Message Service Center address.
|
||||
*
|
||||
* @param SMSC
|
||||
* @param smscAddress
|
||||
* Short Message Service Center address in PDU format.
|
||||
*/
|
||||
setSMSCAddress: function setSMSCAddress(options) {
|
||||
Buf.newParcel(REQUEST_SET_SMSC_ADDRESS);
|
||||
Buf.writeString(options.SMSC);
|
||||
setSmscAddress: function setSmscAddress(options) {
|
||||
Buf.newParcel(REQUEST_SET_SMSC_ADDRESS, options);
|
||||
Buf.writeString(options.smscAddress);
|
||||
Buf.sendParcel();
|
||||
},
|
||||
|
||||
@ -3330,7 +3341,7 @@ let RIL = {
|
||||
let rs = this.voiceRegistrationState;
|
||||
let stateChanged = this._processCREG(rs, state);
|
||||
if (stateChanged && rs.connected) {
|
||||
RIL.getSMSCAddress();
|
||||
RIL.getSmscAddress();
|
||||
}
|
||||
|
||||
let cell = rs.cell;
|
||||
@ -5914,11 +5925,15 @@ RIL[REQUEST_EXIT_EMERGENCY_CALLBACK_MODE] = function REQUEST_EXIT_EMERGENCY_CALL
|
||||
this.sendChromeMessage(options);
|
||||
};
|
||||
RIL[REQUEST_GET_SMSC_ADDRESS] = function REQUEST_GET_SMSC_ADDRESS(length, options) {
|
||||
if (options.rilRequestError) {
|
||||
this.SMSC = options.rilRequestError ? null : Buf.readString();
|
||||
|
||||
if (!options || options.rilMessageType !== "getSmscAddress") {
|
||||
return;
|
||||
}
|
||||
|
||||
this.SMSC = Buf.readString();
|
||||
options.smscAddress = this.SMSC;
|
||||
options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
|
||||
this.sendChromeMessage(options);
|
||||
};
|
||||
RIL[REQUEST_SET_SMSC_ADDRESS] = null;
|
||||
RIL[REQUEST_REPORT_SMS_MEMORY_STATUS] = null;
|
||||
|
@ -10,12 +10,14 @@
|
||||
#include "nsIDOMMozVoicemailStatus.h"
|
||||
#include "nsIDOMMozVoicemailEvent.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "GeneratedEvents.h"
|
||||
|
||||
#define NS_RILCONTENTHELPER_CONTRACTID "@mozilla.org/ril/content-helper;1"
|
||||
const char* kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces";
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
@ -67,18 +69,48 @@ Voicemail::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
return MozVoicemailBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
bool
|
||||
Voicemail::IsValidServiceId(uint32_t aServiceId) const
|
||||
{
|
||||
uint32_t numClients = mozilla::Preferences::GetUint(kPrefRilNumRadioInterfaces, 1);
|
||||
|
||||
return aServiceId < numClients;
|
||||
}
|
||||
|
||||
bool
|
||||
Voicemail::PassedOrDefaultServiceId(const Optional<uint32_t>& aServiceId,
|
||||
uint32_t& aResult) const
|
||||
{
|
||||
if (aServiceId.WasPassed()) {
|
||||
if (!IsValidServiceId(aServiceId.Value())) {
|
||||
return false;
|
||||
}
|
||||
aResult = aServiceId.Value();
|
||||
} else {
|
||||
mProvider->GetVoicemailDefaultServiceId(&aResult);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// MozVoicemail WebIDL
|
||||
|
||||
already_AddRefed<nsIDOMMozVoicemailStatus>
|
||||
Voicemail::GetStatus(ErrorResult& aRv) const
|
||||
Voicemail::GetStatus(const Optional<uint32_t>& aServiceId,
|
||||
ErrorResult& aRv) const
|
||||
{
|
||||
if (!mProvider) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t id = 0;
|
||||
if (!PassedOrDefaultServiceId(aServiceId, id)) {
|
||||
aRv.Throw(NS_ERROR_INVALID_ARG);
|
||||
return nullptr;
|
||||
}
|
||||
nsCOMPtr<nsIDOMMozVoicemailStatus> status;
|
||||
nsresult rv = mProvider->GetVoicemailStatus(getter_AddRefs(status));
|
||||
nsresult rv = mProvider->GetVoicemailStatus(id, getter_AddRefs(status));
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return nullptr;
|
||||
@ -88,7 +120,8 @@ Voicemail::GetStatus(ErrorResult& aRv) const
|
||||
}
|
||||
|
||||
void
|
||||
Voicemail::GetNumber(nsString& aNumber, ErrorResult& aRv) const
|
||||
Voicemail::GetNumber(const Optional<uint32_t>& aServiceId, nsString& aNumber,
|
||||
ErrorResult& aRv) const
|
||||
{
|
||||
aNumber.SetIsVoid(true);
|
||||
|
||||
@ -97,11 +130,18 @@ Voicemail::GetNumber(nsString& aNumber, ErrorResult& aRv) const
|
||||
return;
|
||||
}
|
||||
|
||||
aRv = mProvider->GetVoicemailNumber(aNumber);
|
||||
uint32_t id = 0;
|
||||
if (!PassedOrDefaultServiceId(aServiceId, id)) {
|
||||
aRv.Throw(NS_ERROR_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
|
||||
aRv = mProvider->GetVoicemailNumber(id, aNumber);
|
||||
}
|
||||
|
||||
void
|
||||
Voicemail::GetDisplayName(nsString& aDisplayName, ErrorResult& aRv) const
|
||||
Voicemail::GetDisplayName(const Optional<uint32_t>& aServiceId, nsString& aDisplayName,
|
||||
ErrorResult& aRv) const
|
||||
{
|
||||
aDisplayName.SetIsVoid(true);
|
||||
|
||||
@ -110,7 +150,13 @@ Voicemail::GetDisplayName(nsString& aDisplayName, ErrorResult& aRv) const
|
||||
return;
|
||||
}
|
||||
|
||||
aRv = mProvider->GetVoicemailDisplayName(aDisplayName);
|
||||
uint32_t id = 0;
|
||||
if (!PassedOrDefaultServiceId(aServiceId, id)) {
|
||||
aRv.Throw(NS_ERROR_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
|
||||
aRv = mProvider->GetVoicemailDisplayName(id, aDisplayName);
|
||||
}
|
||||
|
||||
// nsIVoicemailListener
|
||||
|
@ -52,19 +52,28 @@ public:
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
||||
already_AddRefed<nsIDOMMozVoicemailStatus>
|
||||
GetStatus(ErrorResult& aRv) const;
|
||||
GetStatus(const Optional<uint32_t>& aServiceId, ErrorResult& aRv) const;
|
||||
|
||||
void
|
||||
GetNumber(nsString& aNumber, ErrorResult& aRv) const;
|
||||
GetNumber(const Optional<uint32_t>& aServiceId, nsString& aNumber,
|
||||
ErrorResult& aRv) const;
|
||||
|
||||
void
|
||||
GetDisplayName(nsString& aDisplayName, ErrorResult& aRv) const;
|
||||
GetDisplayName(const Optional<uint32_t>& aServiceId, nsString& aDisplayName,
|
||||
ErrorResult& aRv) const;
|
||||
|
||||
IMPL_EVENT_HANDLER(statuschanged)
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIVoicemailProvider> mProvider;
|
||||
nsRefPtr<Listener> mListener;
|
||||
|
||||
bool
|
||||
IsValidServiceId(uint32_t aServiceId) const;
|
||||
|
||||
bool
|
||||
PassedOrDefaultServiceId(const Optional<uint32_t>& aServiceId,
|
||||
uint32_t& aResult) const;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -6,13 +6,10 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(8c58859a-e006-466a-ad76-b188ba0918ab)]
|
||||
[scriptable, uuid(efd352af-9eee-48dc-8e92-4d4fdbc89ecb)]
|
||||
interface nsIDOMMozVoicemailStatus : nsISupports
|
||||
{
|
||||
/**
|
||||
* There are voicemail messages waiting, but the count is unknown.
|
||||
*/
|
||||
const long MESSAGE_COUNT_UNKNOWN = -1;
|
||||
readonly attribute unsigned long serviceId;
|
||||
|
||||
/**
|
||||
* Whether or not there are messages waiting in the voicemail box
|
||||
@ -22,7 +19,7 @@ interface nsIDOMMozVoicemailStatus : nsISupports
|
||||
/**
|
||||
* The total message count. Some voicemail indicators will only specify that
|
||||
* messages are waiting, but not the actual number. In that case, the value
|
||||
* of messageCount will be MESSAGE_COUNT_UNKNOWN (-1).
|
||||
* of messageCount will be -1, indicating the unknown message count.
|
||||
*
|
||||
* Logic for a voicemail notification might look something like:
|
||||
* if (status.hasMessages) {
|
||||
|
@ -22,7 +22,7 @@ interface nsIVoicemailListener : nsISupports
|
||||
* XPCOM component (in the content process) that provides the voicemail
|
||||
* information.
|
||||
*/
|
||||
[scriptable, uuid(38746f3c-f4e3-4804-b900-ba2463b923c8)]
|
||||
[scriptable, uuid(1bbfff90-88f7-4d73-896e-9620a0000ab0)]
|
||||
interface nsIVoicemailProvider : nsISupports
|
||||
{
|
||||
readonly attribute unsigned long voicemailDefaultServiceId;
|
||||
@ -35,7 +35,7 @@ interface nsIVoicemailProvider : nsISupports
|
||||
void registerVoicemailMsg(in nsIVoicemailListener listener);
|
||||
void unregisterVoicemailMsg(in nsIVoicemailListener listener);
|
||||
|
||||
readonly attribute nsIDOMMozVoicemailStatus voicemailStatus;
|
||||
readonly attribute DOMString voicemailNumber;
|
||||
readonly attribute DOMString voicemailDisplayName;
|
||||
nsIDOMMozVoicemailStatus getVoicemailStatus(in unsigned long clientId);
|
||||
DOMString getVoicemailNumber(in unsigned long clientId);
|
||||
DOMString getVoicemailDisplayName(in unsigned long clientId);
|
||||
};
|
||||
|
@ -8,9 +8,14 @@ SpecialPowers.addPermission("voicemail", true, document);
|
||||
let voicemail = window.navigator.mozVoicemail;
|
||||
ok(voicemail instanceof MozVoicemail);
|
||||
|
||||
let serviceId = 0;
|
||||
|
||||
// These are the emulator's hard coded voicemail number and alphaId
|
||||
is(voicemail.number, "+15552175049");
|
||||
is(voicemail.displayName, "Voicemail");
|
||||
is(voicemail.getNumber(serviceId), "+15552175049");
|
||||
is(voicemail.getDisplayName(serviceId), "Voicemail");
|
||||
|
||||
is(voicemail.getNumber(), "+15552175049");
|
||||
is(voicemail.getDisplayName(), "Voicemail");
|
||||
|
||||
SpecialPowers.removePermission("voicemail", document);
|
||||
finish();
|
||||
|
@ -4,6 +4,8 @@
|
||||
SpecialPowers.addPermission("voicemail", true, document);
|
||||
|
||||
let voicemail = window.navigator.mozVoicemail;
|
||||
let serviceId = 0;
|
||||
|
||||
ok(voicemail instanceof MozVoicemail);
|
||||
is(voicemail.status, null);
|
||||
|
||||
@ -42,10 +44,13 @@ function sendIndicatorPDU(pdu, listener, nextTest) {
|
||||
// See RadioInterfaceLayer.js / Bug #768441
|
||||
|
||||
function isVoicemailStatus(status) {
|
||||
is(voicemail.status.hasMessages, status.hasMessages);
|
||||
is(voicemail.status.messageCount, status.messageCount);
|
||||
is(voicemail.status.returnNumber, status.returnNumber);
|
||||
is(voicemail.status.returnMessage, status.returnMessage);
|
||||
is(voicemail.getStatus(), status);
|
||||
is(voicemail.getStatus(serviceId), status);
|
||||
|
||||
is(voicemail.getStatus().hasMessages, status.hasMessages);
|
||||
is(voicemail.getStatus().messageCount, status.messageCount);
|
||||
is(voicemail.getStatus().returnNumber, status.returnNumber);
|
||||
is(voicemail.getStatus().returnMessage, status.returnMessage);
|
||||
}
|
||||
|
||||
const MWI_PDU_PREFIX = "0000";
|
||||
@ -80,7 +85,7 @@ function testLevel1Indicator() {
|
||||
// TODO: bug 905228 - MozVoicemailStatus is not defined.
|
||||
//ok(status instanceof MozVoicemailStatus);
|
||||
is(status.hasMessages, true);
|
||||
is(status.messageCount, status.MESSAGE_COUNT_UNKNOWN);
|
||||
is(status.messageCount, -1);
|
||||
is(status.returnNumber, MWI_LEVEL1_SENDER);
|
||||
is(status.returnMessage, MWI_DEFAULT_BODY);
|
||||
isVoicemailStatus(status);
|
||||
|
@ -11,26 +11,28 @@ interface MozVoicemailStatus;
|
||||
interface MozVoicemail : EventTarget
|
||||
{
|
||||
/**
|
||||
* The current voicemail status, or null when the status is unknown
|
||||
* The current voicemail status of a specified service, or null when the
|
||||
* status is unknown.
|
||||
*/
|
||||
[GetterThrows]
|
||||
readonly attribute MozVoicemailStatus? status;
|
||||
[Throws]
|
||||
MozVoicemailStatus getStatus(optional unsigned long serviceId);
|
||||
|
||||
/**
|
||||
* The voicemail box dialing number, or null if one wasn't found
|
||||
* The voicemail box dialing number of a specified service, or null if one
|
||||
* wasn't found.
|
||||
*/
|
||||
[GetterThrows]
|
||||
readonly attribute DOMString? number;
|
||||
[Throws]
|
||||
DOMString getNumber(optional unsigned long serviceId);
|
||||
|
||||
/**
|
||||
* The display name of the voicemail box dialing number, or null if one
|
||||
* wasn't found
|
||||
* The display name of the voicemail box dialing number of a specified service,
|
||||
* or null if one wasn't found.
|
||||
*/
|
||||
[GetterThrows]
|
||||
readonly attribute DOMString? displayName;
|
||||
[Throws]
|
||||
DOMString getDisplayName(optional unsigned long serviceId);
|
||||
|
||||
/**
|
||||
* The current voicemail status has changed
|
||||
* The current voicemail status has changed.
|
||||
*/
|
||||
attribute EventHandler onstatuschanged;
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
registrar.registerFactory(newClassID, "", CONTRACT_ID, newFactory);
|
||||
}
|
||||
},
|
||||
@ -70,18 +61,15 @@ 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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Expose everything to content. We call reset() here so that all of the relevant
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user