mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central to b2g-inbound
This commit is contained in:
commit
5c5ba13e67
2
CLOBBER
2
CLOBBER
@ -18,4 +18,4 @@
|
||||
# Modifying this file will now automatically clobber the buildbot machines \o/
|
||||
#
|
||||
|
||||
Bug 914270 needs a clobber since moving variables to moz.build always requires a clobber (bug 852814)
|
||||
Bug 918345 needs a clobber due to WebIDL binding dependency issues (bug 928195).
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
#include "nsISelectionController.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsITextControlFrame.h"
|
||||
|
||||
|
@ -728,6 +728,7 @@ pref("font.size.inflation.disabledInMasterProcess", true);
|
||||
pref("memory.free_dirty_pages", true);
|
||||
|
||||
pref("layout.imagevisibility.enabled", false);
|
||||
pref("layout.imagevisibility.enabled_for_browser_elements_only", true);
|
||||
pref("layout.imagevisibility.numscrollportwidths", 1);
|
||||
pref("layout.imagevisibility.numscrollportheights", 1);
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
"use strict"
|
||||
|
||||
function debug(str) {
|
||||
//dump("-*- ContentPermissionPrompt: " + s + "\n");
|
||||
//dump("-*- ContentPermissionPrompt: " + str + "\n");
|
||||
}
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
@ -13,11 +13,14 @@ const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
|
||||
const PROMPT_FOR_UNKNOWN = ["geolocation", "desktop-notification",
|
||||
"audio-capture"];
|
||||
const PROMPT_FOR_UNKNOWN = ["audio-capture",
|
||||
"desktop-notification",
|
||||
"geolocation",
|
||||
"video-capture"];
|
||||
// Due to privary issue, permission requests like GetUserMedia should prompt
|
||||
// every time instead of providing session persistence.
|
||||
const PERMISSION_NO_SESSION = ["audio-capture"];
|
||||
const PERMISSION_NO_SESSION = ["audio-capture", "video-capture"];
|
||||
const ALLOW_MULTIPLE_REQUESTS = ["audio-capture", "video-capture"];
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
@ -41,7 +44,21 @@ XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"@mozilla.org/telephony/audiomanager;1",
|
||||
"nsIAudioManager");
|
||||
|
||||
function rememberPermission(aPermission, aPrincipal, aSession)
|
||||
/**
|
||||
* aTypesInfo is an array of {permission, access, action, deny} which keeps
|
||||
* the information of each permission. This arrary is initialized in
|
||||
* ContentPermissionPrompt.prompt and used among functions.
|
||||
*
|
||||
* aTypesInfo[].permission : permission name
|
||||
* aTypesInfo[].access : permission name + request.access
|
||||
* aTypesInfo[].action : the default action of this permission
|
||||
* aTypesInfo[].deny : true if security manager denied this app's origin
|
||||
* principal.
|
||||
* Note:
|
||||
* aTypesInfo[].permission will be sent to prompt only when
|
||||
* aTypesInfo[].action is PROMPT_ACTION and aTypesInfo[].deny is false.
|
||||
*/
|
||||
function rememberPermission(aTypesInfo, aPrincipal, aSession)
|
||||
{
|
||||
function convertPermToAllow(aPerm, aPrincipal)
|
||||
{
|
||||
@ -49,12 +66,13 @@ function rememberPermission(aPermission, aPrincipal, aSession)
|
||||
permissionManager.testExactPermissionFromPrincipal(aPrincipal, aPerm);
|
||||
if (type == Ci.nsIPermissionManager.PROMPT_ACTION ||
|
||||
(type == Ci.nsIPermissionManager.UNKNOWN_ACTION &&
|
||||
PROMPT_FOR_UNKNOWN.indexOf(aPermission) >= 0)) {
|
||||
PROMPT_FOR_UNKNOWN.indexOf(aPerm) >= 0)) {
|
||||
debug("add " + aPerm + " to permission manager with ALLOW_ACTION");
|
||||
if (!aSession) {
|
||||
permissionManager.addFromPrincipal(aPrincipal,
|
||||
aPerm,
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
} else if (PERMISSION_NO_SESSION.indexOf(aPermission) < 0) {
|
||||
} else if (PERMISSION_NO_SESSION.indexOf(aPerm) < 0) {
|
||||
permissionManager.addFromPrincipal(aPrincipal,
|
||||
aPerm,
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
@ -63,14 +81,18 @@ function rememberPermission(aPermission, aPrincipal, aSession)
|
||||
}
|
||||
}
|
||||
|
||||
// Expand the permission to see if we have multiple access properties to convert
|
||||
let access = PermissionsTable[aPermission].access;
|
||||
if (access) {
|
||||
for (let idx in access) {
|
||||
convertPermToAllow(aPermission + "-" + access[idx], aPrincipal);
|
||||
for (let i in aTypesInfo) {
|
||||
// Expand the permission to see if we have multiple access properties
|
||||
// to convert
|
||||
let perm = aTypesInfo[i].permission;
|
||||
let access = PermissionsTable[perm].access;
|
||||
if (access) {
|
||||
for (let idx in access) {
|
||||
convertPermToAllow(perm + "-" + access[idx], aPrincipal);
|
||||
}
|
||||
} else {
|
||||
convertPermToAllow(perm, aPrincipal);
|
||||
}
|
||||
} else {
|
||||
convertPermToAllow(aPermission, aPrincipal);
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,23 +100,63 @@ function ContentPermissionPrompt() {}
|
||||
|
||||
ContentPermissionPrompt.prototype = {
|
||||
|
||||
handleExistingPermission: function handleExistingPermission(request) {
|
||||
let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
|
||||
request.type;
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, access);
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
handleExistingPermission: function handleExistingPermission(request,
|
||||
typesInfo) {
|
||||
typesInfo.forEach(function(type) {
|
||||
type.action =
|
||||
Services.perms.testExactPermissionFromPrincipal(request.principal,
|
||||
type.access);
|
||||
});
|
||||
|
||||
// If all permissions are allowed already, call allow() without prompting.
|
||||
let checkAllowPermission = function(type) {
|
||||
if (type.action == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (typesInfo.every(checkAllowPermission)) {
|
||||
debug("all permission requests are allowed");
|
||||
request.allow();
|
||||
return true;
|
||||
}
|
||||
if (result == Ci.nsIPermissionManager.DENY_ACTION ||
|
||||
result == Ci.nsIPermissionManager.UNKNOWN_ACTION && PROMPT_FOR_UNKNOWN.indexOf(access) < 0) {
|
||||
|
||||
// If all permissions are DENY_ACTION or UNKNOWN_ACTION, call cancel()
|
||||
// without prompting.
|
||||
let checkDenyPermission = function(type) {
|
||||
if (type.action == Ci.nsIPermissionManager.DENY_ACTION ||
|
||||
type.action == Ci.nsIPermissionManager.UNKNOWN_ACTION &&
|
||||
PROMPT_FOR_UNKNOWN.indexOf(type.access) < 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (typesInfo.every(checkDenyPermission)) {
|
||||
debug("all permission requests are denied");
|
||||
request.cancel();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
handledByApp: function handledByApp(request) {
|
||||
// multiple requests should be audio and video
|
||||
checkMultipleRequest: function checkMultipleRequest(typesInfo) {
|
||||
if (typesInfo.length == 1) {
|
||||
return true;
|
||||
} else if (typesInfo.length > 1) {
|
||||
let checkIfAllowMultiRequest = function(type) {
|
||||
return (ALLOW_MULTIPLE_REQUESTS.indexOf(type.access) !== -1);
|
||||
}
|
||||
if (typesInfo.every(checkIfAllowMultiRequest)) {
|
||||
debug("legal multiple requests");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
handledByApp: function handledByApp(request, typesInfo) {
|
||||
if (request.principal.appId == Ci.nsIScriptSecurityManager.NO_APP_ID ||
|
||||
request.principal.appId == Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID) {
|
||||
// This should not really happen
|
||||
@ -106,49 +168,94 @@ ContentPermissionPrompt.prototype = {
|
||||
.getService(Ci.nsIAppsService);
|
||||
let app = appsService.getAppByLocalId(request.principal.appId);
|
||||
|
||||
let url = Services.io.newURI(app.origin, null, null);
|
||||
let principal = secMan.getAppCodebasePrincipal(url, request.principal.appId,
|
||||
/*mozbrowser*/false);
|
||||
let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
|
||||
request.type;
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(principal, access);
|
||||
// Check each permission if it's denied by permission manager with app's
|
||||
// URL.
|
||||
let checkIfDenyAppPrincipal = function(type) {
|
||||
let url = Services.io.newURI(app.origin, null, null);
|
||||
let principal = secMan.getAppCodebasePrincipal(url,
|
||||
request.principal.appId,
|
||||
/*mozbrowser*/false);
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(principal,
|
||||
type.access);
|
||||
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION ||
|
||||
result == Ci.nsIPermissionManager.PROMPT_ACTION) {
|
||||
return false;
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION ||
|
||||
result == Ci.nsIPermissionManager.PROMPT_ACTION) {
|
||||
type.deny = false;
|
||||
}
|
||||
return type.deny;
|
||||
}
|
||||
if (typesInfo.every(checkIfDenyAppPrincipal)) {
|
||||
request.cancel();
|
||||
return true;
|
||||
}
|
||||
|
||||
request.cancel();
|
||||
return true;
|
||||
return false;
|
||||
},
|
||||
|
||||
handledByPermissionType: function handledByPermissionType(request) {
|
||||
return permissionSpecificChecker.hasOwnProperty(request.type)
|
||||
? permissionSpecificChecker[request.type](request)
|
||||
: false;
|
||||
handledByPermissionType: function handledByPermissionType(request, typesInfo) {
|
||||
for (let i in typesInfo) {
|
||||
if (permissionSpecificChecker.hasOwnProperty(typesInfo[i].permission) &&
|
||||
permissionSpecificChecker[typesInfo[i].permission](request)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
_id: 0,
|
||||
prompt: function(request) {
|
||||
if (secMan.isSystemPrincipal(request.principal)) {
|
||||
request.allow();
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.handledByApp(request) ||
|
||||
this.handledByPermissionType(request)) {
|
||||
// Initialize the typesInfo and set the default value.
|
||||
let typesInfo = [];
|
||||
let perms = request.types.QueryInterface(Ci.nsIArray);
|
||||
for (let idx = 0; idx < perms.length; idx++) {
|
||||
let perm = perms.queryElementAt(idx, Ci.nsIContentPermissionType);
|
||||
let tmp = {
|
||||
permission: perm.type,
|
||||
access: (perm.access && perm.access !== "unused") ?
|
||||
perm.type + "-" + perm.access : perm.type,
|
||||
deny: true,
|
||||
action: Ci.nsIPermissionManager.UNKNOWN_ACTION
|
||||
};
|
||||
typesInfo.push(tmp);
|
||||
}
|
||||
if (typesInfo.length == 0) {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
if(!this.checkMultipleRequest(typesInfo)) {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.handledByApp(request, typesInfo) ||
|
||||
this.handledByPermissionType(request, typesInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// returns true if the request was handled
|
||||
if (this.handleExistingPermission(request))
|
||||
if (this.handleExistingPermission(request, typesInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// prompt PROMPT_ACTION request only.
|
||||
typesInfo.forEach(function(aType, aIndex) {
|
||||
if (aType.action != Ci.nsIPermissionManager.PROMPT_ACTION || aType.deny) {
|
||||
typesInfo.splice(aIndex);
|
||||
}
|
||||
});
|
||||
|
||||
let frame = request.element;
|
||||
let requestId = this._id++;
|
||||
|
||||
if (!frame) {
|
||||
this.delegatePrompt(request, requestId);
|
||||
this.delegatePrompt(request, requestId, typesInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -163,7 +270,7 @@ ContentPermissionPrompt.prototype = {
|
||||
if (evt.detail.visible === true)
|
||||
return;
|
||||
|
||||
self.cancelPrompt(request, requestId);
|
||||
self.cancelPrompt(request, requestId, typesInfo);
|
||||
cancelRequest();
|
||||
}
|
||||
|
||||
@ -180,7 +287,7 @@ ContentPermissionPrompt.prototype = {
|
||||
// away but the request is still here.
|
||||
frame.addEventListener("mozbrowservisibilitychange", onVisibilityChange);
|
||||
|
||||
self.delegatePrompt(request, requestId, function onCallback() {
|
||||
self.delegatePrompt(request, requestId, typesInfo, function onCallback() {
|
||||
frame.removeEventListener("mozbrowservisibilitychange", onVisibilityChange);
|
||||
});
|
||||
};
|
||||
@ -191,22 +298,17 @@ ContentPermissionPrompt.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
cancelPrompt: function(request, requestId) {
|
||||
this.sendToBrowserWindow("cancel-permission-prompt", request, requestId);
|
||||
cancelPrompt: function(request, requestId, typesInfo) {
|
||||
this.sendToBrowserWindow("cancel-permission-prompt", request, requestId,
|
||||
typesInfo);
|
||||
},
|
||||
|
||||
delegatePrompt: function(request, requestId, callback) {
|
||||
let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
|
||||
request.type;
|
||||
let principal = request.principal;
|
||||
delegatePrompt: function(request, requestId, typesInfo, callback) {
|
||||
|
||||
this._permission = access;
|
||||
this._uri = principal.URI.spec;
|
||||
this._origin = principal.origin;
|
||||
|
||||
this.sendToBrowserWindow("permission-prompt", request, requestId, function(type, remember) {
|
||||
this.sendToBrowserWindow("permission-prompt", request, requestId, typesInfo,
|
||||
function(type, remember) {
|
||||
if (type == "permission-allow") {
|
||||
rememberPermission(request.type, principal, !remember);
|
||||
rememberPermission(typesInfo, request.principal, !remember);
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
@ -214,14 +316,20 @@ ContentPermissionPrompt.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
if (remember) {
|
||||
Services.perms.addFromPrincipal(principal, access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION);
|
||||
} else {
|
||||
Services.perms.addFromPrincipal(principal, access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION,
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION, 0);
|
||||
let addDenyPermission = function(type) {
|
||||
debug("add " + type.permission +
|
||||
" to permission manager with DENY_ACTION");
|
||||
if (remember) {
|
||||
Services.perms.addFromPrincipal(request.principal, type.access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION);
|
||||
} else {
|
||||
Services.perms.addFromPrincipal(request.principal, type.access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION,
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION,
|
||||
0);
|
||||
}
|
||||
}
|
||||
typesInfo.forEach(addDenyPermission);
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
@ -230,7 +338,7 @@ ContentPermissionPrompt.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
sendToBrowserWindow: function(type, request, requestId, callback) {
|
||||
sendToBrowserWindow: function(type, request, requestId, typesInfo, callback) {
|
||||
let browser = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let content = browser.getContentWindow();
|
||||
if (!content)
|
||||
@ -253,10 +361,15 @@ ContentPermissionPrompt.prototype = {
|
||||
principal.appStatus == Ci.nsIPrincipal.APP_STATUS_CERTIFIED)
|
||||
? true
|
||||
: request.remember;
|
||||
let permissions = [];
|
||||
for (let i in typesInfo) {
|
||||
debug("prompt " + typesInfo[i].permission);
|
||||
permissions.push(typesInfo[i].permission);
|
||||
}
|
||||
|
||||
let details = {
|
||||
type: type,
|
||||
permission: request.type,
|
||||
permissions: permissions,
|
||||
id: requestId,
|
||||
origin: principal.origin,
|
||||
isApp: isApp,
|
||||
@ -289,6 +402,5 @@ ContentPermissionPrompt.prototype = {
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
//module initialization
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentPermissionPrompt]);
|
||||
|
@ -213,20 +213,12 @@ var gPluginHandler = {
|
||||
},
|
||||
|
||||
handleEvent : function(event) {
|
||||
let plugin;
|
||||
let doc;
|
||||
|
||||
let eventType = event.type;
|
||||
if (eventType === "PluginRemoved") {
|
||||
doc = event.target;
|
||||
}
|
||||
else {
|
||||
plugin = event.target;
|
||||
doc = plugin.ownerDocument;
|
||||
let plugin = event.target;
|
||||
let doc = plugin.ownerDocument;
|
||||
|
||||
if (!(plugin instanceof Ci.nsIObjectLoadingContent))
|
||||
return;
|
||||
}
|
||||
if (!(plugin instanceof Ci.nsIObjectLoadingContent))
|
||||
return;
|
||||
|
||||
if (eventType == "PluginBindingAttached") {
|
||||
// The plugin binding fires this event when it is created.
|
||||
@ -308,13 +300,12 @@ var gPluginHandler = {
|
||||
break;
|
||||
|
||||
case "PluginInstantiated":
|
||||
case "PluginRemoved":
|
||||
shouldShowNotification = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Show the in-content UI if it's not too big. The crashed plugin handler already did this.
|
||||
if (eventType != "PluginCrashed" && eventType != "PluginRemoved") {
|
||||
if (eventType != "PluginCrashed") {
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
if (overlay != null) {
|
||||
if (!this.isTooSmall(plugin, overlay))
|
||||
@ -336,7 +327,7 @@ var gPluginHandler = {
|
||||
// Only show the notification after we've done the isTooSmall check, so
|
||||
// that the notification can decide whether to show the "alert" icon
|
||||
if (shouldShowNotification) {
|
||||
this._showClickToPlayNotification(browser);
|
||||
this._showClickToPlayNotification(browser, plugin, false);
|
||||
}
|
||||
},
|
||||
|
||||
@ -562,7 +553,7 @@ var gPluginHandler = {
|
||||
if (!(aEvent.originalTarget instanceof HTMLAnchorElement) &&
|
||||
(aEvent.originalTarget.getAttribute('anonid') != 'closeIcon') &&
|
||||
aEvent.button == 0 && aEvent.isTrusted) {
|
||||
gPluginHandler._showClickToPlayNotification(browser, plugin);
|
||||
gPluginHandler._showClickToPlayNotification(browser, plugin, true);
|
||||
aEvent.stopPropagation();
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
@ -607,7 +598,7 @@ var gPluginHandler = {
|
||||
}, true);
|
||||
|
||||
if (!playPreviewInfo.ignoreCTP) {
|
||||
gPluginHandler._showClickToPlayNotification(browser);
|
||||
gPluginHandler._showClickToPlayNotification(browser, aPlugin, false);
|
||||
}
|
||||
},
|
||||
|
||||
@ -625,14 +616,20 @@ var gPluginHandler = {
|
||||
if (gPluginHandler.canActivatePlugin(objLoadingContent))
|
||||
gPluginHandler._handleClickToPlayEvent(plugin);
|
||||
}
|
||||
gPluginHandler._showClickToPlayNotification(browser);
|
||||
gPluginHandler._showClickToPlayNotification(browser, null, false);
|
||||
},
|
||||
|
||||
_clickToPlayNotificationEventCallback: function PH_ctpEventCallback(event) {
|
||||
if (event == "showing") {
|
||||
gPluginHandler._makeCenterActions(this);
|
||||
Services.telemetry.getHistogramById("PLUGINS_NOTIFICATION_SHOWN")
|
||||
.add(!this.options.primaryPlugin);
|
||||
// Histograms always start at 0, even though our data starts at 1
|
||||
let histogramCount = this.options.centerActions.size - 1;
|
||||
if (histogramCount > 4) {
|
||||
histogramCount = 4;
|
||||
}
|
||||
Services.telemetry.getHistogramById("PLUGINS_NOTIFICATION_PLUGIN_COUNT")
|
||||
.add(histogramCount);
|
||||
}
|
||||
else if (event == "dismissed") {
|
||||
// Once the popup is dismissed, clicking the icon should show the full
|
||||
@ -655,86 +652,6 @@ var gPluginHandler = {
|
||||
return principal.origin;
|
||||
},
|
||||
|
||||
_makeCenterActions: function PH_makeCenterActions(notification) {
|
||||
let contentWindow = notification.browser.contentWindow;
|
||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
let principal = contentWindow.document.nodePrincipal;
|
||||
// This matches the behavior of nsPermssionManager, used for display purposes only
|
||||
let principalHost = this._getHostFromPrincipal(principal);
|
||||
|
||||
let centerActions = [];
|
||||
let pluginsFound = new Set();
|
||||
for (let plugin of cwu.plugins) {
|
||||
plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
if (plugin.getContentTypeForMIMEType(plugin.actualType) != Ci.nsIObjectLoadingContent.TYPE_PLUGIN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let pluginInfo = this._getPluginInfo(plugin);
|
||||
if (pluginInfo.permissionString === null) {
|
||||
Components.utils.reportError("No permission string for active plugin.");
|
||||
continue;
|
||||
}
|
||||
if (pluginsFound.has(pluginInfo.permissionString)) {
|
||||
continue;
|
||||
}
|
||||
pluginsFound.add(pluginInfo.permissionString);
|
||||
|
||||
// Add the per-site permissions and details URLs to pluginInfo here
|
||||
// because they are more expensive to compute and so we avoid it in
|
||||
// the tighter loop above.
|
||||
let permissionObj = Services.perms.
|
||||
getPermissionObject(principal, pluginInfo.permissionString, false);
|
||||
if (permissionObj) {
|
||||
pluginInfo.pluginPermissionHost = permissionObj.host;
|
||||
pluginInfo.pluginPermissionType = permissionObj.expireType;
|
||||
}
|
||||
else {
|
||||
pluginInfo.pluginPermissionHost = principalHost;
|
||||
pluginInfo.pluginPermissionType = undefined;
|
||||
}
|
||||
|
||||
let url;
|
||||
// TODO: allow the blocklist to specify a better link, bug 873093
|
||||
if (pluginInfo.blocklistState == Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE) {
|
||||
url = Services.urlFormatter.formatURLPref("plugins.update.url");
|
||||
}
|
||||
else if (pluginInfo.blocklistState != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
|
||||
url = Services.blocklist.getPluginBlocklistURL(pluginInfo.pluginTag);
|
||||
}
|
||||
else {
|
||||
url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "clicktoplay";
|
||||
}
|
||||
pluginInfo.detailsLink = url;
|
||||
|
||||
centerActions.push(pluginInfo);
|
||||
}
|
||||
|
||||
if (centerActions.length == 0) {
|
||||
// TODO: this is a temporary band-aid to avoid broken doorhangers
|
||||
// until bug 926605 is landed.
|
||||
notification.options.centerActions = [];
|
||||
setTimeout(() => PopupNotifications.remove(notification), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
centerActions.sort(function(a, b) {
|
||||
return a.pluginName.localeCompare(b.pluginName);
|
||||
});
|
||||
|
||||
notification.options.centerActions = centerActions;
|
||||
|
||||
// Histograms always start at 0, even though our data starts at 1
|
||||
let histogramCount = centerActions.length - 1;
|
||||
if (histogramCount > 4) {
|
||||
histogramCount = 4;
|
||||
}
|
||||
Services.telemetry.getHistogramById("PLUGINS_NOTIFICATION_PLUGIN_COUNT")
|
||||
.add(histogramCount);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called from the plugin doorhanger to set the new permissions for a plugin
|
||||
* and activate plugins if necessary.
|
||||
@ -798,6 +715,7 @@ var gPluginHandler = {
|
||||
let plugins = cwu.plugins;
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
|
||||
let pluginFound = false;
|
||||
for (let plugin of plugins) {
|
||||
plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
// canActivatePlugin will return false if this isn't a known plugin type,
|
||||
@ -809,60 +727,141 @@ var gPluginHandler = {
|
||||
overlay.removeEventListener("click", gPluginHandler._overlayClickListener, true);
|
||||
}
|
||||
plugin.playPlugin();
|
||||
pluginFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no instances of the plugin on the page any more, what the
|
||||
// user probably needs is for us to allow and then refresh.
|
||||
if (!pluginFound) {
|
||||
browser.reload();
|
||||
}
|
||||
},
|
||||
|
||||
_showClickToPlayNotification: function PH_showClickToPlayNotification(aBrowser, aPrimaryPlugin) {
|
||||
_showClickToPlayNotification: function PH_showClickToPlayNotification(aBrowser, aPlugin, aShowNow) {
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins", aBrowser);
|
||||
let plugins = [];
|
||||
|
||||
let contentWindow = aBrowser.contentWindow;
|
||||
let contentDoc = aBrowser.contentDocument;
|
||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
// cwu.plugins may contain non-plugin <object>s, filter them out
|
||||
let plugins = cwu.plugins.filter((plugin) =>
|
||||
plugin.getContentTypeForMIMEType(plugin.actualType) == Ci.nsIObjectLoadingContent.TYPE_PLUGIN);
|
||||
if (plugins.length == 0) {
|
||||
if (notification) {
|
||||
PopupNotifications.remove(notification);
|
||||
// if aPlugin is null, that means the user has navigated back to a page with plugins, and we need
|
||||
// to collect all the plugins
|
||||
if (aPlugin === null) {
|
||||
let contentWindow = aBrowser.contentWindow;
|
||||
let contentDoc = aBrowser.contentDocument;
|
||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
// cwu.plugins may contain non-plugin <object>s, filter them out
|
||||
plugins = cwu.plugins.filter((plugin) =>
|
||||
plugin.getContentTypeForMIMEType(plugin.actualType) == Ci.nsIObjectLoadingContent.TYPE_PLUGIN);
|
||||
|
||||
if (plugins.length == 0) {
|
||||
if (notification) {
|
||||
PopupNotifications.remove(notification);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
plugins = [aPlugin];
|
||||
}
|
||||
|
||||
// If this is a new notification, create a centerActions map, otherwise append
|
||||
let centerActions;
|
||||
if (notification) {
|
||||
centerActions = notification.options.centerActions;
|
||||
} else {
|
||||
centerActions = new Map();
|
||||
}
|
||||
|
||||
let principal = aBrowser.contentDocument.nodePrincipal;
|
||||
let principalHost = this._getHostFromPrincipal(principal);
|
||||
|
||||
for (var plugin of plugins) {
|
||||
let pluginInfo = this._getPluginInfo(plugin);
|
||||
if (pluginInfo.permissionString === null) {
|
||||
Cu.reportError("No permission string for active plugin.");
|
||||
continue;
|
||||
}
|
||||
if (centerActions.has(pluginInfo.permissionString)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Assume that plugins are hidden and then set override later
|
||||
pluginInfo.hidden = true;
|
||||
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
if (overlay && overlay.style.visibility != "hidden" && overlay.style.visibility != "") {
|
||||
pluginInfo.hidden = false;
|
||||
}
|
||||
|
||||
let permissionObj = Services.perms.
|
||||
getPermissionObject(principal, pluginInfo.permissionString, false);
|
||||
if (permissionObj) {
|
||||
pluginInfo.pluginPermissionHost = permissionObj.host;
|
||||
pluginInfo.pluginPermissionType = permissionObj.expireType;
|
||||
}
|
||||
else {
|
||||
pluginInfo.pluginPermissionHost = principalHost;
|
||||
pluginInfo.pluginPermissionType = undefined;
|
||||
}
|
||||
|
||||
let url;
|
||||
// TODO: allow the blocklist to specify a better link, bug 873093
|
||||
if (pluginInfo.blocklistState == Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE) {
|
||||
url = Services.urlFormatter.formatURLPref("plugins.update.url");
|
||||
}
|
||||
else if (pluginInfo.blocklistState != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
|
||||
url = Services.blocklist.getPluginBlocklistURL(pluginInfo.pluginTag);
|
||||
}
|
||||
else {
|
||||
url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "clicktoplay";
|
||||
}
|
||||
pluginInfo.detailsLink = url;
|
||||
|
||||
centerActions.set(pluginInfo.permissionString, pluginInfo);
|
||||
}
|
||||
|
||||
let pluginBlocked = false;
|
||||
let pluginHidden = false;
|
||||
for (let pluginInfo of centerActions.values()) {
|
||||
let fallbackType = pluginInfo.fallbackType;
|
||||
if (fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE ||
|
||||
fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE ||
|
||||
fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED) {
|
||||
pluginBlocked = true;
|
||||
pluginHidden = false;
|
||||
break;
|
||||
}
|
||||
if (fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY && pluginInfo.hidden) {
|
||||
pluginHidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
let iconClasses = document.getElementById("plugins-notification-icon").classList;
|
||||
iconClasses.toggle("plugin-blocked", pluginBlocked);
|
||||
iconClasses.toggle("plugin-hidden", pluginHidden);
|
||||
|
||||
let primaryPluginPermission = null;
|
||||
if (aShowNow) {
|
||||
primaryPluginPermission = this._getPluginInfo(aPlugin).permissionString;
|
||||
}
|
||||
|
||||
if (notification) {
|
||||
// Don't modify the notification UI while it's on the screen, that would be
|
||||
// jumpy and might allow clickjacking.
|
||||
if (aShowNow) {
|
||||
notification.options.primaryPlugin = primaryPluginPermission;
|
||||
notification.reshow();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let icon = 'plugins-notification-icon';
|
||||
for (let plugin of plugins) {
|
||||
let fallbackType = plugin.pluginFallbackType;
|
||||
if (fallbackType == plugin.PLUGIN_VULNERABLE_UPDATABLE ||
|
||||
fallbackType == plugin.PLUGIN_VULNERABLE_NO_UPDATE ||
|
||||
fallbackType == plugin.PLUGIN_BLOCKLISTED) {
|
||||
icon = 'blocked-plugins-notification-icon';
|
||||
break;
|
||||
}
|
||||
if (fallbackType == plugin.PLUGIN_CLICK_TO_PLAY) {
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
if (!overlay || overlay.style.visibility == 'hidden') {
|
||||
icon = 'alert-plugins-notification-icon';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let dismissed = notification ? notification.dismissed : true;
|
||||
if (aPrimaryPlugin)
|
||||
dismissed = false;
|
||||
|
||||
let primaryPluginPermission = null;
|
||||
if (aPrimaryPlugin) {
|
||||
primaryPluginPermission = this._getPluginInfo(aPrimaryPlugin).permissionString;
|
||||
}
|
||||
|
||||
let options = {
|
||||
dismissed: dismissed,
|
||||
dismissed: !aShowNow,
|
||||
eventCallback: this._clickToPlayNotificationEventCallback,
|
||||
primaryPlugin: primaryPluginPermission
|
||||
primaryPlugin: primaryPluginPermission,
|
||||
centerActions: centerActions
|
||||
};
|
||||
PopupNotifications.show(aBrowser, "click-to-play-plugins",
|
||||
"", icon,
|
||||
"", "plugins-notification-icon",
|
||||
null, null, options);
|
||||
},
|
||||
|
||||
|
@ -756,7 +756,6 @@ var gBrowserInit = {
|
||||
gBrowser.addEventListener("PluginCrashed", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginOutdated", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginInstantiated", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginRemoved", gPluginHandler, true);
|
||||
|
||||
gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true);
|
||||
|
||||
|
@ -534,8 +534,6 @@
|
||||
<image id="webapps-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="plugins-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="web-notifications-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="alert-plugins-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="blocked-plugins-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="plugin-install-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="mixed-content-blocked-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="webRTC-shareDevices-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
@ -571,7 +569,7 @@
|
||||
onclick="gPopupBlockerObserver.onReportButtonClick(event);"/>
|
||||
<image id="star-button"
|
||||
class="urlbar-icon"
|
||||
onclick="BookmarkingUI.onCommand(event);"/>
|
||||
onclick="if (event.button === 0) BookmarkingUI.onCommand(event);"/>
|
||||
<image id="go-button"
|
||||
class="urlbar-icon"
|
||||
tooltiptext="&goEndCap.tooltip;"
|
||||
|
@ -1277,7 +1277,7 @@ nsContextMenu.prototype = {
|
||||
},
|
||||
|
||||
playPlugin: function() {
|
||||
gPluginHandler._showClickToPlayNotification(this.browser, this.target);
|
||||
gPluginHandler._showClickToPlayNotification(this.browser, this.target, true);
|
||||
},
|
||||
|
||||
hidePlugin: function() {
|
||||
|
@ -60,7 +60,6 @@ support-files =
|
||||
plugin_clickToPlayDeny.html
|
||||
plugin_data_url.html
|
||||
plugin_hidden_to_visible.html
|
||||
plugin_iframe.html
|
||||
plugin_small.html
|
||||
plugin_test.html
|
||||
plugin_test2.html
|
||||
@ -87,7 +86,6 @@ support-files =
|
||||
|
||||
[browser_CTP_data_urls.js]
|
||||
[browser_CTP_drag_drop.js]
|
||||
[browser_CTP_iframe.js]
|
||||
[browser_CTP_nonplugins.js]
|
||||
[browser_CTP_resize.js]
|
||||
[browser_URLBarSetURI.js]
|
||||
|
@ -71,32 +71,43 @@ function test1() {
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(!objLoadingContent.activated, "Test 1, Plugin should not be activated");
|
||||
|
||||
window.document.addEventListener("popupshown", test2, false);
|
||||
// When the popupshown DOM event is fired, the actual showing of the popup
|
||||
// may still be pending. Clear the event loop before continuing so that
|
||||
// subsequently-opened popups aren't cancelled by accident.
|
||||
let goToNext = function() {
|
||||
window.document.removeEventListener("popupshown", goToNext, false);
|
||||
executeSoon(test2);
|
||||
};
|
||||
window.document.addEventListener("popupshown", goToNext, false);
|
||||
EventUtils.synthesizeMouseAtCenter(plugin,
|
||||
{ type: "contextmenu", button: 2 },
|
||||
gTestBrowser.contentWindow);
|
||||
}
|
||||
|
||||
function test2() {
|
||||
window.document.removeEventListener("popupshown", test2, false);
|
||||
let activate = window.document.getElementById("context-ctp-play");
|
||||
ok(activate, "Test 2, Should have a context menu entry for activating the plugin");
|
||||
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(notification, "Test 2, Should have a click-to-play notification");
|
||||
ok(notification.dismissed, "Test 2, notification should be dismissed");
|
||||
|
||||
// Trigger the click-to-play popup
|
||||
activate.doCommand();
|
||||
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(notification, "Test 2, Should have a click-to-play notification");
|
||||
ok(!notification.dismissed, "Test 2, The click-to-play notification should not be dismissed");
|
||||
waitForCondition(() => !notification.dismissed,
|
||||
test3, "Test 2, waited too long for context activation");
|
||||
}
|
||||
|
||||
function test3() {
|
||||
// Activate the plugin
|
||||
PopupNotifications.panel.firstChild._primaryButton.click();
|
||||
|
||||
let plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
waitForCondition(() => objLoadingContent.activated, test3, "Waited too long for plugin to activate");
|
||||
waitForCondition(() => objLoadingContent.activated, test4, "Waited too long for plugin to activate");
|
||||
}
|
||||
|
||||
function test3() {
|
||||
function test4() {
|
||||
finishTest();
|
||||
}
|
||||
|
@ -161,10 +161,10 @@ function test2b() {
|
||||
|
||||
// Simulate choosing "Allow now" for the test plugin
|
||||
notification.reshow();
|
||||
is(notification.options.centerActions.length, 2, "Test 2b, Should have two types of plugin in the notification");
|
||||
is(notification.options.centerActions.size, 2, "Test 2b, Should have two types of plugin in the notification");
|
||||
|
||||
var centerAction = null;
|
||||
for (var action of notification.options.centerActions) {
|
||||
for (var action of notification.options.centerActions.values()) {
|
||||
if (action.pluginName == "Test") {
|
||||
centerAction = action;
|
||||
break;
|
||||
|
@ -64,13 +64,11 @@ function part5() {
|
||||
gBrowser.selectedBrowser.removeEventListener("PluginBindingAttached", handleEvent);
|
||||
ok(PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser), "Should have a click-to-play notification in the initial tab");
|
||||
|
||||
gNextTest = part6;
|
||||
gNewWindow = gBrowser.replaceTabWithWindow(gBrowser.selectedTab);
|
||||
gNewWindow.addEventListener("load", handleEvent, true);
|
||||
waitForFocus(part6, gNewWindow);
|
||||
}
|
||||
|
||||
function part6() {
|
||||
gNewWindow.removeEventListener("load", handleEvent);
|
||||
let condition = function() PopupNotifications.getNotification("click-to-play-plugins", gNewWindow.gBrowser.selectedBrowser);
|
||||
waitForCondition(condition, part7, "Waited too long for click-to-play notification");
|
||||
}
|
||||
|
@ -1,135 +0,0 @@
|
||||
var rootDir = getRootDirectory(gTestPath);
|
||||
const gTestRoot = rootDir;
|
||||
const gHttpTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
|
||||
|
||||
var gTestBrowser = null;
|
||||
var gNextTest = null;
|
||||
var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost);
|
||||
var gPageLoads = 0;
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// This listens for the next opened tab and checks it is of the right url.
|
||||
// opencallback is called when the new tab is fully loaded
|
||||
// closecallback is called when the tab is closed
|
||||
function TabOpenListener(url, opencallback, closecallback) {
|
||||
this.url = url;
|
||||
this.opencallback = opencallback;
|
||||
this.closecallback = closecallback;
|
||||
|
||||
gBrowser.tabContainer.addEventListener("TabOpen", this, false);
|
||||
}
|
||||
|
||||
TabOpenListener.prototype = {
|
||||
url: null,
|
||||
opencallback: null,
|
||||
closecallback: null,
|
||||
tab: null,
|
||||
browser: null,
|
||||
|
||||
handleEvent: function(event) {
|
||||
if (event.type == "TabOpen") {
|
||||
gBrowser.tabContainer.removeEventListener("TabOpen", this, false);
|
||||
this.tab = event.originalTarget;
|
||||
this.browser = this.tab.linkedBrowser;
|
||||
gBrowser.addEventListener("pageshow", this, false);
|
||||
} else if (event.type == "pageshow") {
|
||||
if (event.target.location.href != this.url)
|
||||
return;
|
||||
gBrowser.removeEventListener("pageshow", this, false);
|
||||
this.tab.addEventListener("TabClose", this, false);
|
||||
var url = this.browser.contentDocument.location.href;
|
||||
is(url, this.url, "Should have opened the correct tab");
|
||||
this.opencallback(this.tab, this.browser.contentWindow);
|
||||
} else if (event.type == "TabClose") {
|
||||
if (event.originalTarget != this.tab)
|
||||
return;
|
||||
this.tab.removeEventListener("TabClose", this, false);
|
||||
this.opencallback = null;
|
||||
this.tab = null;
|
||||
this.browser = null;
|
||||
// Let the window close complete
|
||||
executeSoon(this.closecallback);
|
||||
this.closecallback = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
registerCleanupFunction(function() {
|
||||
clearAllPluginPermissions();
|
||||
Services.prefs.clearUserPref("extensions.blocklist.suppressUI");
|
||||
});
|
||||
Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true);
|
||||
|
||||
var newTab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = newTab;
|
||||
gTestBrowser = gBrowser.selectedBrowser;
|
||||
gTestBrowser.addEventListener("load", pageLoad, true);
|
||||
|
||||
Services.prefs.setBoolPref("plugins.click_to_play", true);
|
||||
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY);
|
||||
|
||||
prepareTest(runAfterPluginBindingAttached(test1), gHttpTestRoot + "plugin_iframe.html");
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
clearAllPluginPermissions();
|
||||
gTestBrowser.removeEventListener("load", pageLoad, true);
|
||||
gBrowser.removeCurrentTab();
|
||||
window.focus();
|
||||
finish();
|
||||
}
|
||||
|
||||
function pageLoad() {
|
||||
// Wait for the iframe to be loaded as well.
|
||||
if (gPageLoads++ < 1)
|
||||
return;
|
||||
|
||||
// The plugin events are async dispatched and can come after the load event
|
||||
// This just allows the events to fire before we then go on to test the states.
|
||||
executeSoon(gNextTest);
|
||||
}
|
||||
|
||||
function prepareTest(nextTest, url) {
|
||||
gNextTest = nextTest;
|
||||
gTestBrowser.contentWindow.location = url;
|
||||
}
|
||||
|
||||
// Due to layout being async, "PluginBindAttached" may trigger later.
|
||||
// This wraps a function to force a layout flush, thus triggering it,
|
||||
// and schedules the function execution so they're definitely executed
|
||||
// afterwards.
|
||||
function runAfterPluginBindingAttached(func) {
|
||||
return function() {
|
||||
let doc = gTestBrowser.contentDocument.getElementById('frame').contentDocument;
|
||||
let elems = doc.getElementsByTagName('embed');
|
||||
if (elems.length < 1) {
|
||||
elems = doc.getElementsByTagName('object');
|
||||
}
|
||||
elems[0].clientTop;
|
||||
executeSoon(func);
|
||||
};
|
||||
}
|
||||
|
||||
// Test that we don't show a doorhanger after removing the last plugin
|
||||
// when the plugin was in an iframe.
|
||||
|
||||
function test1() {
|
||||
let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(popupNotification, "Test 1, Should have a click-to-play notification");
|
||||
|
||||
let frame = gTestBrowser.contentDocument.getElementById("frame");
|
||||
frame.parentElement.removeChild(frame);
|
||||
|
||||
let condition = () => {
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
if (notification) {
|
||||
notification.reshow();
|
||||
}
|
||||
return !notification;
|
||||
}
|
||||
|
||||
waitForCondition(condition, finishTest, "Test1, Waited too long for notification too be removed");
|
||||
}
|
@ -149,12 +149,12 @@ function test2() {
|
||||
let plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
plugin.parentNode.removeChild(plugin);
|
||||
|
||||
runAfterPluginRemoved(() => executeSoon(test3));
|
||||
executeSoon(test3);
|
||||
}
|
||||
|
||||
function test3() {
|
||||
let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(!popupNotification, "Test 3, Should not have a click-to-play notification");
|
||||
ok(popupNotification, "Test 3, Should still have a click-to-play notification");
|
||||
|
||||
finishTest();
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ function pluginBindingAttached() {
|
||||
ok(notification, "should have popup notification");
|
||||
// We don't set up the action list until the notification is shown
|
||||
notification.reshow();
|
||||
is(notification.options.centerActions.length, 1, "should be 1 type of plugin in the popup notification");
|
||||
is(notification.options.centerActions.size, 1, "should be 1 type of plugin in the popup notification");
|
||||
XPCNativeWrapper.unwrap(gTestBrowser.contentWindow).addSecondPlugin();
|
||||
} else if (gNumPluginBindingsAttached == 2) {
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
@ -51,7 +51,7 @@ function pluginBindingAttached() {
|
||||
var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(notification, "should have popup notification");
|
||||
notification.reshow();
|
||||
is(notification.options.centerActions.length, 2, "should be 2 types of plugin in the popup notification");
|
||||
is(notification.options.centerActions.size, 2, "should be 2 types of plugin in the popup notification");
|
||||
finish();
|
||||
} else {
|
||||
ok(false, "if we've gotten here, something is quite wrong");
|
||||
|
@ -179,7 +179,7 @@ function test5() {
|
||||
ok(notification.dismissed, "Test 5: The plugin notification should be dismissed by default");
|
||||
|
||||
notification.reshow();
|
||||
is(notification.options.centerActions.length, 1, "Test 5: Only the blocked plugin should be present in the notification");
|
||||
is(notification.options.centerActions.size, 1, "Test 5: Only the blocked plugin should be present in the notification");
|
||||
ok(PopupNotifications.panel.firstChild._buttonContainer.hidden, "Part 5: The blocked plugins notification should not have any buttons visible.");
|
||||
|
||||
ok(!gTestBrowser.missingPlugins, "Test 5, Should not be a missing plugin list");
|
||||
@ -441,10 +441,11 @@ function test18f() {
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(!objLoadingContent.activated, "Test 18f, Plugin should not be activated");
|
||||
|
||||
// XXXBAD: this code doesn't do what you think it does! it is actually
|
||||
// observing the "removed" event of the old notification, since we create
|
||||
// a *new* one when the plugin is clicked.
|
||||
notification.options.eventCallback = function() { executeSoon(test18g); };
|
||||
var oldEventCallback = notification.options.eventCallback;
|
||||
notification.options.eventCallback = function() {
|
||||
oldEventCallback();
|
||||
executeSoon(test18g);
|
||||
};
|
||||
EventUtils.synthesizeMouseAtCenter(plugin, {}, gTestBrowser.contentWindow);
|
||||
}
|
||||
|
||||
@ -603,10 +604,10 @@ function test21a() {
|
||||
|
||||
// we have to actually show the panel to get the bindings to instantiate
|
||||
notification.reshow();
|
||||
is(notification.options.centerActions.length, 2, "Test 21a, Should have two types of plugin in the notification");
|
||||
is(notification.options.centerActions.size, 2, "Test 21a, Should have two types of plugin in the notification");
|
||||
|
||||
var centerAction = null;
|
||||
for (var action of notification.options.centerActions) {
|
||||
for (var action of notification.options.centerActions.values()) {
|
||||
if (action.pluginName == "Test") {
|
||||
centerAction = action;
|
||||
break;
|
||||
@ -640,7 +641,7 @@ function test21c() {
|
||||
ok(notification, "Test 21c, Should have a click-to-play notification");
|
||||
|
||||
notification.reshow();
|
||||
ok(notification.options.centerActions.length == 2, "Test 21c, Should have one type of plugin in the notification");
|
||||
ok(notification.options.centerActions.size == 2, "Test 21c, Should have one type of plugin in the notification");
|
||||
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("test");
|
||||
@ -661,7 +662,7 @@ function test21c() {
|
||||
}
|
||||
|
||||
var centerAction = null;
|
||||
for (var action of notification.options.centerActions) {
|
||||
for (var action of notification.options.centerActions.values()) {
|
||||
if (action.pluginName == "Second Test") {
|
||||
centerAction = action;
|
||||
break;
|
||||
|
@ -68,7 +68,7 @@ function testActivateAddSameTypePart2() {
|
||||
function testActivateAddSameTypePart3() {
|
||||
let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
let centerAction = null;
|
||||
for (let action of popupNotification.options.centerActions) {
|
||||
for (let action of popupNotification.options.centerActions.values()) {
|
||||
if (action.pluginName == "Test") {
|
||||
centerAction = action;
|
||||
break;
|
||||
@ -142,7 +142,7 @@ function testActivateAddDifferentTypePart2() {
|
||||
|
||||
function testActivateAddDifferentTypePart3() {
|
||||
let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
is(popupNotification.options.centerActions.length, 1, "Should be one plugin action");
|
||||
is(popupNotification.options.centerActions.size, 1, "Should be one plugin action");
|
||||
|
||||
let plugin = gTestBrowser.contentDocument.getElementsByTagName("embed")[0];
|
||||
ok(!plugin.activated, "testActivateAddDifferentTypePart3: plugin should not be activated");
|
||||
|
@ -1,11 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="plugin_test.html" id="frame" width="300" height="300">
|
||||
This should load plugin_test.html
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
@ -1567,14 +1567,20 @@
|
||||
<field name="_items">[]</field>
|
||||
<constructor><![CDATA[
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
for (let action of this.notification.options.centerActions) {
|
||||
let sortedActions = [];
|
||||
for (let action of this.notification.options.centerActions.values()) {
|
||||
sortedActions.push(action);
|
||||
}
|
||||
sortedActions.sort((a, b) => a.pluginName.localeCompare(b.pluginName));
|
||||
|
||||
for (let action of sortedActions) {
|
||||
let item = document.createElementNS(XUL_NS, "row");
|
||||
item.setAttribute("class", "plugin-popupnotification-centeritem");
|
||||
item.action = action;
|
||||
this.appendChild(item);
|
||||
this._items.push(item);
|
||||
}
|
||||
switch (this.notification.options.centerActions.length) {
|
||||
switch (this._items.length) {
|
||||
case 0:
|
||||
PopupNotifications._dismiss();
|
||||
break;
|
||||
@ -1639,7 +1645,7 @@
|
||||
</method>
|
||||
<method name="_setupSingleState">
|
||||
<body><![CDATA[
|
||||
var action = this.notification.options.centerActions[0];
|
||||
var action = this._items[0].action;
|
||||
var host = action.pluginPermissionHost;
|
||||
|
||||
let label, linkLabel, linkUrl, button1, button2;
|
||||
@ -1803,7 +1809,7 @@
|
||||
<method name="_singleActivateNow">
|
||||
<body><![CDATA[
|
||||
gPluginHandler._updatePluginPermission(this.notification,
|
||||
this.notification.options.centerActions[0],
|
||||
this._items[0].action,
|
||||
"allownow");
|
||||
this._cancel();
|
||||
]]></body>
|
||||
@ -1811,7 +1817,7 @@
|
||||
<method name="_singleBlock">
|
||||
<body><![CDATA[
|
||||
gPluginHandler._updatePluginPermission(this.notification,
|
||||
this.notification.options.centerActions[0],
|
||||
this._items[0].action,
|
||||
"block");
|
||||
this._cancel();
|
||||
]]></body>
|
||||
@ -1819,7 +1825,7 @@
|
||||
<method name="_singleActivateAlways">
|
||||
<body><![CDATA[
|
||||
gPluginHandler._updatePluginPermission(this.notification,
|
||||
this.notification.options.centerActions[0],
|
||||
this._items[0].action,
|
||||
"allowalways");
|
||||
this._cancel();
|
||||
]]></body>
|
||||
@ -1827,7 +1833,7 @@
|
||||
<method name="_singleContinue">
|
||||
<body><![CDATA[
|
||||
gPluginHandler._updatePluginPermission(this.notification,
|
||||
this.notification.options.centerActions[0],
|
||||
this._items[0].action,
|
||||
"continue");
|
||||
this._cancel();
|
||||
]]></body>
|
||||
|
@ -1964,13 +1964,21 @@ ContentPermissionPrompt.prototype = {
|
||||
|
||||
prompt: function CPP_prompt(request) {
|
||||
|
||||
// Only allow exactly one permission rquest here.
|
||||
let types = request.types.QueryInterface(Ci.nsIArray);
|
||||
if (types.length != 1) {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
let perm = types.queryElementAt(0, Ci.nsIContentPermissionType);
|
||||
|
||||
const kFeatureKeys = { "geolocation" : "geo",
|
||||
"desktop-notification" : "desktop-notification",
|
||||
"pointerLock" : "pointerLock",
|
||||
};
|
||||
|
||||
// Make sure that we support the request.
|
||||
if (!(request.type in kFeatureKeys)) {
|
||||
if (!(perm.type in kFeatureKeys)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1982,7 +1990,7 @@ ContentPermissionPrompt.prototype = {
|
||||
return;
|
||||
|
||||
var autoAllow = false;
|
||||
var permissionKey = kFeatureKeys[request.type];
|
||||
var permissionKey = kFeatureKeys[perm.type];
|
||||
var result = Services.perms.testExactPermissionFromPrincipal(requestingPrincipal, permissionKey);
|
||||
|
||||
if (result == Ci.nsIPermissionManager.DENY_ACTION) {
|
||||
@ -1993,14 +2001,14 @@ ContentPermissionPrompt.prototype = {
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
autoAllow = true;
|
||||
// For pointerLock, we still want to show a warning prompt.
|
||||
if (request.type != "pointerLock") {
|
||||
if (perm.type != "pointerLock") {
|
||||
request.allow();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Show the prompt.
|
||||
switch (request.type) {
|
||||
switch (perm.type) {
|
||||
case "geolocation":
|
||||
this._promptGeo(request);
|
||||
break;
|
||||
|
@ -64,7 +64,7 @@ function test() {
|
||||
|
||||
MockFilePicker.returnFiles = [aFile];
|
||||
MockFilePicker.displayDirectory = null;
|
||||
aWin.getTargetFile(params, function() {
|
||||
aWin.promiseTargetFile(params).then(function() {
|
||||
// File picker should start with expected display dir.
|
||||
is(MockFilePicker.displayDirectory.path, aDisplayDir.path,
|
||||
"File picker should start with browser.download.lastDir");
|
||||
@ -78,7 +78,7 @@ function test() {
|
||||
gDownloadLastDir.cleanupPrivateFile();
|
||||
aWin.close();
|
||||
aCallback();
|
||||
});
|
||||
}).then(null, function() { ok(false); });
|
||||
}
|
||||
|
||||
testOnWindow(false, function(win, downloadDir) {
|
||||
|
@ -135,7 +135,7 @@ function once(aTarget, aEventName, aUseCapture = false) {
|
||||
|
||||
function waitForFrame(aDebuggee) {
|
||||
let deferred = promise.defer();
|
||||
aDebuggee.mozRequestAnimationFrame(deferred.resolve);
|
||||
aDebuggee.requestAnimationFrame(deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
|
@ -487,7 +487,6 @@ function SideMenuGroup(aWidget, aName, aOptions={}) {
|
||||
if (aOptions.showCheckbox) {
|
||||
let checkbox = this._checkbox = makeCheckbox(title, { description: aName });
|
||||
checkbox.className = "side-menu-widget-group-checkbox";
|
||||
checkbox.setAttribute("align", "start");
|
||||
}
|
||||
|
||||
title.appendChild(name);
|
||||
@ -592,7 +591,6 @@ function SideMenuItem(aGroup, aContents, aTooltip, aAttachment={}, aOptions={})
|
||||
if (aOptions.showCheckbox) {
|
||||
let checkbox = this._checkbox = makeCheckbox(container, aAttachment);
|
||||
checkbox.className = "side-menu-widget-item-checkbox";
|
||||
checkbox.setAttribute("align", "start");
|
||||
}
|
||||
|
||||
container.appendChild(target);
|
||||
|
@ -24,6 +24,11 @@
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
.side-menu-widget-group-checkbox .checkbox-label-box,
|
||||
.side-menu-widget-item-checkbox .checkbox-label-box {
|
||||
display: none; /* See bug 669507 */
|
||||
}
|
||||
|
||||
/* VariablesView */
|
||||
|
||||
.variables-view-container {
|
||||
|
@ -31,8 +31,10 @@ function testPropertyProvider() {
|
||||
completion = JSPropertyProvider(content, strComplete);
|
||||
ok(completion.matches.length == 2, "two matches found");
|
||||
ok(completion.matchProp == "locatio", "matching part is 'test'");
|
||||
ok(completion.matches[0] == "location", "the first match is 'location'");
|
||||
ok(completion.matches[1] == "locationbar", "the second match is 'locationbar'");
|
||||
var matches = completion.matches;
|
||||
matches.sort();
|
||||
ok(matches[0] == "location", "the first match is 'location'");
|
||||
ok(matches[1] == "locationbar", "the second match is 'locationbar'");
|
||||
|
||||
finishTest();
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
This is the pdf.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 0.8.629
|
||||
Current extension version is: 0.8.641
|
||||
|
||||
|
@ -20,8 +20,8 @@ if (typeof PDFJS === 'undefined') {
|
||||
(typeof window !== 'undefined' ? window : this).PDFJS = {};
|
||||
}
|
||||
|
||||
PDFJS.version = '0.8.629';
|
||||
PDFJS.build = 'b16b3be';
|
||||
PDFJS.version = '0.8.641';
|
||||
PDFJS.build = '19485c3';
|
||||
|
||||
(function pdfjsWrapper() {
|
||||
// Use strict in our context only - users might not want it
|
||||
@ -6575,6 +6575,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
var bounds = Util.getAxialAlignedBoundingBox(
|
||||
group.bbox,
|
||||
currentCtx.mozCurrentTransform);
|
||||
// Clip the bounding box to the current canvas.
|
||||
bounds = Util.intersect(bounds, [0,
|
||||
0,
|
||||
currentCtx.canvas.width,
|
||||
currentCtx.canvas.height]);
|
||||
// Use ceil in case we're between sizes so we don't create canvas that is
|
||||
// too small and make the canvas at least 1x1 pixels.
|
||||
var drawnWidth = Math.max(Math.ceil(bounds[2] - bounds[0]), 1);
|
||||
|
@ -20,8 +20,8 @@ if (typeof PDFJS === 'undefined') {
|
||||
(typeof window !== 'undefined' ? window : this).PDFJS = {};
|
||||
}
|
||||
|
||||
PDFJS.version = '0.8.629';
|
||||
PDFJS.build = 'b16b3be';
|
||||
PDFJS.version = '0.8.641';
|
||||
PDFJS.build = '19485c3';
|
||||
|
||||
(function pdfjsWrapper() {
|
||||
// Use strict in our context only - users might not want it
|
||||
|
@ -223,7 +223,7 @@ limitations under the License.
|
||||
data-l10n-id="page_rotate_ccw"></menuitem>
|
||||
</menu>
|
||||
|
||||
<div id="viewerContainer">
|
||||
<div id="viewerContainer" tabindex="0">
|
||||
<div id="viewer"></div>
|
||||
</div>
|
||||
|
||||
|
@ -1299,11 +1299,12 @@ var SecondaryToolbar = {
|
||||
|
||||
initialize: function secondaryToolbarInitialize(options) {
|
||||
this.toolbar = options.toolbar;
|
||||
this.presentationMode = options.presentationMode;
|
||||
this.buttonContainer = this.toolbar.firstElementChild;
|
||||
|
||||
// Define the toolbar buttons.
|
||||
this.toggleButton = options.toggleButton;
|
||||
this.presentationMode = options.presentationMode;
|
||||
this.presentationModeButton = options.presentationModeButton;
|
||||
this.openFile = options.openFile;
|
||||
this.print = options.print;
|
||||
this.download = options.download;
|
||||
@ -1315,7 +1316,8 @@ var SecondaryToolbar = {
|
||||
// Attach the event listeners.
|
||||
var elements = [
|
||||
{ element: this.toggleButton, handler: this.toggle },
|
||||
{ element: this.presentationMode, handler: this.presentationModeClick },
|
||||
{ element: this.presentationModeButton,
|
||||
handler: this.presentationModeClick },
|
||||
{ element: this.openFile, handler: this.openFileClick },
|
||||
{ element: this.print, handler: this.printClick },
|
||||
{ element: this.download, handler: this.downloadClick },
|
||||
@ -1335,7 +1337,7 @@ var SecondaryToolbar = {
|
||||
|
||||
// Event handling functions.
|
||||
presentationModeClick: function secondaryToolbarPresentationModeClick(evt) {
|
||||
PresentationMode.request();
|
||||
this.presentationMode.request();
|
||||
this.close();
|
||||
},
|
||||
|
||||
@ -1372,7 +1374,7 @@ var SecondaryToolbar = {
|
||||
|
||||
// Misc. functions for interacting with the toolbar.
|
||||
setMaxHeight: function secondaryToolbarSetMaxHeight(container) {
|
||||
if (!container) {
|
||||
if (!container || !this.buttonContainer) {
|
||||
return;
|
||||
}
|
||||
this.newContainerHeight = container.clientHeight;
|
||||
@ -1410,10 +1412,6 @@ var SecondaryToolbar = {
|
||||
} else {
|
||||
this.open();
|
||||
}
|
||||
},
|
||||
|
||||
get isOpen() {
|
||||
return this.opened;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1506,6 +1504,8 @@ var PresentationMode = {
|
||||
this.container = options.container;
|
||||
this.secondaryToolbar = options.secondaryToolbar;
|
||||
|
||||
this.viewer = this.container.firstElementChild;
|
||||
|
||||
this.firstPage = options.firstPage;
|
||||
this.lastPage = options.lastPage;
|
||||
this.pageRotateCw = options.pageRotateCw;
|
||||
@ -1538,7 +1538,8 @@ var PresentationMode = {
|
||||
},
|
||||
|
||||
request: function presentationModeRequest() {
|
||||
if (!PDFView.supportsFullscreen || this.isFullscreen) {
|
||||
if (!PDFView.supportsFullscreen || this.isFullscreen ||
|
||||
!this.viewer.hasChildNodes()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1720,8 +1721,10 @@ var PDFView = {
|
||||
|
||||
SecondaryToolbar.initialize({
|
||||
toolbar: document.getElementById('secondaryToolbar'),
|
||||
presentationMode: PresentationMode,
|
||||
toggleButton: document.getElementById('secondaryToolbarToggle'),
|
||||
presentationMode: document.getElementById('secondaryPresentationMode'),
|
||||
presentationModeButton:
|
||||
document.getElementById('secondaryPresentationMode'),
|
||||
openFile: document.getElementById('secondaryOpenFile'),
|
||||
print: document.getElementById('secondaryPrint'),
|
||||
download: document.getElementById('secondaryDownload'),
|
||||
@ -1968,8 +1971,8 @@ var PDFView = {
|
||||
},
|
||||
|
||||
get isHorizontalScrollbarEnabled() {
|
||||
var div = document.getElementById('viewerContainer');
|
||||
return div.scrollWidth > div.clientWidth;
|
||||
return (PresentationMode.active ? false :
|
||||
(this.container.scrollWidth > this.container.clientWidth));
|
||||
},
|
||||
|
||||
initPassiveLoading: function pdfViewInitPassiveLoading() {
|
||||
@ -3230,6 +3233,7 @@ var PageView = function pageView(container, id, scale,
|
||||
this.scrollIntoView = function pageViewScrollIntoView(dest) {
|
||||
if (PresentationMode.active) { // Avoid breaking presentation mode.
|
||||
dest = null;
|
||||
PDFView.setScale(PDFView.currentScaleValue, true, true);
|
||||
}
|
||||
if (!dest) {
|
||||
scrollIntoView(div);
|
||||
@ -4554,7 +4558,7 @@ window.addEventListener('DOMMouseScroll', function(evt) {
|
||||
|
||||
window.addEventListener('click', function click(evt) {
|
||||
if (!PresentationMode.active) {
|
||||
if (SecondaryToolbar.isOpen && PDFView.container.contains(evt.target)) {
|
||||
if (SecondaryToolbar.opened && PDFView.container.contains(evt.target)) {
|
||||
SecondaryToolbar.close();
|
||||
}
|
||||
} else if (evt.button === 0) {
|
||||
@ -4649,6 +4653,9 @@ window.addEventListener('keydown', function keydown(evt) {
|
||||
return; // ignoring if the 'toolbar' element is focused
|
||||
curElement = curElement.parentNode;
|
||||
}
|
||||
// Workaround for issue in Firefox, that prevents scroll keys from working
|
||||
// when elements with 'tabindex' are focused.
|
||||
PDFView.container.blur();
|
||||
|
||||
if (cmd === 0) { // no control key pressed at all.
|
||||
switch (evt.keyCode) {
|
||||
@ -4673,7 +4680,7 @@ window.addEventListener('keydown', function keydown(evt) {
|
||||
handled = true;
|
||||
break;
|
||||
case 27: // esc key
|
||||
if (SecondaryToolbar.isOpen) {
|
||||
if (SecondaryToolbar.opened) {
|
||||
SecondaryToolbar.close();
|
||||
handled = true;
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
chrome.manifest
|
||||
components/PdfRedirector.js
|
||||
components/PdfStreamConverter.js
|
||||
content/PdfJs.jsm
|
||||
content/PdfJsTelemetry.jsm
|
||||
content/build/pdf.js
|
||||
content/build/pdf.worker.js
|
||||
content/network.js
|
||||
content/PdfJs.jsm
|
||||
content/PdfJsTelemetry.jsm
|
||||
content/web/debugger.js
|
||||
content/web/images/annotation-check.svg
|
||||
content/web/images/annotation-comment.svg
|
||||
|
@ -44,6 +44,8 @@ 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() {
|
||||
@ -60,7 +62,7 @@ let IndexedDB = {
|
||||
}
|
||||
|
||||
prompt.prompt({
|
||||
type: type,
|
||||
types: types,
|
||||
uri: Services.io.newURI(payload.location, null, null),
|
||||
window: null,
|
||||
element: aMessage.target,
|
||||
|
@ -56,8 +56,8 @@ ContentPermissionPrompt.prototype = {
|
||||
return chromeWin.Browser.getNotificationBox(request.element);
|
||||
},
|
||||
|
||||
handleExistingPermission: function handleExistingPermission(request) {
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, request.type);
|
||||
handleExistingPermission: function handleExistingPermission(request, type) {
|
||||
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, type);
|
||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
request.allow();
|
||||
return true;
|
||||
@ -70,20 +70,28 @@ ContentPermissionPrompt.prototype = {
|
||||
},
|
||||
|
||||
prompt: function(request) {
|
||||
// Only allow exactly one permission rquest here.
|
||||
let types = request.types.QueryInterface(Ci.nsIArray);
|
||||
if (types.length != 1) {
|
||||
request.cancel();
|
||||
return;
|
||||
}
|
||||
let perm = types.queryElementAt(0, Ci.nsIContentPermissionType);
|
||||
|
||||
// returns true if the request was handled
|
||||
if (this.handleExistingPermission(request))
|
||||
if (this.handleExistingPermission(request, perm.type))
|
||||
return;
|
||||
|
||||
let pm = Services.perms;
|
||||
let notificationBox = this.getNotificationBoxForRequest(request);
|
||||
let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
|
||||
|
||||
let notification = notificationBox.getNotificationWithValue(request.type);
|
||||
let notification = notificationBox.getNotificationWithValue(perm.type);
|
||||
if (notification)
|
||||
return;
|
||||
|
||||
let entityName = kEntities[request.type];
|
||||
let icon = kIcons[request.type] || "";
|
||||
let entityName = kEntities[perm.type];
|
||||
let icon = kIcons[perm.type] || "";
|
||||
|
||||
let buttons = [{
|
||||
label: browserBundle.GetStringFromName(entityName + ".allow"),
|
||||
@ -96,7 +104,7 @@ ContentPermissionPrompt.prototype = {
|
||||
label: browserBundle.GetStringFromName("contentPermissions.alwaysForSite"),
|
||||
accessKey: "",
|
||||
callback: function(notification) {
|
||||
Services.perms.addFromPrincipal(request.principal, request.type, Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
request.allow();
|
||||
}
|
||||
},
|
||||
@ -104,7 +112,7 @@ ContentPermissionPrompt.prototype = {
|
||||
label: browserBundle.GetStringFromName("contentPermissions.neverForSite"),
|
||||
accessKey: "",
|
||||
callback: function(notification) {
|
||||
Services.perms.addFromPrincipal(request.principal, request.type, Ci.nsIPermissionManager.DENY_ACTION);
|
||||
Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.DENY_ACTION);
|
||||
request.cancel();
|
||||
}
|
||||
}];
|
||||
@ -112,12 +120,12 @@ ContentPermissionPrompt.prototype = {
|
||||
let message = browserBundle.formatStringFromName(entityName + ".wantsTo",
|
||||
[request.principal.URI.host], 1);
|
||||
let newBar = notificationBox.appendNotification(message,
|
||||
request.type,
|
||||
perm.type,
|
||||
icon,
|
||||
notificationBox.PRIORITY_WARNING_MEDIUM,
|
||||
buttons);
|
||||
|
||||
if (request.type == "geolocation") {
|
||||
if (perm.type == "geolocation") {
|
||||
// Add the "learn more" link.
|
||||
let link = newBar.ownerDocument.createElement("label");
|
||||
link.setAttribute("value", browserBundle.GetStringFromName("geolocation.learnMore"));
|
||||
|
@ -1296,30 +1296,22 @@ toolbar[iconsize="small"] #webrtc-status-button {
|
||||
#plugins-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/notification-pluginNormal.png);
|
||||
}
|
||||
|
||||
#alert-plugins-notification-icon {
|
||||
#plugins-notification-icon.plugin-hidden {
|
||||
list-style-image: url(chrome://browser/skin/notification-pluginAlert.png);
|
||||
}
|
||||
|
||||
#blocked-plugins-notification-icon {
|
||||
#plugins-notification-icon.plugin-blocked {
|
||||
list-style-image: url(chrome://browser/skin/notification-pluginBlocked.png);
|
||||
}
|
||||
|
||||
#plugins-notification-icon,
|
||||
#alert-plugins-notification-icon,
|
||||
#blocked-plugins-notification-icon {
|
||||
#plugins-notification-icon {
|
||||
-moz-image-region: rect(0, 16px, 16px, 0);
|
||||
}
|
||||
|
||||
#plugins-notification-icon:hover,
|
||||
#alert-plugins-notification-icon:hover,
|
||||
#blocked-plugins-notification-icon:hover {
|
||||
#plugins-notification-icon:hover {
|
||||
-moz-image-region: rect(0, 32px, 16px, 16px);
|
||||
}
|
||||
|
||||
#plugins-notification-icon:active,
|
||||
#alert-plugins-notification-icon:active,
|
||||
#blocked-plugins-notification-icon:active {
|
||||
#plugins-notification-icon:active {
|
||||
-moz-image-region: rect(0, 48px, 16px, 32px);
|
||||
}
|
||||
|
||||
@ -1334,7 +1326,7 @@ toolbar[iconsize="small"] #webrtc-status-button {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
#blocked-plugins-notification-icon[showing] {
|
||||
#plugins-notification-icon.plugin-blocked[showing] {
|
||||
animation: pluginBlockedNotification 500ms ease 0s 5 alternate both;
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,11 @@
|
||||
-moz-border-end: 1px solid #222426; /* Match the sources list's dark margin. */
|
||||
}
|
||||
|
||||
#sources-toolbar .devtools-toolbarbutton {
|
||||
min-width: 32px;
|
||||
}
|
||||
|
||||
#pretty-print {
|
||||
min-width: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
@ -3,3 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
%include ../../shared/devtools/shadereditor.inc.css
|
||||
|
||||
.side-menu-widget-item-checkbox > .checkbox-spacer-box {
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
@ -317,11 +317,6 @@
|
||||
background-image: linear-gradient(#fff, #eee);
|
||||
}
|
||||
|
||||
.side-menu-widget-group-checkbox {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* SideMenuWidget items */
|
||||
|
||||
.side-menu-widget-item[theme="dark"] {
|
||||
@ -379,11 +374,6 @@
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
-moz-margin-start: 4px;
|
||||
-moz-margin-end: -6px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-other {
|
||||
background: url(background-noise-toolbar.png), hsla(208,11%,27%, 0.65);
|
||||
}
|
||||
@ -403,6 +393,25 @@
|
||||
text-shadow: 0 1px 1px #111;
|
||||
}
|
||||
|
||||
/* SideMenuWidget checkboxes */
|
||||
|
||||
.side-menu-widget-group-checkbox {
|
||||
margin: 0;
|
||||
-moz-margin-end: 4px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
margin: 0;
|
||||
-moz-margin-start: 4px;
|
||||
-moz-margin-end: -4px;
|
||||
}
|
||||
|
||||
.side-menu-widget-group-checkbox .checkbox-spacer-box,
|
||||
.side-menu-widget-item-checkbox .checkbox-spacer-box {
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* SideMenuWidget misc */
|
||||
|
||||
.side-menu-widget-empty-notice-container {
|
||||
|
@ -3207,29 +3207,23 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
list-style-image: url(chrome://browser/skin/notification-pluginNormal.png);
|
||||
}
|
||||
|
||||
#alert-plugins-notification-icon {
|
||||
#plugins-notification-icon.plugin-hidden {
|
||||
list-style-image: url(chrome://browser/skin/notification-pluginAlert.png);
|
||||
}
|
||||
|
||||
#blocked-plugins-notification-icon {
|
||||
#plugins-notification-icon.plugin-blocked {
|
||||
list-style-image: url(chrome://browser/skin/notification-pluginBlocked.png);
|
||||
}
|
||||
|
||||
#plugins-notification-icon,
|
||||
#alert-plugins-notification-icon,
|
||||
#blocked-plugins-notification-icon {
|
||||
#plugins-notification-icon {
|
||||
-moz-image-region: rect(0, 16px, 16px, 0);
|
||||
}
|
||||
|
||||
#plugins-notification-icon:hover,
|
||||
#alert-plugins-notification-icon:hover,
|
||||
#blocked-plugins-notification-icon:hover {
|
||||
#plugins-notification-icon:hover {
|
||||
-moz-image-region: rect(0, 32px, 16px, 16px);
|
||||
}
|
||||
|
||||
#plugins-notification-icon:active,
|
||||
#alert-plugins-notification-icon:active,
|
||||
#blocked-plugins-notification-icon:active {
|
||||
#plugins-notification-icon:active {
|
||||
-moz-image-region: rect(0, 48px, 16px, 32px);
|
||||
}
|
||||
|
||||
@ -3238,29 +3232,23 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
list-style-image: url(chrome://browser/skin/notification-pluginNormal@2x.png);
|
||||
}
|
||||
|
||||
#alert-plugins-notification-icon {
|
||||
#plugins-notification-icon.plugin-hidden {
|
||||
list-style-image: url(chrome://browser/skin/notification-pluginAlert@2x.png);
|
||||
}
|
||||
|
||||
#blocked-plugins-notification-icon {
|
||||
#plugins-notification-icon.plugin-blocked {
|
||||
list-style-image: url(chrome://browser/skin/notification-pluginBlocked@2x.png);
|
||||
}
|
||||
|
||||
#plugins-notification-icon,
|
||||
#alert-plugins-notification-icon,
|
||||
#blocked-plugins-notification-icon {
|
||||
#plugins-notification-icon {
|
||||
-moz-image-region: rect(0, 32px, 32px, 0);
|
||||
}
|
||||
|
||||
#plugins-notification-icon:hover,
|
||||
#alert-plugins-notification-icon:hover,
|
||||
#blocked-plugins-notification-icon:hover {
|
||||
#plugins-notification-icon:hover {
|
||||
-moz-image-region: rect(0, 64px, 32px, 32px);
|
||||
}
|
||||
|
||||
#plugins-notification-icon:active,
|
||||
#alert-plugins-notification-icon:active,
|
||||
#blocked-plugins-notification-icon:active {
|
||||
#plugins-notification-icon:active {
|
||||
-moz-image-region: rect(0, 96px, 32px, 64px);
|
||||
}
|
||||
}
|
||||
@ -3281,7 +3269,7 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
#blocked-plugins-notification-icon[showing] {
|
||||
#plugins-notification-icon.plugin-blocked[showing] {
|
||||
animation: pluginBlockedNotification 500ms ease 0s 5 alternate both;
|
||||
}
|
||||
|
||||
|
@ -26,8 +26,11 @@
|
||||
-moz-border-end: 1px solid #222426; /* Match the sources list's dark margin. */
|
||||
}
|
||||
|
||||
#sources-toolbar .devtools-toolbarbutton {
|
||||
min-width: 32px;
|
||||
}
|
||||
|
||||
#pretty-print {
|
||||
min-width: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
@ -317,11 +317,6 @@
|
||||
background-image: linear-gradient(#fff, #eee);
|
||||
}
|
||||
|
||||
.side-menu-widget-group-checkbox {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* SideMenuWidget items */
|
||||
|
||||
.side-menu-widget-item[theme="dark"] {
|
||||
@ -379,11 +374,6 @@
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
-moz-margin-start: 4px;
|
||||
-moz-margin-end: -6px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-other {
|
||||
background: url(background-noise-toolbar.png), hsla(208,11%,27%, 0.65);
|
||||
}
|
||||
@ -403,6 +393,19 @@
|
||||
text-shadow: 0 1px 1px #111;
|
||||
}
|
||||
|
||||
/* SideMenuWidget checkboxes */
|
||||
|
||||
.side-menu-widget-group-checkbox {
|
||||
margin: 0;
|
||||
-moz-margin-end: 4px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
margin: 0;
|
||||
-moz-margin-start: 4px;
|
||||
-moz-margin-end: -4px;
|
||||
}
|
||||
|
||||
/* SideMenuWidget misc */
|
||||
|
||||
.side-menu-widget-empty-notice-container {
|
||||
|
@ -51,8 +51,6 @@
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
-moz-appearance: none;
|
||||
-moz-margin-end: -6px;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
transition: opacity .15s ease-out 0s;
|
||||
}
|
||||
@ -66,10 +64,10 @@
|
||||
transition: opacity .15s ease-out 0s;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox > .checkbox-check {
|
||||
.side-menu-widget-item-checkbox .checkbox-check {
|
||||
-moz-appearance: none;
|
||||
background: none;
|
||||
background-image: url("chrome://browser/skin/devtools/itemToggle.png");
|
||||
background-image: url(itemToggle.png);
|
||||
background-repeat: no-repeat;
|
||||
background-clip: content-box;
|
||||
background-size: 32px 16px;
|
||||
@ -79,7 +77,7 @@
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox[checked] > .checkbox-check {
|
||||
.side-menu-widget-item-checkbox[checked] .checkbox-check {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
|
@ -2568,30 +2568,23 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
|
||||
#plugins-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/notification-pluginNormal.png);
|
||||
}
|
||||
|
||||
#alert-plugins-notification-icon {
|
||||
#plugins-notification-icon.plugin-hidden {
|
||||
list-style-image: url(chrome://browser/skin/notification-pluginAlert.png);
|
||||
}
|
||||
|
||||
#blocked-plugins-notification-icon {
|
||||
#plugins-notification-icon.plugin-blocked {
|
||||
list-style-image: url(chrome://browser/skin/notification-pluginBlocked.png);
|
||||
}
|
||||
|
||||
#plugins-notification-icon,
|
||||
#alert-plugins-notification-icon,
|
||||
#blocked-plugins-notification-icon {
|
||||
#plugins-notification-icon {
|
||||
-moz-image-region: rect(0, 16px, 16px, 0);
|
||||
}
|
||||
|
||||
#plugins-notification-icon:hover,
|
||||
#alert-plugins-notification-icon:hover,
|
||||
#blocked-plugins-notification-icon:hover {
|
||||
#plugins-notification-icon:hover {
|
||||
-moz-image-region: rect(0, 32px, 16px, 16px);
|
||||
}
|
||||
|
||||
#plugins-notification-icon:active,
|
||||
#alert-plugins-notification-icon:active,
|
||||
#blocked-plugins-notification-icon:active {
|
||||
#plugins-notification-icon:active {
|
||||
-moz-image-region: rect(0, 48px, 16px, 32px);
|
||||
}
|
||||
|
||||
@ -2606,7 +2599,7 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
#blocked-plugins-notification-icon[showing] {
|
||||
#plugins-notification-icon.plugin-blocked[showing] {
|
||||
animation: pluginBlockedNotification 500ms ease 0s 5 alternate both;
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,11 @@
|
||||
-moz-border-end: 1px solid #222426; /* Match the sources list's dark margin. */
|
||||
}
|
||||
|
||||
#sources-toolbar .devtools-toolbarbutton {
|
||||
min-width: 32px;
|
||||
}
|
||||
|
||||
#pretty-print {
|
||||
min-width: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
@ -321,11 +321,6 @@
|
||||
background-image: linear-gradient(#fff, #eee);
|
||||
}
|
||||
|
||||
.side-menu-widget-group-checkbox {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* SideMenuWidget items */
|
||||
|
||||
.side-menu-widget-item[theme="dark"] {
|
||||
@ -383,11 +378,6 @@
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
-moz-margin-start: 4px;
|
||||
-moz-margin-end: -6px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-other {
|
||||
background: url(background-noise-toolbar.png), hsla(208,11%,27%, 0.65);
|
||||
}
|
||||
@ -406,6 +396,19 @@
|
||||
color: #f5f7fa;
|
||||
}
|
||||
|
||||
/* SideMenuWidget checkboxes */
|
||||
|
||||
.side-menu-widget-group-checkbox {
|
||||
margin: 0;
|
||||
-moz-margin-end: 4px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
margin: 0;
|
||||
-moz-margin-start: 4px;
|
||||
-moz-margin-end: -4px;
|
||||
}
|
||||
|
||||
/* SideMenuWidget misc */
|
||||
|
||||
.side-menu-widget-empty-notice-container {
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "plstr.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsMemory.h"
|
||||
|
@ -84,8 +84,6 @@
|
||||
#include "nsIBaseWindow.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
|
||||
#include "nsNodeInfoManager.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsIDOMDocumentType.h"
|
||||
|
@ -79,7 +79,7 @@
|
||||
#include "nsIBaseWindow.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "js/GCAPI.h"
|
||||
|
||||
#include "nsNodeInfoManager.h"
|
||||
#include "nsICategoryManager.h"
|
||||
|
@ -215,6 +215,8 @@
|
||||
#include "mozilla/dom/XPathEvaluator.h"
|
||||
#include "nsIDocumentEncoder.h"
|
||||
#include "nsIStructuredCloneContainer.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsContentPermissionHelper.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -10647,17 +10649,11 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsPointerLockPermissionRequest,
|
||||
nsIContentPermissionRequest)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPointerLockPermissionRequest::GetType(nsACString& aType)
|
||||
nsPointerLockPermissionRequest::GetTypes(nsIArray** aTypes)
|
||||
{
|
||||
aType = "pointerLock";
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPointerLockPermissionRequest::GetAccess(nsACString& aAccess)
|
||||
{
|
||||
aAccess = "unused";
|
||||
return NS_OK;
|
||||
return CreatePermissionArray(NS_LITERAL_CSTRING("pointerLock"),
|
||||
NS_LITERAL_CSTRING("unused"),
|
||||
aTypes);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -88,6 +88,7 @@
|
||||
#include "mozilla/dom/HTMLVideoElement.h"
|
||||
#include "mozilla/dom/TextMetrics.h"
|
||||
#include "mozilla/dom/UnionTypes.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
|
||||
#ifdef USE_SKIA_GPU
|
||||
#undef free // apparently defined by some windows header, clashing with a free()
|
||||
@ -2858,27 +2859,27 @@ CanvasRenderingContext2D::SetMozDashOffset(double mozDashOffset)
|
||||
}
|
||||
|
||||
void
|
||||
CanvasRenderingContext2D::SetLineDash(const mozilla::dom::AutoSequence<double>& mSegments) {
|
||||
CanvasRenderingContext2D::SetLineDash(const mozilla::dom::AutoSequence<double>& aSegments) {
|
||||
FallibleTArray<mozilla::gfx::Float>& dash = CurrentState().dash;
|
||||
dash.Clear();
|
||||
|
||||
for(mozilla::dom::AutoSequence<double>::index_type x = 0; x < mSegments.Length(); x++) {
|
||||
dash.AppendElement(mSegments[x]);
|
||||
for (uint32_t x = 0; x < aSegments.Length(); x++) {
|
||||
dash.AppendElement(aSegments[x]);
|
||||
}
|
||||
if(mSegments.Length()%2) { // If the number of elements is odd, concatenate again
|
||||
for(mozilla::dom::AutoSequence<double>::index_type x = 0; x < mSegments.Length(); x++) {
|
||||
dash.AppendElement(mSegments[x]);
|
||||
if (aSegments.Length() % 2) { // If the number of elements is odd, concatenate again
|
||||
for (uint32_t x = 0; x < aSegments.Length(); x++) {
|
||||
dash.AppendElement(aSegments[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CanvasRenderingContext2D::GetLineDash(nsTArray<double>& mSegments) const {
|
||||
CanvasRenderingContext2D::GetLineDash(nsTArray<double>& aSegments) const {
|
||||
const FallibleTArray<mozilla::gfx::Float>& dash = CurrentState().dash;
|
||||
mSegments.Clear();
|
||||
aSegments.Clear();
|
||||
|
||||
for(FallibleTArray<mozilla::gfx::Float>::index_type x = 0; x < dash.Length(); x++) {
|
||||
mSegments.AppendElement(dash[x]);
|
||||
for (uint32_t x = 0; x < dash.Length(); x++) {
|
||||
aSegments.AppendElement(dash[x]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3224,7 +3225,7 @@ CanvasRenderingContext2D::GetGlobalCompositeOperation(nsAString& op,
|
||||
}
|
||||
|
||||
void
|
||||
CanvasRenderingContext2D::DrawWindow(nsIDOMWindow* window, double x,
|
||||
CanvasRenderingContext2D::DrawWindow(nsGlobalWindow& window, double x,
|
||||
double y, double w, double h,
|
||||
const nsAString& bgColor,
|
||||
uint32_t flags, ErrorResult& error)
|
||||
@ -3253,16 +3254,13 @@ CanvasRenderingContext2D::DrawWindow(nsIDOMWindow* window, double x,
|
||||
|
||||
// Flush layout updates
|
||||
if (!(flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DO_NOT_FLUSH)) {
|
||||
nsContentUtils::FlushLayoutForTree(window);
|
||||
nsContentUtils::FlushLayoutForTree(&window);
|
||||
}
|
||||
|
||||
nsRefPtr<nsPresContext> presContext;
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(window);
|
||||
if (win) {
|
||||
nsIDocShell* docshell = win->GetDocShell();
|
||||
if (docshell) {
|
||||
docshell->GetPresContext(getter_AddRefs(presContext));
|
||||
}
|
||||
nsIDocShell* docshell = window.GetDocShell();
|
||||
if (docshell) {
|
||||
docshell->GetPresContext(getter_AddRefs(presContext));
|
||||
}
|
||||
if (!presContext) {
|
||||
error.Throw(NS_ERROR_FAILURE);
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "gfx2DGlue.h"
|
||||
#include "imgIEncoder.h"
|
||||
|
||||
class nsGlobalWindow;
|
||||
class nsXULElement;
|
||||
|
||||
namespace mozilla {
|
||||
@ -369,7 +370,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void DrawWindow(nsIDOMWindow* window, double x, double y, double w, double h,
|
||||
void DrawWindow(nsGlobalWindow& window, double x, double y, double w, double h,
|
||||
const nsAString& bgColor, uint32_t flags,
|
||||
mozilla::ErrorResult& error);
|
||||
void AsyncDrawXULElement(nsXULElement& elem, double x, double y, double w,
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsUnicharUtils.h" // for nsCaseInsensitiveStringComparator()
|
||||
#include "jsapi.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
#include "nsITimer.h"
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "EncodedFrameContainer.h"
|
||||
#include "TrackMetadataBase.h"
|
||||
|
||||
namespace mozilla {
|
||||
/**
|
||||
@ -31,11 +33,20 @@ public:
|
||||
* END_OF_STREAM if this is the last packet of track.
|
||||
* Currently, WriteEncodedTrack doesn't support multiple tracks.
|
||||
*/
|
||||
virtual nsresult WriteEncodedTrack(const nsTArray<uint8_t>& aBuffer,
|
||||
int aDuration, uint32_t aFlags = 0) = 0;
|
||||
virtual nsresult WriteEncodedTrack(const EncodedFrameContainer& aData,
|
||||
uint32_t aFlags = 0) = 0;
|
||||
|
||||
/**
|
||||
* Set the meta data pointer into muxer
|
||||
* This function will check the integrity of aMetadata.
|
||||
* If the meta data isn't well format, this function will return NS_ERROR_FAILURE to caller,
|
||||
* else save the pointer to mMetadata and return NS_OK.
|
||||
*/
|
||||
virtual nsresult SetMetadata(nsRefPtr<TrackMetadataBase> aMetadata) = 0;
|
||||
|
||||
enum {
|
||||
FLUSH_NEEDED = 1 << 0
|
||||
FLUSH_NEEDED = 1 << 0,
|
||||
GET_HEADER = 1 << 1
|
||||
};
|
||||
|
||||
/**
|
||||
@ -50,6 +61,7 @@ public:
|
||||
uint32_t aFlags = 0) = 0;
|
||||
|
||||
protected:
|
||||
nsRefPtr<TrackMetadataBase> mMetadata;
|
||||
bool mInitialized;
|
||||
};
|
||||
}
|
||||
|
82
content/media/encoder/EncodedFrameContainer.h
Normal file
82
content/media/encoder/EncodedFrameContainer.h
Normal file
@ -0,0 +1,82 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
|
||||
/* 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/. */
|
||||
|
||||
#ifndef EncodedFrameContainer_H_
|
||||
#define EncodedFrameContainer_H_
|
||||
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class EncodedFrame;
|
||||
|
||||
/*
|
||||
* This container is used to carry video or audio encoded data from encoder to muxer.
|
||||
* The media data object is created by encoder and recycle by the destructor.
|
||||
* Only allow to store audio or video encoded data in EncodedData.
|
||||
*/
|
||||
class EncodedFrameContainer
|
||||
{
|
||||
public:
|
||||
// Append encoded frame data
|
||||
void AppendEncodedFrame(EncodedFrame* aEncodedFrame)
|
||||
{
|
||||
mEncodedFrames.AppendElement(aEncodedFrame);
|
||||
}
|
||||
// Retrieve all of the encoded frames
|
||||
const nsTArray<nsAutoPtr<EncodedFrame> >& GetEncodedFrames() const
|
||||
{
|
||||
return mEncodedFrames;
|
||||
}
|
||||
private:
|
||||
// This container is used to store the video or audio encoded packets.
|
||||
// Muxer should check mFrameType and get the encoded data type from mEncodedFrames.
|
||||
nsTArray<nsAutoPtr<EncodedFrame> > mEncodedFrames;
|
||||
};
|
||||
|
||||
// Represent one encoded frame
|
||||
class EncodedFrame
|
||||
{
|
||||
public:
|
||||
EncodedFrame() :
|
||||
mTimeStamp(0),
|
||||
mDuration(0),
|
||||
mFrameType(UNKNOW)
|
||||
{}
|
||||
enum FrameType {
|
||||
I_FRAME, // intraframe
|
||||
P_FRAME, // predicted frame
|
||||
B_FRAME, // bidirectionally predicted frame
|
||||
AUDIO_FRAME, // audio frame
|
||||
UNKNOW // FrameType not set
|
||||
};
|
||||
const nsTArray<uint8_t>& GetFrameData() const
|
||||
{
|
||||
return mFrameData;
|
||||
}
|
||||
void SetFrameData(nsTArray<uint8_t> *aData)
|
||||
{
|
||||
mFrameData.SwapElements(*aData);
|
||||
}
|
||||
uint64_t GetTimeStamp() const { return mTimeStamp; }
|
||||
void SetTimeStamp(uint64_t aTimeStamp) { mTimeStamp = aTimeStamp; }
|
||||
|
||||
uint64_t GetDuration() const { return mDuration; }
|
||||
void SetDuration(uint64_t aDuration) { mDuration = aDuration; }
|
||||
|
||||
FrameType GetFrameType() const { return mFrameType; }
|
||||
void SetFrameType(FrameType aFrameType) { mFrameType = aFrameType; }
|
||||
private:
|
||||
// Encoded data
|
||||
nsTArray<uint8_t> mFrameData;
|
||||
uint64_t mTimeStamp;
|
||||
// The playback duration of this packet in number of samples
|
||||
uint64_t mDuration;
|
||||
// Represent what is in the FrameData
|
||||
FrameType mFrameType;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
@ -5,6 +5,7 @@
|
||||
#include "MediaEncoder.h"
|
||||
#include "MediaDecoder.h"
|
||||
#include "nsIPrincipal.h"
|
||||
|
||||
#ifdef MOZ_OGG
|
||||
#include "OggWriter.h"
|
||||
#endif
|
||||
@ -128,17 +129,15 @@ MediaEncoder::CreateEncoder(const nsAString& aMIMEType)
|
||||
|
||||
/**
|
||||
* GetEncodedData() runs as a state machine, starting with mState set to
|
||||
* ENCODE_HEADER, the procedure should be as follow:
|
||||
* GET_METADDATA, the procedure should be as follow:
|
||||
*
|
||||
* While non-stop
|
||||
* If mState is ENCODE_HEADER
|
||||
* Create the header from audio/video encoder
|
||||
* If a header is generated
|
||||
* Insert header data into the container stream of writer
|
||||
* Force copied the final container data from writer
|
||||
* Return the copy of final container data
|
||||
* Else
|
||||
* If mState is GET_METADDATA
|
||||
* Get the meta data from audio/video encoder
|
||||
* If a meta data is generated
|
||||
* Get meta data from audio/video encoder
|
||||
* Set mState to ENCODE_TRACK
|
||||
* Return the final container data
|
||||
*
|
||||
* If mState is ENCODE_TRACK
|
||||
* Get encoded track data from audio/video encoder
|
||||
@ -163,48 +162,36 @@ MediaEncoder::GetEncodedData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
|
||||
bool reloop = true;
|
||||
while (reloop) {
|
||||
switch (mState) {
|
||||
case ENCODE_HEADER: {
|
||||
nsTArray<uint8_t> buffer;
|
||||
nsresult rv = mAudioEncoder->GetHeader(&buffer);
|
||||
case ENCODE_METADDATA: {
|
||||
nsRefPtr<TrackMetadataBase> meta = mAudioEncoder->GetMetadata();
|
||||
MOZ_ASSERT(meta);
|
||||
nsresult rv = mWriter->SetMetadata(meta);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Encoding might be canceled.
|
||||
mState = ENCODE_DONE;
|
||||
break;
|
||||
mState = ENCODE_DONE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!buffer.IsEmpty()) {
|
||||
rv = mWriter->WriteEncodedTrack(buffer, 0);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG("ERROR! Fail to write header to the media container.");
|
||||
mState = ENCODE_DONE;
|
||||
break;
|
||||
}
|
||||
|
||||
rv = mWriter->GetContainerData(aOutputBufs,
|
||||
ContainerWriter::FLUSH_NEEDED);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Successfully get the copy of final container data from writer.
|
||||
reloop = false;
|
||||
}
|
||||
} else {
|
||||
// No more headers, starts to encode tracks.
|
||||
mState = ENCODE_TRACK;
|
||||
rv = mWriter->GetContainerData(aOutputBufs,
|
||||
ContainerWriter::GET_HEADER);
|
||||
if (NS_FAILED(rv)) {
|
||||
mState = ENCODE_DONE;
|
||||
break;
|
||||
}
|
||||
|
||||
mState = ENCODE_TRACK;
|
||||
break;
|
||||
}
|
||||
|
||||
case ENCODE_TRACK: {
|
||||
nsTArray<uint8_t> buffer;
|
||||
int encodedDuration = 0;
|
||||
nsresult rv = mAudioEncoder->GetEncodedTrack(&buffer, encodedDuration);
|
||||
EncodedFrameContainer encodedData;
|
||||
nsresult rv = mAudioEncoder->GetEncodedTrack(encodedData);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Encoding might be canceled.
|
||||
LOG("ERROR! Fail to get encoded data from encoder.");
|
||||
mState = ENCODE_DONE;
|
||||
break;
|
||||
}
|
||||
|
||||
rv = mWriter->WriteEncodedTrack(buffer, encodedDuration,
|
||||
rv = mWriter->WriteEncodedTrack(encodedData,
|
||||
mAudioEncoder->IsEncodingComplete() ?
|
||||
ContainerWriter::END_OF_STREAM : 0);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -51,7 +51,7 @@ class MediaEncoder : public MediaStreamListener
|
||||
{
|
||||
public :
|
||||
enum {
|
||||
ENCODE_HEADER,
|
||||
ENCODE_METADDATA,
|
||||
ENCODE_TRACK,
|
||||
ENCODE_DONE,
|
||||
};
|
||||
@ -64,7 +64,7 @@ public :
|
||||
, mAudioEncoder(aAudioEncoder)
|
||||
, mVideoEncoder(aVideoEncoder)
|
||||
, mMIMEType(aMIMEType)
|
||||
, mState(MediaEncoder::ENCODE_HEADER)
|
||||
, mState(MediaEncoder::ENCODE_METADDATA)
|
||||
, mShutdown(false)
|
||||
{}
|
||||
|
||||
|
@ -115,7 +115,6 @@ SerializeOpusCommentHeader(const nsCString& aVendor,
|
||||
|
||||
OpusTrackEncoder::OpusTrackEncoder()
|
||||
: AudioTrackEncoder()
|
||||
, mEncoderState(ID_HEADER)
|
||||
, mEncoder(nullptr)
|
||||
, mSourceSegment(new AudioSegment())
|
||||
, mLookahead(0)
|
||||
@ -187,8 +186,8 @@ OpusTrackEncoder::GetPacketDuration()
|
||||
return GetOutputSampleRate() * kFrameDurationMs / 1000;
|
||||
}
|
||||
|
||||
nsresult
|
||||
OpusTrackEncoder::GetHeader(nsTArray<uint8_t>* aOutput)
|
||||
nsRefPtr<TrackMetadataBase>
|
||||
OpusTrackEncoder::GetMetadata()
|
||||
{
|
||||
{
|
||||
// Wait if mEncoder is not initialized.
|
||||
@ -199,50 +198,35 @@ OpusTrackEncoder::GetHeader(nsTArray<uint8_t>* aOutput)
|
||||
}
|
||||
|
||||
if (mCanceled || mDoneEncoding) {
|
||||
return NS_ERROR_FAILURE;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
switch (mEncoderState) {
|
||||
case ID_HEADER:
|
||||
{
|
||||
OpusMetadata* meta = new OpusMetadata();
|
||||
|
||||
mLookahead = 0;
|
||||
int error = opus_encoder_ctl(mEncoder, OPUS_GET_LOOKAHEAD(&mLookahead));
|
||||
if (error != OPUS_OK) {
|
||||
mLookahead = 0;
|
||||
int error = opus_encoder_ctl(mEncoder, OPUS_GET_LOOKAHEAD(&mLookahead));
|
||||
if (error != OPUS_OK) {
|
||||
mLookahead = 0;
|
||||
}
|
||||
|
||||
// The ogg time stamping and pre-skip is always timed at 48000.
|
||||
SerializeOpusIdHeader(mChannels, mLookahead*(kOpusSamplingRate/mSamplingRate),
|
||||
mSamplingRate, aOutput);
|
||||
|
||||
mEncoderState = COMMENT_HEADER;
|
||||
break;
|
||||
}
|
||||
case COMMENT_HEADER:
|
||||
{
|
||||
nsCString vendor;
|
||||
vendor.AppendASCII(opus_get_version_string());
|
||||
|
||||
nsTArray<nsCString> comments;
|
||||
comments.AppendElement(NS_LITERAL_CSTRING("ENCODER=Mozilla" MOZ_APP_UA_VERSION));
|
||||
// The ogg time stamping and pre-skip is always timed at 48000.
|
||||
SerializeOpusIdHeader(mChannels, mLookahead*(kOpusSamplingRate/mSamplingRate),
|
||||
mSamplingRate, &meta->mIdHeader);
|
||||
|
||||
SerializeOpusCommentHeader(vendor, comments, aOutput);
|
||||
nsCString vendor;
|
||||
vendor.AppendASCII(opus_get_version_string());
|
||||
|
||||
mEncoderState = DATA;
|
||||
break;
|
||||
}
|
||||
case DATA:
|
||||
// No more headers.
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Invalid state");
|
||||
}
|
||||
return NS_OK;
|
||||
nsTArray<nsCString> comments;
|
||||
comments.AppendElement(NS_LITERAL_CSTRING("ENCODER=Mozilla" MOZ_APP_UA_VERSION));
|
||||
|
||||
SerializeOpusCommentHeader(vendor, comments,
|
||||
&meta->mCommentHeader);
|
||||
|
||||
return meta;
|
||||
}
|
||||
|
||||
nsresult
|
||||
OpusTrackEncoder::GetEncodedTrack(nsTArray<uint8_t>* aOutput,
|
||||
int &aOutputDuration)
|
||||
OpusTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
|
||||
{
|
||||
{
|
||||
// Move all the samples from mRawSegment to mSourceSegment. We only hold
|
||||
@ -297,6 +281,8 @@ OpusTrackEncoder::GetEncodedTrack(nsTArray<uint8_t>* aOutput,
|
||||
iter.Next();
|
||||
}
|
||||
|
||||
EncodedFrame* audiodata = new EncodedFrame();
|
||||
audiodata->SetFrameType(EncodedFrame::AUDIO_FRAME);
|
||||
if (mResampler) {
|
||||
nsAutoTArray<AudioDataValue, 9600> resamplingDest;
|
||||
// We want to consume all the input data, so we slightly oversize the
|
||||
@ -321,10 +307,10 @@ OpusTrackEncoder::GetEncodedTrack(nsTArray<uint8_t>* aOutput,
|
||||
|
||||
pcm = resamplingDest;
|
||||
// This is always at 48000Hz.
|
||||
aOutputDuration = outframes;
|
||||
audiodata->SetDuration(outframes);
|
||||
} else {
|
||||
// The ogg time stamping and pre-skip is always timed at 48000.
|
||||
aOutputDuration = frameCopied * (kOpusSamplingRate / mSamplingRate);
|
||||
audiodata->SetDuration(frameCopied * (kOpusSamplingRate / mSamplingRate));
|
||||
}
|
||||
|
||||
// Remove the raw data which has been pulled to pcm buffer.
|
||||
@ -348,26 +334,28 @@ OpusTrackEncoder::GetEncodedTrack(nsTArray<uint8_t>* aOutput,
|
||||
memset(pcm.Elements() + frameCopied * mChannels, 0,
|
||||
(GetPacketDuration()-frameCopied)*mChannels*sizeof(AudioDataValue));
|
||||
}
|
||||
|
||||
nsTArray<uint8_t> frameData;
|
||||
// Encode the data with Opus Encoder.
|
||||
aOutput->SetLength(MAX_DATA_BYTES);
|
||||
frameData.SetLength(MAX_DATA_BYTES);
|
||||
// result is returned as opus error code if it is negative.
|
||||
int result = 0;
|
||||
#ifdef MOZ_SAMPLE_TYPE_S16
|
||||
const opus_int16* pcmBuf = static_cast<opus_int16*>(pcm.Elements());
|
||||
result = opus_encode(mEncoder, pcmBuf, GetPacketDuration(),
|
||||
aOutput->Elements(), MAX_DATA_BYTES);
|
||||
frameData.Elements(), MAX_DATA_BYTES);
|
||||
#else
|
||||
const float* pcmBuf = static_cast<float*>(pcm.Elements());
|
||||
result = opus_encode_float(mEncoder, pcmBuf, GetPacketDuration(),
|
||||
aOutput->Elements(), MAX_DATA_BYTES);
|
||||
frameData.Elements(), MAX_DATA_BYTES);
|
||||
#endif
|
||||
aOutput->SetLength(result >= 0 ? result : 0);
|
||||
frameData.SetLength(result >= 0 ? result : 0);
|
||||
|
||||
if (result < 0) {
|
||||
LOG("[Opus] Fail to encode data! Result: %s.", opus_strerror(result));
|
||||
}
|
||||
|
||||
audiodata->SetFrameData(&frameData);
|
||||
aData.AppendEncodedFrame(audiodata);
|
||||
return result >= 0 ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -9,21 +9,32 @@
|
||||
#include <stdint.h>
|
||||
#include <speex/speex_resampler.h>
|
||||
#include "TrackEncoder.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
struct OpusEncoder;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Opus meta data structure
|
||||
class OpusMetadata : public TrackMetadataBase
|
||||
{
|
||||
public:
|
||||
// The ID Header of OggOpus. refer to http://wiki.xiph.org/OggOpus.
|
||||
nsTArray<uint8_t> mIdHeader;
|
||||
// The Comment Header of OggOpus.
|
||||
nsTArray<uint8_t> mCommentHeader;
|
||||
|
||||
MetadataKind GetKind() const MOZ_OVERRIDE { return METADATA_OPUS; }
|
||||
};
|
||||
|
||||
class OpusTrackEncoder : public AudioTrackEncoder
|
||||
{
|
||||
public:
|
||||
OpusTrackEncoder();
|
||||
virtual ~OpusTrackEncoder();
|
||||
|
||||
nsresult GetHeader(nsTArray<uint8_t>* aOutput) MOZ_OVERRIDE;
|
||||
nsRefPtr<TrackMetadataBase> GetMetadata() MOZ_OVERRIDE;
|
||||
|
||||
nsresult GetEncodedTrack(nsTArray<uint8_t>* aOutput, int &aOutputDuration) MOZ_OVERRIDE;
|
||||
nsresult GetEncodedTrack(EncodedFrameContainer& aData) MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
int GetPacketDuration() MOZ_OVERRIDE;
|
||||
@ -31,12 +42,6 @@ protected:
|
||||
nsresult Init(int aChannels, int aSamplingRate) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
enum {
|
||||
ID_HEADER,
|
||||
COMMENT_HEADER,
|
||||
DATA
|
||||
} mEncoderState;
|
||||
|
||||
/**
|
||||
* Get the samplerate of the data to be fed to the Opus encoder. This might be
|
||||
* different from the intput samplerate if resampling occurs.
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include "AudioSegment.h"
|
||||
#include "StreamBuffer.h"
|
||||
#include "TrackMetadataBase.h"
|
||||
#include "EncodedFrameContainer.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -48,17 +50,14 @@ public:
|
||||
virtual void NotifyRemoved(MediaStreamGraph* aGraph) = 0;
|
||||
|
||||
/**
|
||||
* Creates and sets up header for a specific codec. Result data is returned
|
||||
* in aOutput.
|
||||
* Creates and sets up meta data for a specific codec
|
||||
*/
|
||||
virtual nsresult GetHeader(nsTArray<uint8_t>* aOutput) = 0;
|
||||
virtual nsRefPtr<TrackMetadataBase> GetMetadata() = 0;
|
||||
|
||||
/**
|
||||
* Encodes raw segments. Result data is returned in aOutput. aOutputDuration
|
||||
* is the playback duration of this packet in number of samples.
|
||||
* Encodes raw segments. Result data is returned in aData.
|
||||
*/
|
||||
virtual nsresult GetEncodedTrack(nsTArray<uint8_t>* aOutput,
|
||||
int &aOutputDuration) = 0;
|
||||
virtual nsresult GetEncodedTrack(EncodedFrameContainer& aData) = 0;
|
||||
};
|
||||
|
||||
class AudioTrackEncoder : public TrackEncoder
|
||||
|
29
content/media/encoder/TrackMetadataBase.h
Normal file
29
content/media/encoder/TrackMetadataBase.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
|
||||
/* 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/. */
|
||||
|
||||
#ifndef TrackMetadataBase_h_
|
||||
#define TrackMetadataBase_h_
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
namespace mozilla {
|
||||
|
||||
// A class represent meta data for various codec format. Only support one track information.
|
||||
class TrackMetadataBase
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TrackMetadataBase)
|
||||
enum MetadataKind {
|
||||
METADATA_OPUS, // Represent the Opus metadata
|
||||
METADATA_VP8,
|
||||
METADATA_UNKNOW // Metadata Kind not set
|
||||
};
|
||||
virtual ~TrackMetadataBase() {}
|
||||
// Return the specific metadata kind
|
||||
virtual MetadataKind GetKind() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
@ -8,8 +8,10 @@ MODULE = 'content'
|
||||
|
||||
EXPORTS += [
|
||||
'ContainerWriter.h',
|
||||
'EncodedFrameContainer.h',
|
||||
'MediaEncoder.h',
|
||||
'TrackEncoder.h',
|
||||
'TrackMetadataBase.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
|
@ -4,6 +4,7 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "OggWriter.h"
|
||||
#include "prtime.h"
|
||||
#include "OpusTrackEncoder.h"
|
||||
|
||||
#undef LOG
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
@ -46,8 +47,29 @@ OggWriter::Init()
|
||||
}
|
||||
|
||||
nsresult
|
||||
OggWriter::WriteEncodedTrack(const nsTArray<uint8_t>& aBuffer, int aDuration,
|
||||
OggWriter::WriteEncodedTrack(const EncodedFrameContainer& aData,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
for (uint32_t i = 0; i < aData.GetEncodedFrames().Length(); i++) {
|
||||
if (aData.GetEncodedFrames()[i]->GetFrameType() != EncodedFrame::AUDIO_FRAME) {
|
||||
LOG("[OggWriter] wrong encoded data type!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv = WriteEncodedData(aData.GetEncodedFrames()[i]->GetFrameData(),
|
||||
aData.GetEncodedFrames()[i]->GetDuration(),
|
||||
aFlags);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG("%p Failed to WriteEncodedTrack!", this);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
OggWriter::WriteEncodedData(const nsTArray<uint8_t>& aBuffer, int aDuration,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
if (!mInitialized) {
|
||||
LOG("[OggWriter] OggWriter has not initialized!");
|
||||
@ -87,14 +109,49 @@ OggWriter::WriteEncodedTrack(const nsTArray<uint8_t>& aBuffer, int aDuration,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
OggWriter::ProduceOggPage(nsTArray<nsTArray<uint8_t> >* aOutputBufs)
|
||||
{
|
||||
aOutputBufs->AppendElement();
|
||||
aOutputBufs->LastElement().SetLength(mOggPage.header_len +
|
||||
mOggPage.body_len);
|
||||
memcpy(aOutputBufs->LastElement().Elements(), mOggPage.header,
|
||||
mOggPage.header_len);
|
||||
memcpy(aOutputBufs->LastElement().Elements() + mOggPage.header_len,
|
||||
mOggPage.body, mOggPage.body_len);
|
||||
}
|
||||
|
||||
nsresult
|
||||
OggWriter::GetContainerData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
int rc = -1;
|
||||
// Generate the oggOpus Header
|
||||
if (aFlags & ContainerWriter::GET_HEADER) {
|
||||
OpusMetadata* meta = static_cast<OpusMetadata*>(mMetadata.get());
|
||||
NS_ASSERTION(meta, "should have meta data");
|
||||
NS_ASSERTION(meta->GetKind() == TrackMetadataBase::METADATA_OPUS,
|
||||
"should have Opus meta data");
|
||||
|
||||
nsresult rv = WriteEncodedData(meta->mIdHeader, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rc = ogg_stream_flush(&mOggStreamState, &mOggPage);
|
||||
NS_ENSURE_TRUE(rc > 0, NS_ERROR_FAILURE);
|
||||
ProduceOggPage(aOutputBufs);
|
||||
|
||||
rv = WriteEncodedData(meta->mCommentHeader, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rc = ogg_stream_flush(&mOggStreamState, &mOggPage);
|
||||
NS_ENSURE_TRUE(rc > 0, NS_ERROR_FAILURE);
|
||||
|
||||
ProduceOggPage(aOutputBufs);
|
||||
return NS_OK;
|
||||
|
||||
// Force generate a page even if the amount of packet data is not enough.
|
||||
// Usually do so after a header packet.
|
||||
if (aFlags & ContainerWriter::FLUSH_NEEDED) {
|
||||
} else if (aFlags & ContainerWriter::FLUSH_NEEDED) {
|
||||
// rc = 0 means no packet to put into a page, or an internal error.
|
||||
rc = ogg_stream_flush(&mOggStreamState, &mOggPage);
|
||||
} else {
|
||||
@ -104,16 +161,32 @@ OggWriter::GetContainerData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
aOutputBufs->AppendElement();
|
||||
aOutputBufs->LastElement().SetLength(mOggPage.header_len +
|
||||
mOggPage.body_len);
|
||||
memcpy(aOutputBufs->LastElement().Elements(), mOggPage.header,
|
||||
mOggPage.header_len);
|
||||
memcpy(aOutputBufs->LastElement().Elements() + mOggPage.header_len,
|
||||
mOggPage.body, mOggPage.body_len);
|
||||
ProduceOggPage(aOutputBufs);
|
||||
}
|
||||
|
||||
return (rc > 0) ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
OggWriter::SetMetadata(nsRefPtr<TrackMetadataBase> aMetadata)
|
||||
{
|
||||
if (aMetadata->GetKind() != TrackMetadataBase::METADATA_OPUS) {
|
||||
LOG("wrong meta data type!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Validate each field of METADATA
|
||||
OpusMetadata* meta = static_cast<OpusMetadata*>(aMetadata.get());
|
||||
if (meta->mIdHeader.Length() == 0) {
|
||||
LOG("miss mIdHeader!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (meta->mCommentHeader.Length() == 0) {
|
||||
LOG("miss mCommentHeader!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mMetadata = aMetadata;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,15 +22,23 @@ class OggWriter : public ContainerWriter
|
||||
public:
|
||||
OggWriter();
|
||||
|
||||
nsresult WriteEncodedTrack(const nsTArray<uint8_t>& aBuffer, int aDuration,
|
||||
nsresult WriteEncodedTrack(const EncodedFrameContainer &aData,
|
||||
uint32_t aFlags = 0) MOZ_OVERRIDE;
|
||||
|
||||
nsresult GetContainerData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
|
||||
uint32_t aFlags = 0) MOZ_OVERRIDE;
|
||||
|
||||
// Check metadata type integrity and reject unacceptable track encoder.
|
||||
nsresult SetMetadata(nsRefPtr<TrackMetadataBase> aMetadata) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
nsresult Init();
|
||||
|
||||
nsresult WriteEncodedData(const nsTArray<uint8_t>& aBuffer, int aDuration,
|
||||
uint32_t aFlags = 0);
|
||||
|
||||
void ProduceOggPage(nsTArray<nsTArray<uint8_t> >* aOutputBufs);
|
||||
|
||||
ogg_stream_state mOggStreamState;
|
||||
ogg_page mOggPage;
|
||||
ogg_packet mPacket;
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "nsRuleProcessorData.h"
|
||||
#include "nsIWeakReference.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsDOMCID.h"
|
||||
#include "nsIDOMScriptObjectFactory.h"
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
#include "nsXULContentSink.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "js/Tracer.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "mozAutoDocUpdate.h"
|
||||
#include "nsTextNode.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "pldhash.h"
|
||||
#include "rdf.h"
|
||||
|
||||
|
@ -8751,7 +8751,7 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
||||
|
||||
nsISupports* context = requestingElement;
|
||||
if (!context) {
|
||||
context = nsGlobalWindow::ToSupports(mScriptGlobal);
|
||||
context = ToSupports(mScriptGlobal);
|
||||
}
|
||||
|
||||
// XXXbz would be nice to know the loading principal here... but we don't
|
||||
|
@ -302,6 +302,11 @@ this.PermissionsTable = { geolocation: {
|
||||
privileged: PROMPT_ACTION,
|
||||
certified: PROMPT_ACTION
|
||||
},
|
||||
"video-capture": {
|
||||
app: PROMPT_ACTION,
|
||||
privileged: PROMPT_ACTION,
|
||||
certified: PROMPT_ACTION
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -3,3 +3,5 @@
|
||||
[test_apps_service.xul]
|
||||
[test_operator_app_install.js]
|
||||
[test_operator_app_install.xul]
|
||||
# bug 928262
|
||||
skip-if = os == "win"
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsprf.h"
|
||||
#include "js/OldDebugAPI.h"
|
||||
#include "mozilla/HoldDropJSObjects.h"
|
||||
|
@ -91,7 +91,7 @@ WindowNamedPropertiesHandler::getOwnPropertyDescriptor(JSContext* aCx,
|
||||
nsCOMPtr<nsPIDOMWindow> piWin = do_QueryWrappedNative(wrapper);
|
||||
MOZ_ASSERT(piWin);
|
||||
nsGlobalWindow* win = static_cast<nsGlobalWindow*>(piWin.get());
|
||||
if (win->GetLength() > 0) {
|
||||
if (win->Length() > 0) {
|
||||
nsCOMPtr<nsIDOMWindow> childWin = win->GetChildWindow(str);
|
||||
if (childWin && ShouldExposeChildWindow(str, childWin)) {
|
||||
// We found a subframe of the right name. Shadowing via |var foo| in
|
||||
|
@ -2,19 +2,155 @@
|
||||
* 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);
|
||||
@ -26,14 +162,12 @@ nsContentPermissionRequestProxy::~nsContentPermissionRequestProxy()
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsContentPermissionRequestProxy::Init(const nsACString & type,
|
||||
const nsACString & access,
|
||||
nsContentPermissionRequestProxy::Init(const nsTArray<PermissionRequest>& requests,
|
||||
ContentPermissionRequestParent* parent)
|
||||
{
|
||||
NS_ASSERTION(parent, "null parent");
|
||||
mParent = parent;
|
||||
mType = type;
|
||||
mAccess = access;
|
||||
mPermissionRequests = requests;
|
||||
|
||||
nsCOMPtr<nsIContentPermissionPrompt> prompt = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
|
||||
if (!prompt) {
|
||||
@ -53,17 +187,14 @@ nsContentPermissionRequestProxy::OnParentDestroyed()
|
||||
NS_IMPL_ISUPPORTS1(nsContentPermissionRequestProxy, nsIContentPermissionRequest)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsContentPermissionRequestProxy::GetType(nsACString & aType)
|
||||
nsContentPermissionRequestProxy::GetTypes(nsIArray** aTypes)
|
||||
{
|
||||
aType = mType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsContentPermissionRequestProxy::GetAccess(nsACString & aAccess)
|
||||
{
|
||||
aAccess = mAccess;
|
||||
return NS_OK;
|
||||
nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
if (ConvertPermissionRequestToArray(mPermissionRequests, types)) {
|
||||
types.forget(aTypes);
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -134,55 +265,3 @@ nsContentPermissionRequestProxy::Allow()
|
||||
mParent = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
ContentPermissionRequestParent::ContentPermissionRequestParent(const nsACString& aType,
|
||||
const nsACString& aAccess,
|
||||
Element* aElement,
|
||||
const IPC::Principal& aPrincipal)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ContentPermissionRequestParent);
|
||||
|
||||
mPrincipal = aPrincipal;
|
||||
mElement = aElement;
|
||||
mType = aType;
|
||||
mAccess = aAccess;
|
||||
}
|
||||
|
||||
ContentPermissionRequestParent::~ContentPermissionRequestParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(ContentPermissionRequestParent);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentPermissionRequestParent::Recvprompt()
|
||||
{
|
||||
mProxy = new nsContentPermissionRequestProxy();
|
||||
NS_ASSERTION(mProxy, "Alloc of request proxy failed");
|
||||
if (NS_FAILED(mProxy->Init(mType, mAccess, this))) {
|
||||
mProxy->Cancel();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ContentPermissionRequestParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (mProxy) {
|
||||
mProxy->OnParentDestroyed();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ContentPermissionRequestParent::IsBeingDestroyed()
|
||||
{
|
||||
// When TabParent::Destroy() is called, we are being destroyed. It's unsafe
|
||||
// to send out any message now.
|
||||
TabParent* tabParent = static_cast<TabParent*>(Manager());
|
||||
return tabParent->IsDestroyed();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -6,60 +6,75 @@
|
||||
#define nsContentPermissionHelper_h
|
||||
|
||||
#include "nsIContentPermissionPrompt.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||
#include "mozilla/dom/PContentPermissionRequestParent.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIMutableArray.h"
|
||||
|
||||
class nsContentPermissionRequestProxy;
|
||||
|
||||
// Forward declare IPC::Principal here which is defined in
|
||||
// PermissionMessageUtils.h. Include this file will transitively includes
|
||||
// "windows.h" and it defines
|
||||
// #define CreateEvent CreateEventW
|
||||
// #define LoadImage LoadImageW
|
||||
// That will mess up windows build.
|
||||
namespace IPC {
|
||||
class Principal;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class Element;
|
||||
class PermissionRequest;
|
||||
class ContentPermissionRequestParent;
|
||||
class PContentPermissionRequestParent;
|
||||
|
||||
class ContentPermissionRequestParent : public PContentPermissionRequestParent
|
||||
class ContentPermissionType : public nsIContentPermissionType
|
||||
{
|
||||
public:
|
||||
ContentPermissionRequestParent(const nsACString& type,
|
||||
const nsACString& access,
|
||||
Element* element,
|
||||
const IPC::Principal& principal);
|
||||
virtual ~ContentPermissionRequestParent();
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICONTENTPERMISSIONTYPE
|
||||
|
||||
bool IsBeingDestroyed();
|
||||
ContentPermissionType(const nsACString& aType, const nsACString& aAccess);
|
||||
virtual ~ContentPermissionType();
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<Element> mElement;
|
||||
nsCOMPtr<nsContentPermissionRequestProxy> mProxy;
|
||||
protected:
|
||||
nsCString mType;
|
||||
nsCString mAccess;
|
||||
|
||||
private:
|
||||
virtual bool Recvprompt();
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
};
|
||||
|
||||
uint32_t ConvertPermissionRequestToArray(nsTArray<PermissionRequest>& aSrcArray,
|
||||
nsIMutableArray* aDesArray);
|
||||
|
||||
nsresult CreatePermissionArray(const nsACString& aType,
|
||||
const nsACString& aAccess,
|
||||
nsIArray** aTypesArray);
|
||||
|
||||
PContentPermissionRequestParent*
|
||||
CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
|
||||
Element* element,
|
||||
const IPC::Principal& principal);
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsContentPermissionRequestProxy : public nsIContentPermissionRequest
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICONTENTPERMISSIONREQUEST
|
||||
|
||||
nsContentPermissionRequestProxy();
|
||||
virtual ~nsContentPermissionRequestProxy();
|
||||
|
||||
nsresult Init(const nsACString& type, const nsACString& access, mozilla::dom::ContentPermissionRequestParent* parent);
|
||||
nsresult Init(const nsTArray<mozilla::dom::PermissionRequest>& requests,
|
||||
mozilla::dom::ContentPermissionRequestParent* parent);
|
||||
void OnParentDestroyed();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICONTENTPERMISSIONREQUEST
|
||||
|
||||
private:
|
||||
// Non-owning pointer to the ContentPermissionRequestParent object which owns this proxy.
|
||||
mozilla::dom::ContentPermissionRequestParent* mParent;
|
||||
nsCString mType;
|
||||
nsCString mAccess;
|
||||
nsTArray<mozilla::dom::PermissionRequest> mPermissionRequests;
|
||||
};
|
||||
#endif // nsContentPermissionHelper_h
|
||||
|
||||
#endif // nsContentPermissionHelper_h
|
||||
|
@ -63,7 +63,8 @@ DOMCI_CASTABLE_INTERFACE(nsStyledElement, nsStyledElement, 8, _extra) \
|
||||
DOMCI_CASTABLE_INTERFACE(nsSVGElement, nsIContent, 9, _extra) \
|
||||
/* NOTE: When removing the casts below, remove the nsDOMEventBase class */ \
|
||||
DOMCI_CASTABLE_INTERFACE(nsDOMMouseEvent, nsDOMEventBase, 10, _extra) \
|
||||
DOMCI_CASTABLE_INTERFACE(nsDOMUIEvent, nsDOMEventBase, 11, _extra)
|
||||
DOMCI_CASTABLE_INTERFACE(nsDOMUIEvent, nsDOMEventBase, 11, _extra) \
|
||||
DOMCI_CASTABLE_INTERFACE(nsGlobalWindow, nsIDOMEventTarget, 12, _extra)
|
||||
|
||||
// Make sure all classes mentioned in DOMCI_CASTABLE_INTERFACES
|
||||
// have been declared.
|
||||
|
@ -2,11 +2,11 @@
|
||||
* 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/. */
|
||||
|
||||
|
||||
#ifndef nsDOMJSUtils_h__
|
||||
#define nsDOMJSUtils_h__
|
||||
|
||||
#include "nsIScriptContext.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
class nsIJSArgArray;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -46,7 +46,6 @@
|
||||
#include "nsIIdleObserver.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMTouchEvent.h"
|
||||
|
||||
#include "mozilla/dom/EventTarget.h"
|
||||
#include "Units.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
@ -79,6 +78,7 @@
|
||||
class nsIArray;
|
||||
class nsIBaseWindow;
|
||||
class nsIContent;
|
||||
class nsICSSDeclaration;
|
||||
class nsIDocShellTreeOwner;
|
||||
class nsIDOMCrypto;
|
||||
class nsIDOMOfflineResourceList;
|
||||
@ -106,6 +106,7 @@ class nsWindowSizes;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class BarProp;
|
||||
class Function;
|
||||
class Gamepad;
|
||||
class Navigator;
|
||||
class SpeechSynthesis;
|
||||
@ -121,6 +122,17 @@ NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow,
|
||||
int32_t *aInterval,
|
||||
nsIScriptTimeoutHandler **aRet);
|
||||
|
||||
extern already_AddRefed<nsIScriptTimeoutHandler>
|
||||
NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow,
|
||||
mozilla::dom::Function& aFunction,
|
||||
const mozilla::dom::Sequence<JS::Value>& aArguments,
|
||||
mozilla::ErrorResult& aError);
|
||||
|
||||
extern already_AddRefed<nsIScriptTimeoutHandler>
|
||||
NS_CreateJSTimeoutHandler(JSContext* aCx, nsGlobalWindow *aWindow,
|
||||
const nsAString& aExpression,
|
||||
mozilla::ErrorResult& aError);
|
||||
|
||||
/*
|
||||
* Timeout struct that holds information about each script
|
||||
* timeout. Holds a strong reference to an nsIScriptTimeoutHandler, which
|
||||
@ -306,7 +318,6 @@ class nsGlobalWindow : public mozilla::dom::EventTarget,
|
||||
public:
|
||||
typedef mozilla::TimeStamp TimeStamp;
|
||||
typedef mozilla::TimeDuration TimeDuration;
|
||||
typedef mozilla::dom::Navigator Navigator;
|
||||
typedef nsDataHashtable<nsUint64HashKey, nsGlobalWindow*> WindowByIdTable;
|
||||
|
||||
// public methods
|
||||
@ -456,7 +467,6 @@ public:
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
|
||||
// WebIDL interface.
|
||||
uint32_t GetLength();
|
||||
already_AddRefed<nsIDOMWindow> IndexedGetter(uint32_t aIndex, bool& aFound);
|
||||
|
||||
void GetSupportedNames(nsTArray<nsString>& aNames);
|
||||
@ -469,11 +479,6 @@ public:
|
||||
// Make sure this matches the casts we do in QueryInterface().
|
||||
return (nsGlobalWindow *)(mozilla::dom::EventTarget *)supports;
|
||||
}
|
||||
static nsISupports *ToSupports(nsGlobalWindow *win)
|
||||
{
|
||||
// Make sure this matches the casts we do in QueryInterface().
|
||||
return (nsISupports *)(mozilla::dom::EventTarget *)win;
|
||||
}
|
||||
static nsGlobalWindow *FromWrapper(nsIXPConnectWrappedNative *wrapper)
|
||||
{
|
||||
return FromSupports(wrapper->Native());
|
||||
@ -502,10 +507,7 @@ public:
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindow> top;
|
||||
GetScriptableTop(getter_AddRefs(top));
|
||||
if (top) {
|
||||
return static_cast<nsGlobalWindow *>(top.get());
|
||||
}
|
||||
return nullptr;
|
||||
return static_cast<nsGlobalWindow *>(top.get());
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMWindow> GetChildWindow(const nsAString& aName);
|
||||
@ -761,11 +763,177 @@ public:
|
||||
#undef ERROR_EVENT
|
||||
#undef EVENT
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
mozilla::dom::SpeechSynthesis* GetSpeechSynthesisInternal();
|
||||
#endif
|
||||
nsISupports* GetParentObject()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mozilla::dom::BarProp* GetScrollbars();
|
||||
nsIDOMWindow* GetWindow(mozilla::ErrorResult& aError);
|
||||
nsIDOMWindow* GetSelf(mozilla::ErrorResult& aError);
|
||||
nsIDocument* GetDocument()
|
||||
{
|
||||
return GetDoc();
|
||||
}
|
||||
void GetName(nsAString& aName, mozilla::ErrorResult& aError);
|
||||
void SetName(const nsAString& aName, mozilla::ErrorResult& aError);
|
||||
nsIDOMLocation* GetLocation(mozilla::ErrorResult& aError);
|
||||
nsHistory* GetHistory(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::BarProp* GetLocationbar(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::BarProp* GetMenubar(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::BarProp* GetPersonalbar(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::BarProp* GetScrollbars(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::BarProp* GetStatusbar(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::BarProp* GetToolbar(mozilla::ErrorResult& aError);
|
||||
void GetStatus(nsAString& aStatus, mozilla::ErrorResult& aError);
|
||||
void SetStatus(const nsAString& aStatus, mozilla::ErrorResult& aError);
|
||||
void Close(mozilla::ErrorResult& aError);
|
||||
bool GetClosed(mozilla::ErrorResult& aError);
|
||||
void Stop(mozilla::ErrorResult& aError);
|
||||
void Focus(mozilla::ErrorResult& aError);
|
||||
void Blur(mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsIDOMWindow> GetFrames(mozilla::ErrorResult& aError);
|
||||
uint32_t Length();
|
||||
already_AddRefed<nsIDOMWindow> GetTop(mozilla::ErrorResult& aError)
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindow> top;
|
||||
aError = GetScriptableTop(getter_AddRefs(top));
|
||||
return top.forget();
|
||||
}
|
||||
nsIDOMWindow* GetOpener(mozilla::ErrorResult& aError);
|
||||
void SetOpener(nsIDOMWindow* aOpener, mozilla::ErrorResult& aError);
|
||||
using nsIDOMWindow::GetParent;
|
||||
already_AddRefed<nsIDOMWindow> GetParent(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::Element* GetFrameElement(mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsIDOMWindow> Open(const nsAString& aUrl,
|
||||
const nsAString& aName,
|
||||
const nsAString& aOptions,
|
||||
mozilla::ErrorResult& aError);
|
||||
mozilla::dom::Navigator* GetNavigator(mozilla::ErrorResult& aError);
|
||||
nsIDOMOfflineResourceList* GetApplicationCache(mozilla::ErrorResult& aError);
|
||||
void Alert(const nsAString& aMessage, mozilla::ErrorResult& aError);
|
||||
bool Confirm(const nsAString& aMessage, mozilla::ErrorResult& aError);
|
||||
void Prompt(const nsAString& aMessage, const nsAString& aInitial,
|
||||
nsAString& aReturn, mozilla::ErrorResult& aError);
|
||||
void Print(mozilla::ErrorResult& aError);
|
||||
JS::Value ShowModalDialog(JSContext* aCx, const nsAString& aUrl, const mozilla::dom::Optional<JS::Handle<JS::Value> >& aArgument, const nsAString& aOptions, mozilla::ErrorResult& aError);
|
||||
void PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const nsAString& aTargetOrigin,
|
||||
const mozilla::dom::Optional<mozilla::dom::Sequence<JS::Value > >& aTransfer,
|
||||
mozilla::ErrorResult& aError);
|
||||
int32_t SetTimeout(JSContext* aCx, mozilla::dom::Function& aFunction,
|
||||
int32_t aTimeout,
|
||||
const mozilla::dom::Sequence<JS::Value>& aArguments,
|
||||
mozilla::ErrorResult& aError);
|
||||
int32_t SetTimeout(JSContext* aCx, const nsAString& aHandler,
|
||||
int32_t aTimeout, mozilla::ErrorResult& aError);
|
||||
void ClearTimeout(int32_t aHandle, mozilla::ErrorResult& aError);
|
||||
int32_t SetInterval(JSContext* aCx, mozilla::dom::Function& aFunction,
|
||||
const mozilla::dom::Optional<int32_t>& aTimeout,
|
||||
const mozilla::dom::Sequence<JS::Value>& aArguments,
|
||||
mozilla::ErrorResult& aError);
|
||||
int32_t SetInterval(JSContext* aCx, const nsAString& aHandler,
|
||||
const mozilla::dom::Optional<int32_t>& aTimeout,
|
||||
mozilla::ErrorResult& aError);
|
||||
void ClearInterval(int32_t aHandle, mozilla::ErrorResult& aError);
|
||||
void Atob(const nsAString& aAsciiBase64String, nsAString& aBinaryData,
|
||||
mozilla::ErrorResult& aError);
|
||||
void Btoa(const nsAString& aBinaryData, nsAString& aAsciiBase64String,
|
||||
mozilla::ErrorResult& aError);
|
||||
nsIDOMStorage* GetSessionStorage(mozilla::ErrorResult& aError);
|
||||
nsIDOMStorage* GetLocalStorage(mozilla::ErrorResult& aError);
|
||||
nsISelection* GetSelection(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::indexedDB::IDBFactory* GetIndexedDB(mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsICSSDeclaration>
|
||||
GetComputedStyle(mozilla::dom::Element& aElt, const nsAString& aPseudoElt,
|
||||
mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsIDOMMediaQueryList> MatchMedia(const nsAString& aQuery,
|
||||
mozilla::ErrorResult& aError);
|
||||
nsScreen* GetScreen(mozilla::ErrorResult& aError);
|
||||
void MoveTo(int32_t aXPos, int32_t aYPos, mozilla::ErrorResult& aError);
|
||||
void MoveBy(int32_t aXDif, int32_t aYDif, mozilla::ErrorResult& aError);
|
||||
void ResizeTo(int32_t aWidth, int32_t aHeight,
|
||||
mozilla::ErrorResult& aError);
|
||||
void ResizeBy(int32_t aWidthDif, int32_t aHeightDif,
|
||||
mozilla::ErrorResult& aError);
|
||||
int32_t GetInnerWidth(mozilla::ErrorResult& aError);
|
||||
void SetInnerWidth(int32_t aInnerWidth, mozilla::ErrorResult& aError);
|
||||
int32_t GetInnerHeight(mozilla::ErrorResult& aError);
|
||||
void SetInnerHeight(int32_t aInnerHeight, mozilla::ErrorResult& aError);
|
||||
int32_t GetScrollX(mozilla::ErrorResult& aError);
|
||||
int32_t GetPageXOffset(mozilla::ErrorResult& aError)
|
||||
{
|
||||
return GetScrollX(aError);
|
||||
}
|
||||
int32_t GetScrollY(mozilla::ErrorResult& aError);
|
||||
int32_t GetPageYOffset(mozilla::ErrorResult& aError)
|
||||
{
|
||||
return GetScrollY(aError);
|
||||
}
|
||||
int32_t GetScreenX(mozilla::ErrorResult& aError);
|
||||
void SetScreenX(int32_t aScreenX, mozilla::ErrorResult& aError);
|
||||
int32_t GetScreenY(mozilla::ErrorResult& aError);
|
||||
void SetScreenY(int32_t aScreenY, mozilla::ErrorResult& aError);
|
||||
int32_t GetOuterWidth(mozilla::ErrorResult& aError);
|
||||
void SetOuterWidth(int32_t aOuterWidth, mozilla::ErrorResult& aError);
|
||||
int32_t GetOuterHeight(mozilla::ErrorResult& aError);
|
||||
void SetOuterHeight(int32_t aOuterHeight, mozilla::ErrorResult& aError);
|
||||
int32_t RequestAnimationFrame(mozilla::dom::FrameRequestCallback& aCallback,
|
||||
mozilla::ErrorResult& aError);
|
||||
void CancelAnimationFrame(int32_t aHandle, mozilla::ErrorResult& aError);
|
||||
nsPerformance* GetPerformance(mozilla::ErrorResult& aError);
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
mozilla::dom::SpeechSynthesis*
|
||||
GetSpeechSynthesis(mozilla::ErrorResult& aError);
|
||||
#endif
|
||||
already_AddRefed<nsICSSDeclaration>
|
||||
GetDefaultComputedStyle(mozilla::dom::Element& aElt,
|
||||
const nsAString& aPseudoElt,
|
||||
mozilla::ErrorResult& aError);
|
||||
mozilla::dom::indexedDB::IDBFactory*
|
||||
GetMozIndexedDB(mozilla::ErrorResult& aError)
|
||||
{
|
||||
return GetIndexedDB(aError);
|
||||
}
|
||||
int32_t MozRequestAnimationFrame(nsIFrameRequestCallback* aRequestCallback,
|
||||
mozilla::ErrorResult& aError);
|
||||
void MozCancelAnimationFrame(int32_t aHandle, mozilla::ErrorResult& aError)
|
||||
{
|
||||
return CancelAnimationFrame(aHandle, aError);
|
||||
}
|
||||
void MozCancelRequestAnimationFrame(int32_t aHandle,
|
||||
mozilla::ErrorResult& aError)
|
||||
{
|
||||
return CancelAnimationFrame(aHandle, aError);
|
||||
}
|
||||
int64_t GetMozAnimationStartTime(mozilla::ErrorResult& aError);
|
||||
void SizeToContent(mozilla::ErrorResult& aError);
|
||||
nsIDOMCrypto* GetCrypto(mozilla::ErrorResult& aError);
|
||||
nsIDOMPkcs11* GetPkcs11()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
nsIControllers* GetControllers(mozilla::ErrorResult& aError);
|
||||
float GetMozInnerScreenX(mozilla::ErrorResult& aError);
|
||||
float GetMozInnerScreenY(mozilla::ErrorResult& aError);
|
||||
float GetDevicePixelRatio(mozilla::ErrorResult& aError);
|
||||
int32_t GetScrollMaxX(mozilla::ErrorResult& aError);
|
||||
int32_t GetScrollMaxY(mozilla::ErrorResult& aError);
|
||||
bool GetFullScreen(mozilla::ErrorResult& aError);
|
||||
void SetFullScreen(bool aFullScreen, mozilla::ErrorResult& aError);
|
||||
void Back(mozilla::ErrorResult& aError);
|
||||
void Forward(mozilla::ErrorResult& aError);
|
||||
void Home(mozilla::ErrorResult& aError);
|
||||
bool Find(const nsAString& aString, bool aCaseSensitive, bool aBackwards,
|
||||
bool aWrapAround, bool aWholeWord, bool aSearchInFrames,
|
||||
bool aShowDialog, mozilla::ErrorResult& aError);
|
||||
uint64_t GetMozPaintCount(mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsIDOMWindow> OpenDialog(JSContext* aCx,
|
||||
const nsAString& aUrl,
|
||||
const nsAString& aName,
|
||||
const nsAString& aOptions,
|
||||
const mozilla::dom::Sequence<JS::Value>& aExtraArgument,
|
||||
mozilla::ErrorResult& aError);
|
||||
JSObject* GetContent(JSContext* aCx, mozilla::ErrorResult& aError);
|
||||
|
||||
protected:
|
||||
// Array of idle observers that are notified of idle events.
|
||||
@ -917,7 +1085,21 @@ protected:
|
||||
nsresult SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler,
|
||||
int32_t interval,
|
||||
bool aIsInterval, int32_t *aReturn);
|
||||
nsresult ClearTimeoutOrInterval(int32_t aTimerID);
|
||||
int32_t SetTimeoutOrInterval(mozilla::dom::Function& aFunction,
|
||||
int32_t aTimeout,
|
||||
const mozilla::dom::Sequence<JS::Value>& aArguments,
|
||||
bool aIsInterval, mozilla::ErrorResult& aError);
|
||||
int32_t SetTimeoutOrInterval(JSContext* aCx, const nsAString& aHandler,
|
||||
int32_t aTimeout, bool aIsInterval,
|
||||
mozilla::ErrorResult& aError);
|
||||
void ClearTimeoutOrInterval(int32_t aTimerID,
|
||||
mozilla::ErrorResult& aError);
|
||||
nsresult ClearTimeoutOrInterval(int32_t aTimerID)
|
||||
{
|
||||
mozilla::ErrorResult rv;
|
||||
ClearTimeoutOrInterval(aTimerID, rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
// JS specific timeout functions (JS args grabbed from context).
|
||||
nsresult SetTimeoutOrInterval(bool aIsInterval, int32_t* aReturn);
|
||||
@ -985,15 +1167,17 @@ protected:
|
||||
|
||||
// If aDoFlush is true, we'll flush our own layout; otherwise we'll try to
|
||||
// just flush our parent and only flush ourselves if we think we need to.
|
||||
nsresult GetScrollXY(int32_t* aScrollX, int32_t* aScrollY,
|
||||
bool aDoFlush);
|
||||
nsresult GetScrollMaxXY(int32_t* aScrollMaxX, int32_t* aScrollMaxY);
|
||||
mozilla::CSSIntPoint GetScrollXY(bool aDoFlush, mozilla::ErrorResult& aError);
|
||||
nsresult GetScrollXY(int32_t* aScrollX, int32_t* aScrollY, bool aDoFlush);
|
||||
void GetScrollMaxXY(int32_t* aScrollMaxX, int32_t* aScrollMaxY,
|
||||
mozilla::ErrorResult& aError);
|
||||
|
||||
// Outer windows only.
|
||||
nsresult GetInnerSize(mozilla::CSSIntSize& aSize);
|
||||
|
||||
nsresult GetOuterSize(nsIntSize* aSizeCSSPixels);
|
||||
nsresult SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth);
|
||||
nsIntSize GetOuterSize(mozilla::ErrorResult& aError);
|
||||
void SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth,
|
||||
mozilla::ErrorResult& aError);
|
||||
nsRect GetInnerScreenRect();
|
||||
|
||||
void ScrollTo(const mozilla::CSSIntPoint& aScroll);
|
||||
@ -1079,6 +1263,11 @@ protected:
|
||||
nsDOMWindowList* GetWindowList();
|
||||
|
||||
// Helper for getComputedStyle and getDefaultComputedStyle
|
||||
already_AddRefed<nsICSSDeclaration>
|
||||
GetComputedStyleHelper(mozilla::dom::Element& aElt,
|
||||
const nsAString& aPseudoElt,
|
||||
bool aDefaultStylesOnly,
|
||||
mozilla::ErrorResult& aError);
|
||||
nsresult GetComputedStyleHelper(nsIDOMElement* aElt,
|
||||
const nsAString& aPseudoElt,
|
||||
bool aDefaultStylesOnly,
|
||||
@ -1086,8 +1275,27 @@ protected:
|
||||
|
||||
void PreloadLocalStorage();
|
||||
|
||||
nsresult RequestAnimationFrame(const nsIDocument::FrameRequestCallbackHolder& aCallback,
|
||||
int32_t* aHandle);
|
||||
// Returns device pixels.
|
||||
nsIntPoint GetScreenXY(mozilla::ErrorResult& aError);
|
||||
|
||||
int32_t RequestAnimationFrame(const nsIDocument::FrameRequestCallbackHolder& aCallback,
|
||||
mozilla::ErrorResult& aError);
|
||||
|
||||
nsGlobalWindow* InnerForSetTimeoutOrInterval(mozilla::ErrorResult& aError);
|
||||
|
||||
mozilla::dom::Element* GetRealFrameElement(mozilla::ErrorResult& aError);
|
||||
|
||||
void PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const nsAString& aTargetOrigin,
|
||||
JS::Handle<JS::Value> aTransfer,
|
||||
mozilla::ErrorResult& aError);
|
||||
|
||||
already_AddRefed<nsIVariant>
|
||||
ShowModalDialog(const nsAString& aUrl, nsIVariant* aArgument,
|
||||
const nsAString& aOptions, mozilla::ErrorResult& aError);
|
||||
|
||||
already_AddRefed<nsIDOMWindow>
|
||||
GetContentInternal(mozilla::ErrorResult& aError);
|
||||
|
||||
// When adding new member variables, be careful not to create cycles
|
||||
// through JavaScript. If there is any chance that a member variable
|
||||
@ -1178,7 +1386,7 @@ protected:
|
||||
// For |window.dialogArguments|, via |showModalDialog|.
|
||||
nsRefPtr<DialogValueHolder> mDialogArguments;
|
||||
|
||||
nsRefPtr<Navigator> mNavigator;
|
||||
nsRefPtr<mozilla::dom::Navigator> mNavigator;
|
||||
nsRefPtr<nsScreen> mScreen;
|
||||
nsRefPtr<nsDOMWindowList> mFrames;
|
||||
nsRefPtr<mozilla::dom::BarProp> mMenubar;
|
||||
@ -1284,6 +1492,18 @@ protected:
|
||||
static bool sWarnedAboutWindowInternal;
|
||||
};
|
||||
|
||||
inline nsISupports*
|
||||
ToSupports(nsGlobalWindow *p)
|
||||
{
|
||||
return static_cast<nsIDOMEventTarget*>(p);
|
||||
}
|
||||
|
||||
inline nsISupports*
|
||||
ToCanonicalSupports(nsGlobalWindow *p)
|
||||
{
|
||||
return static_cast<nsIDOMEventTarget*>(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* nsGlobalChromeWindow inherits from nsGlobalWindow. It is the global
|
||||
* object created for a Chrome Window only.
|
||||
|
@ -22,6 +22,7 @@
|
||||
static const char kSetIntervalStr[] = "setInterval";
|
||||
static const char kSetTimeoutStr[] = "setTimeout";
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
// Our JS nsIScriptTimeoutHandler implementation.
|
||||
@ -33,6 +34,13 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsJSScriptTimeoutHandler)
|
||||
|
||||
nsJSScriptTimeoutHandler();
|
||||
// This will call SwapElements on aArguments with an empty array.
|
||||
nsJSScriptTimeoutHandler(nsGlobalWindow *aWindow, Function& aFunction,
|
||||
FallibleTArray<JS::Heap<JS::Value> >& aArguments,
|
||||
ErrorResult& aError);
|
||||
nsJSScriptTimeoutHandler(JSContext* aCx, nsGlobalWindow *aWindow,
|
||||
const nsAString& aExpression, bool* aAllowEval,
|
||||
ErrorResult& aError);
|
||||
~nsJSScriptTimeoutHandler();
|
||||
|
||||
virtual const PRUnichar *GetHandlerText();
|
||||
@ -52,7 +60,7 @@ public:
|
||||
}
|
||||
|
||||
nsresult Init(nsGlobalWindow *aWindow, bool *aIsInterval,
|
||||
int32_t *aInterval);
|
||||
int32_t *aInterval, bool* aAllowEval);
|
||||
|
||||
void ReleaseJSObjects();
|
||||
|
||||
@ -63,9 +71,9 @@ private:
|
||||
uint32_t mLineNo;
|
||||
nsTArray<JS::Heap<JS::Value> > mArgs;
|
||||
|
||||
// The JS expression to evaluate or function to call, if !mExpr
|
||||
// Note this is always a flat string.
|
||||
JS::Heap<JSString*> mExpr;
|
||||
// The expression to evaluate or function to call. If mFunction is non-null
|
||||
// it should be used, else use mExpr.
|
||||
nsString mExpr;
|
||||
nsRefPtr<Function> mFunction;
|
||||
};
|
||||
|
||||
@ -80,14 +88,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsJSScriptTimeoutHandler)
|
||||
if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
|
||||
nsAutoCString name("nsJSScriptTimeoutHandler");
|
||||
if (tmp->mExpr) {
|
||||
name.AppendLiteral(" [");
|
||||
name.Append(tmp->mFileName);
|
||||
name.AppendLiteral(":");
|
||||
name.AppendInt(tmp->mLineNo);
|
||||
name.AppendLiteral("]");
|
||||
}
|
||||
else if (tmp->mFunction) {
|
||||
if (tmp->mFunction) {
|
||||
JSFunction* fun =
|
||||
JS_GetObjectFunction(js::UncheckedUnwrap(tmp->mFunction->Callable()));
|
||||
if (fun && JS_GetFunctionId(fun)) {
|
||||
@ -102,6 +103,12 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsJSScriptTimeoutHandler)
|
||||
name.AppendLiteral("]");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
name.AppendLiteral(" [");
|
||||
name.Append(tmp->mFileName);
|
||||
name.AppendLiteral(":");
|
||||
name.AppendInt(tmp->mLineNo);
|
||||
name.AppendLiteral("]");
|
||||
}
|
||||
cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name.get());
|
||||
}
|
||||
@ -110,12 +117,13 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsJSScriptTimeoutHandler)
|
||||
tmp->mRefCnt.get())
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFunction)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
if (tmp->mFunction) {
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFunction)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSScriptTimeoutHandler)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mExpr)
|
||||
for (uint32_t i = 0; i < tmp->mArgs.Length(); ++i) {
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mArgs[i])
|
||||
}
|
||||
@ -129,10 +137,104 @@ NS_INTERFACE_MAP_END
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsJSScriptTimeoutHandler)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsJSScriptTimeoutHandler)
|
||||
|
||||
nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler() :
|
||||
mLineNo(0),
|
||||
mExpr(nullptr)
|
||||
static bool
|
||||
CheckCSPForEval(JSContext* aCx, nsGlobalWindow* aWindow, ErrorResult& aError)
|
||||
{
|
||||
// if CSP is enabled, and setTimeout/setInterval was called with a string,
|
||||
// disable the registration and log an error
|
||||
nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
|
||||
if (!doc) {
|
||||
// if there's no document, we don't have to do anything.
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
aError = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
if (aError.Failed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!csp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool allowsEval = true;
|
||||
bool reportViolation = false;
|
||||
aError = csp->GetAllowsEval(&reportViolation, &allowsEval);
|
||||
if (aError.Failed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (reportViolation) {
|
||||
// TODO : need actual script sample in violation report.
|
||||
NS_NAMED_LITERAL_STRING(scriptSample,
|
||||
"call to eval() or related function blocked by CSP");
|
||||
|
||||
// Get the calling location.
|
||||
uint32_t lineNum = 0;
|
||||
const char *fileName;
|
||||
nsAutoString fileNameString;
|
||||
if (nsJSUtils::GetCallingLocation(aCx, &fileName, &lineNum)) {
|
||||
AppendUTF8toUTF16(fileName, fileNameString);
|
||||
} else {
|
||||
fileNameString.AssignLiteral("unknown");
|
||||
}
|
||||
|
||||
csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL,
|
||||
fileNameString, scriptSample, lineNum);
|
||||
}
|
||||
|
||||
return allowsEval;
|
||||
}
|
||||
|
||||
nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler() :
|
||||
mLineNo(0)
|
||||
{
|
||||
}
|
||||
|
||||
nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler(nsGlobalWindow *aWindow,
|
||||
Function& aFunction,
|
||||
FallibleTArray<JS::Heap<JS::Value> >& aArguments,
|
||||
ErrorResult& aError) :
|
||||
mLineNo(0),
|
||||
mFunction(&aFunction)
|
||||
{
|
||||
if (!aWindow->GetContextInternal() || !aWindow->FastGetGlobalJSObject()) {
|
||||
// This window was already closed, or never properly initialized,
|
||||
// don't let a timer be scheduled on such a window.
|
||||
aError.Throw(NS_ERROR_NOT_INITIALIZED);
|
||||
return;
|
||||
}
|
||||
|
||||
mozilla::HoldJSObjects(this);
|
||||
mArgs.SwapElements(aArguments);
|
||||
}
|
||||
|
||||
nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler(JSContext* aCx,
|
||||
nsGlobalWindow *aWindow,
|
||||
const nsAString& aExpression,
|
||||
bool* aAllowEval,
|
||||
ErrorResult& aError) :
|
||||
mLineNo(0),
|
||||
mExpr(aExpression)
|
||||
{
|
||||
if (!aWindow->GetContextInternal() || !aWindow->FastGetGlobalJSObject()) {
|
||||
// This window was already closed, or never properly initialized,
|
||||
// don't let a timer be scheduled on such a window.
|
||||
aError.Throw(NS_ERROR_NOT_INITIALIZED);
|
||||
return;
|
||||
}
|
||||
|
||||
*aAllowEval = CheckCSPForEval(aCx, aWindow, aError);
|
||||
if (aError.Failed() || !*aAllowEval) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the calling location.
|
||||
const char *filename;
|
||||
if (nsJSUtils::GetCallingLocation(aCx, &filename, &mLineNo)) {
|
||||
mFileName.Assign(filename);
|
||||
}
|
||||
}
|
||||
|
||||
nsJSScriptTimeoutHandler::~nsJSScriptTimeoutHandler()
|
||||
@ -143,18 +245,16 @@ nsJSScriptTimeoutHandler::~nsJSScriptTimeoutHandler()
|
||||
void
|
||||
nsJSScriptTimeoutHandler::ReleaseJSObjects()
|
||||
{
|
||||
if (mExpr) {
|
||||
mExpr = nullptr;
|
||||
} else {
|
||||
if (mFunction) {
|
||||
mFunction = nullptr;
|
||||
mArgs.Clear();
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJSScriptTimeoutHandler::Init(nsGlobalWindow *aWindow, bool *aIsInterval,
|
||||
int32_t *aInterval)
|
||||
int32_t *aInterval, bool *aAllowEval)
|
||||
{
|
||||
if (!aWindow->GetContextInternal() || !aWindow->FastGetGlobalJSObject()) {
|
||||
// This window was already closed, or never properly initialized,
|
||||
@ -238,51 +338,16 @@ nsJSScriptTimeoutHandler::Init(nsGlobalWindow *aWindow, bool *aIsInterval,
|
||||
}
|
||||
|
||||
if (expr) {
|
||||
// if CSP is enabled, and setTimeout/setInterval was called with a string
|
||||
// or object, disable the registration and log an error
|
||||
nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
|
||||
// if CSP is enabled, and setTimeout/setInterval was called with a string,
|
||||
// disable the registration and log an error
|
||||
ErrorResult error;
|
||||
*aAllowEval = CheckCSPForEval(cx, aWindow, error);
|
||||
if (error.Failed() || !*aAllowEval) {
|
||||
return error.ErrorCode();
|
||||
}
|
||||
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
nsresult rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (csp) {
|
||||
bool allowsEval = true;
|
||||
bool reportViolation = false;
|
||||
rv = csp->GetAllowsEval(&reportViolation, &allowsEval);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (reportViolation) {
|
||||
// TODO : need actual script sample in violation report.
|
||||
NS_NAMED_LITERAL_STRING(scriptSample, "call to eval() or related function blocked by CSP");
|
||||
|
||||
// Get the calling location.
|
||||
uint32_t lineNum = 0;
|
||||
const char *fileName;
|
||||
nsAutoCString aFileName;
|
||||
if (nsJSUtils::GetCallingLocation(cx, &fileName, &lineNum)) {
|
||||
aFileName.Assign(fileName);
|
||||
} else {
|
||||
aFileName.Assign("unknown");
|
||||
}
|
||||
|
||||
csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL,
|
||||
NS_ConvertUTF8toUTF16(aFileName),
|
||||
scriptSample,
|
||||
lineNum);
|
||||
}
|
||||
|
||||
if (!allowsEval) {
|
||||
// Note: Our only caller knows to turn NS_ERROR_DOM_TYPE_ERR into NS_OK.
|
||||
return NS_ERROR_DOM_TYPE_ERR;
|
||||
}
|
||||
}
|
||||
} // if there's no document, we don't have to do anything.
|
||||
|
||||
mozilla::HoldJSObjects(this);
|
||||
|
||||
mExpr = JS_FORGET_STRING_FLATNESS(expr);
|
||||
mExpr.Append(JS_GetFlatStringChars(expr),
|
||||
JS_GetStringLength(JS_FORGET_STRING_FLATNESS(expr)));
|
||||
|
||||
// Get the calling location.
|
||||
const char *filename;
|
||||
@ -290,6 +355,8 @@ nsJSScriptTimeoutHandler::Init(nsGlobalWindow *aWindow, bool *aIsInterval,
|
||||
mFileName.Assign(filename);
|
||||
}
|
||||
} else if (funobj) {
|
||||
*aAllowEval = true;
|
||||
|
||||
mozilla::HoldJSObjects(this);
|
||||
|
||||
mFunction = new Function(funobj);
|
||||
@ -320,8 +387,8 @@ nsJSScriptTimeoutHandler::Init(nsGlobalWindow *aWindow, bool *aIsInterval,
|
||||
const PRUnichar *
|
||||
nsJSScriptTimeoutHandler::GetHandlerText()
|
||||
{
|
||||
NS_ASSERTION(mExpr, "No expression, so no handler text!");
|
||||
return ::JS_GetFlatStringChars(JS_ASSERT_STRING_IS_FLAT(mExpr));
|
||||
NS_ASSERTION(!mFunction, "No expression, so no handler text!");
|
||||
return mExpr.get();
|
||||
}
|
||||
|
||||
nsresult NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow,
|
||||
@ -331,8 +398,9 @@ nsresult NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow,
|
||||
{
|
||||
*aRet = nullptr;
|
||||
nsRefPtr<nsJSScriptTimeoutHandler> handler = new nsJSScriptTimeoutHandler();
|
||||
nsresult rv = handler->Init(aWindow, aIsInterval, aInterval);
|
||||
if (NS_FAILED(rv)) {
|
||||
bool allowEval;
|
||||
nsresult rv = handler->Init(aWindow, aIsInterval, aInterval, &allowEval);
|
||||
if (NS_FAILED(rv) || !allowEval) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -340,3 +408,34 @@ nsresult NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow,
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIScriptTimeoutHandler>
|
||||
NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow, Function& aFunction,
|
||||
const Sequence<JS::Value>& aArguments,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
FallibleTArray<JS::Heap<JS::Value> > args;
|
||||
if (!args.AppendElements(aArguments)) {
|
||||
aError.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsRefPtr<nsJSScriptTimeoutHandler> handler =
|
||||
new nsJSScriptTimeoutHandler(aWindow, aFunction, args, aError);
|
||||
return aError.Failed() ? nullptr : handler.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIScriptTimeoutHandler>
|
||||
NS_CreateJSTimeoutHandler(JSContext* aCx, nsGlobalWindow *aWindow,
|
||||
const nsAString& aExpression, ErrorResult& aError)
|
||||
{
|
||||
ErrorResult rv;
|
||||
bool allowEval = false;
|
||||
nsRefPtr<nsJSScriptTimeoutHandler> handler =
|
||||
new nsJSScriptTimeoutHandler(aCx, aWindow, aExpression, &allowEval, rv);
|
||||
if (rv.Failed() || !allowEval) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return handler.forget();
|
||||
}
|
||||
|
@ -451,7 +451,10 @@ GetWrapperCache(nsWrapperCache* cache)
|
||||
}
|
||||
|
||||
inline nsWrapperCache*
|
||||
GetWrapperCache(nsGlobalWindow* not_allowed);
|
||||
GetWrapperCache(nsGlobalWindow*)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline nsWrapperCache*
|
||||
GetWrapperCache(void* p)
|
||||
|
@ -1417,6 +1417,16 @@ DOMInterfaces = {
|
||||
'nativeType': 'mozilla::dom::DOMWheelEvent',
|
||||
},
|
||||
|
||||
'Window': {
|
||||
'nativeType': 'nsGlobalWindow',
|
||||
'hasXPConnectImpls': True,
|
||||
'register': False,
|
||||
'implicitJSContext': [ 'setInterval', 'setTimeout' ],
|
||||
'binaryNames': {
|
||||
'postMessage': 'postMessageMoz',
|
||||
},
|
||||
},
|
||||
|
||||
'WindowProxy': [
|
||||
{
|
||||
'nativeType': 'nsIDOMWindow',
|
||||
@ -1437,12 +1447,18 @@ DOMInterfaces = {
|
||||
'nativeType': 'mozilla::dom::workers::MessagePort',
|
||||
'headerFile': 'mozilla/dom/workers/bindings/MessagePort.h',
|
||||
'implicitJSContext': [ 'postMessage' ],
|
||||
'binaryNames': {
|
||||
'postMessage': 'postMessageMoz',
|
||||
},
|
||||
},
|
||||
{
|
||||
'nativeType': 'mozilla::dom::workers::WorkerMessagePort',
|
||||
'headerFile': 'mozilla/dom/workers/bindings/WorkerMessagePort.h',
|
||||
'workers': True,
|
||||
'nativeOwnership': 'worker',
|
||||
'binaryNames': {
|
||||
'postMessage': 'postMessageMoz',
|
||||
},
|
||||
}],
|
||||
|
||||
'WorkerNavigator': {
|
||||
@ -1796,6 +1812,7 @@ def addExternalIface(iface, nativeType=None, headerFile=None,
|
||||
domInterface['notflattened'] = notflattened
|
||||
DOMInterfaces[iface] = domInterface
|
||||
|
||||
addExternalIface('ApplicationCache', nativeType='nsIDOMOfflineResourceList')
|
||||
addExternalIface('ActivityOptions', nativeType='nsIDOMMozActivityOptions',
|
||||
headerFile='nsIDOMActivityOptions.h')
|
||||
addExternalIface('Counter')
|
||||
@ -1812,11 +1829,14 @@ addExternalIface('imgINotificationObserver', nativeType='imgINotificationObserve
|
||||
addExternalIface('imgIRequest', nativeType='imgIRequest', notflattened=True)
|
||||
addExternalIface('LockedFile')
|
||||
addExternalIface('MediaList')
|
||||
addExternalIface('MediaQueryList')
|
||||
addExternalIface('MenuBuilder', nativeType='nsIMenuBuilder', notflattened=True)
|
||||
addExternalIface('MozBoxObject', nativeType='nsIBoxObject')
|
||||
addExternalIface('MozConnection', headerFile='nsIDOMConnection.h')
|
||||
addExternalIface('MozControllers', nativeType='nsIControllers')
|
||||
addExternalIface('MozFrameLoader', nativeType='nsIFrameLoader', notflattened=True)
|
||||
addExternalIface('MozFrameRequestCallback', nativeType='nsIFrameRequestCallback',
|
||||
notflattened=True);
|
||||
addExternalIface('MozIccManager', headerFile='nsIDOMIccManager.h')
|
||||
addExternalIface('MozMobileConnection', headerFile='nsIDOMMobileConnection.h')
|
||||
addExternalIface('MozMobileMessageManager', headerFile='nsIDOMMobileMessageManager.h')
|
||||
@ -1833,6 +1853,8 @@ addExternalIface('MozWakeLock', headerFile='nsIDOMWakeLock.h')
|
||||
addExternalIface('MozWakeLockListener', headerFile='nsIDOMWakeLockListener.h')
|
||||
addExternalIface('MozXULTemplateBuilder', nativeType='nsIXULTemplateBuilder')
|
||||
addExternalIface('nsIControllers', nativeType='nsIControllers')
|
||||
addExternalIface('nsIDOMCrypto', nativeType='nsIDOMCrypto',
|
||||
headerFile='Crypto.h')
|
||||
addExternalIface('nsIInputStreamCallback', nativeType='nsIInputStreamCallback',
|
||||
headerFile='nsIAsyncInputStream.h')
|
||||
addExternalIface('nsIStreamListener', nativeType='nsIStreamListener', notflattened=True)
|
||||
@ -1841,6 +1863,7 @@ addExternalIface('nsIEditor', nativeType='nsIEditor', notflattened=True)
|
||||
addExternalIface('nsIVariant', nativeType='nsIVariant', notflattened=True)
|
||||
addExternalIface('OutputStream', nativeType='nsIOutputStream',
|
||||
notflattened=True)
|
||||
addExternalIface('Pkcs11')
|
||||
addExternalIface('Principal', nativeType='nsIPrincipal',
|
||||
headerFile='nsIPrincipal.h', notflattened=True)
|
||||
addExternalIface('Selection', nativeType='nsISelection')
|
||||
@ -1852,7 +1875,6 @@ addExternalIface('SVGNumber')
|
||||
addExternalIface('URI', nativeType='nsIURI', headerFile='nsIURI.h',
|
||||
notflattened=True)
|
||||
addExternalIface('UserDataHandler')
|
||||
addExternalIface('Window')
|
||||
addExternalIface('XPathResult', nativeType='nsISupports')
|
||||
addExternalIface('XPathExpression')
|
||||
addExternalIface('XPathNSResolver')
|
||||
|
@ -171,8 +171,6 @@ class CGDOMJSClass(CGThing):
|
||||
def __init__(self, descriptor):
|
||||
CGThing.__init__(self)
|
||||
self.descriptor = descriptor
|
||||
# Our current reserved slot situation is unsafe for globals. Fix bug 760095!
|
||||
assert "Window" not in descriptor.interface.identifier.name
|
||||
def declare(self):
|
||||
return ""
|
||||
def define(self):
|
||||
@ -2154,6 +2152,11 @@ def CreateBindingJSObject(descriptor, properties, parent):
|
||||
|
||||
js::SetReservedSlot(obj, DOM_OBJECT_SLOT, PRIVATE_TO_JSVAL(aObject));
|
||||
"""
|
||||
if "Window" in descriptor.interface.identifier.name:
|
||||
create = """ MOZ_ASSERT(false,
|
||||
"Our current reserved slot situation is unsafe for globals. Fix "
|
||||
"bug 760095!");
|
||||
""" + create
|
||||
create = objDecl + create
|
||||
|
||||
if descriptor.nativeOwnership == 'refcounted':
|
||||
@ -3058,14 +3061,21 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||
typeName = "Nullable<" + typeName + " >"
|
||||
|
||||
def handleNull(templateBody, setToNullVar, extraConditionForNull=""):
|
||||
null = CGGeneric("if (%s${val}.isNullOrUndefined()) {\n"
|
||||
" %s.SetNull();\n"
|
||||
"}" % (extraConditionForNull, setToNullVar))
|
||||
templateBody = CGWrapper(CGIndenter(templateBody), pre="{\n", post="\n}")
|
||||
return CGList([null, templateBody], " else ")
|
||||
nullTest = "%s${val}.isNullOrUndefined()" % extraConditionForNull
|
||||
return CGIfElseWrapper(nullTest,
|
||||
CGGeneric("%s.SetNull();" % setToNullVar),
|
||||
templateBody)
|
||||
|
||||
if type.hasNullableType:
|
||||
templateBody = handleNull(templateBody, unionArgumentObj)
|
||||
assert not nullable
|
||||
# Make sure to handle a null default value here
|
||||
if defaultValue and isinstance(defaultValue, IDLNullValue):
|
||||
assert defaultValue.type == type
|
||||
extraConditionForNull = "!(${haveValue}) || "
|
||||
else:
|
||||
extraConditionForNull = ""
|
||||
templateBody = handleNull(templateBody, unionArgumentObj,
|
||||
extraConditionForNull=extraConditionForNull)
|
||||
|
||||
declType = CGGeneric(typeName)
|
||||
holderType = CGGeneric(argumentTypeName) if not isMember else None
|
||||
@ -3121,6 +3131,22 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||
extraConditionForNull = ""
|
||||
templateBody = handleNull(templateBody, declLoc,
|
||||
extraConditionForNull=extraConditionForNull)
|
||||
elif (not type.hasNullableType and defaultValue and
|
||||
isinstance(defaultValue, IDLNullValue)):
|
||||
assert type.hasDictionaryType
|
||||
assert defaultValue.type.isDictionary()
|
||||
if not isMember and typeNeedsRooting(defaultValue.type):
|
||||
ctorArgs = "cx"
|
||||
else:
|
||||
ctorArgs = ""
|
||||
initDictionaryWithNull = CGIfWrapper(
|
||||
CGGeneric("return false;"),
|
||||
('!%s.SetAs%s(%s).Init(cx, JS::NullHandleValue, "Member of %s")'
|
||||
% (declLoc, getUnionMemberName(defaultValue.type),
|
||||
ctorArgs, type)))
|
||||
templateBody = CGIfElseWrapper("!(${haveValue})",
|
||||
initDictionaryWithNull,
|
||||
templateBody)
|
||||
|
||||
templateBody = CGList([constructDecl, templateBody], "\n")
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "XPCWrapper.h"
|
||||
#include "WrapperFactory.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
|
||||
|
@ -2440,7 +2440,10 @@ class IDLValue(IDLObject):
|
||||
# We first check for unions to ensure that even if the union is nullable
|
||||
# we end up with the right flat member type, not the union's type.
|
||||
if type.isUnion():
|
||||
for subtype in type.unroll().memberTypes:
|
||||
# We use the flat member types here, because if we have a nullable
|
||||
# member type, or a nested union, we want the type the value
|
||||
# actually coerces to, not the nullable or nested union type.
|
||||
for subtype in type.unroll().flatMemberTypes:
|
||||
try:
|
||||
coercedValue = self.coerceToType(subtype, location)
|
||||
# Create a new IDLValue to make sure that we have the
|
||||
@ -2513,6 +2516,13 @@ class IDLNullValue(IDLObject):
|
||||
[location])
|
||||
|
||||
nullValue = IDLNullValue(self.location)
|
||||
if type.isUnion() and not type.nullable() and type.hasDictionaryType:
|
||||
# We're actually a default value for the union's dictionary member.
|
||||
# Use its type.
|
||||
for t in type.flatMemberTypes:
|
||||
if t.isDictionary():
|
||||
nullValue.type = t
|
||||
return nullValue
|
||||
nullValue.type = type
|
||||
return nullValue
|
||||
|
||||
|
@ -513,6 +513,9 @@ public:
|
||||
void PassUnion9(JSContext*, const ObjectOrStringOrLongOrBoolean& arg);
|
||||
void PassUnion10(const EventInitOrLong& arg);
|
||||
void PassUnion11(JSContext*, const CustomEventInitOrLong& arg);
|
||||
void PassUnion12(const EventInitOrLong& arg);
|
||||
void PassUnion13(JSContext*, const ObjectOrLongOrNull& arg);
|
||||
void PassUnion14(JSContext*, const ObjectOrLongOrNull& arg);
|
||||
#endif
|
||||
void PassNullableUnion(JSContext*, const Nullable<ObjectOrLong>&);
|
||||
void PassOptionalUnion(JSContext*, const Optional<ObjectOrLong>&);
|
||||
|
@ -453,6 +453,9 @@ interface TestInterface {
|
||||
void passUnion9((object or DOMString or long or boolean) arg);
|
||||
void passUnion10(optional (EventInit or long) arg);
|
||||
void passUnion11(optional (CustomEventInit or long) arg);
|
||||
void passUnion12(optional (EventInit or long) arg = 5);
|
||||
void passUnion13(optional (object or long?) arg = null);
|
||||
void passUnion14(optional (object or long?) arg = 5);
|
||||
#endif
|
||||
void passUnionWithNullable((object? or long) arg);
|
||||
void passNullableUnion((object or long)? arg);
|
||||
|
@ -349,6 +349,9 @@ interface TestExampleInterface {
|
||||
void passUnion9((object or DOMString or long or boolean) arg);
|
||||
void passUnion10(optional (EventInit or long) arg);
|
||||
void passUnion11(optional (CustomEventInit or long) arg);
|
||||
void passUnion12(optional (EventInit or long) arg = 5);
|
||||
void passUnion13(optional (object or long?) arg = null);
|
||||
void passUnion14(optional (object or long?) arg = 5);
|
||||
#endif
|
||||
void passUnionWithNullable((object? or long) arg);
|
||||
void passNullableUnion((object or long)? arg);
|
||||
|
@ -371,6 +371,9 @@ interface TestJSImplInterface {
|
||||
void passUnion9((object or DOMString or long or boolean) arg);
|
||||
void passUnion10(optional (EventInit or long) arg);
|
||||
void passUnion11(optional (CustomEventInit or long) arg);
|
||||
void passUnion12(optional (EventInit or long) arg = 5);
|
||||
void passUnion13(optional (object or long?) arg = null);
|
||||
void passUnion14(optional (object or long?) arg = 5);
|
||||
#endif
|
||||
void passUnionWithNullable((object? or long) arg);
|
||||
// FIXME: Bug 863948 Nullable unions not supported yet
|
||||
|
@ -13,10 +13,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=923010
|
||||
try {
|
||||
var conn = new mozRTCPeerConnection();
|
||||
try {
|
||||
conn.createAnswer(function() {}, null, { "mandatory": { "BOGUS": 5 } } )
|
||||
conn.createAnswer(function() {
|
||||
ok(false, "The call to createAnswer succeeded when it should have thrown");
|
||||
}, function() {
|
||||
ok(false, "The call to createAnswer failed when it should have thrown");
|
||||
}, { "mandatory": { "BOGUS": 5 } } )
|
||||
ok(false, "That call to createAnswer should have thrown");
|
||||
} catch (e) {
|
||||
is(e.lineNumber, 16, "Exception should have been on line 15");
|
||||
is(e.lineNumber, 20, "Exception should have been on line 20");
|
||||
is(e.message,
|
||||
"createAnswer passed invalid constraints - unknown mandatory constraint: BOGUS",
|
||||
"Should have the exception we expect");
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsThread.h"
|
||||
#include "DeviceStorage.h"
|
||||
#include "mozilla/dom/CameraControlBinding.h"
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsMemory.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsThread.h"
|
||||
#include <media/MediaProfiles.h>
|
||||
#include "mozilla/FileUtils.h"
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
#include <camera/Camera.h>
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "GonkCameraControl.h"
|
||||
#include "DOMCameraManager.h"
|
||||
#include "CameraCommon.h"
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsIDocument.h"
|
||||
#include <algorithm>
|
||||
#include "nsContentPermissionHelper.h"
|
||||
|
||||
#include "mozilla/dom/DeviceStorageBinding.h"
|
||||
|
||||
@ -1695,17 +1696,14 @@ nsDOMDeviceStorageCursor::GetStorageType(nsAString & aType)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorageCursor::GetType(nsACString & aType)
|
||||
nsDOMDeviceStorageCursor::GetTypes(nsIArray** aTypes)
|
||||
{
|
||||
return DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType,
|
||||
aType);
|
||||
}
|
||||
nsCString type;
|
||||
nsresult rv =
|
||||
DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorageCursor::GetAccess(nsACString & aAccess)
|
||||
{
|
||||
aAccess = NS_LITERAL_CSTRING("read");
|
||||
return NS_OK;
|
||||
return CreatePermissionArray(type, NS_LITERAL_CSTRING("read"), aTypes);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -2180,8 +2178,10 @@ public:
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsTArray<PermissionRequest> permArray;
|
||||
permArray.AppendElement(PermissionRequest(type, access));
|
||||
child->SendPContentPermissionRequestConstructor(
|
||||
this, type, access, IPC::Principal(mPrincipal));
|
||||
this, permArray, IPC::Principal(mPrincipal));
|
||||
|
||||
Sendprompt();
|
||||
return NS_OK;
|
||||
@ -2195,26 +2195,23 @@ public:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetType(nsACString & aType)
|
||||
NS_IMETHODIMP GetTypes(nsIArray** aTypes)
|
||||
{
|
||||
nsCString type;
|
||||
nsresult rv
|
||||
= DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType,
|
||||
aType);
|
||||
nsresult rv =
|
||||
DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, type);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetAccess(nsACString & aAccess)
|
||||
{
|
||||
nsresult rv = DeviceStorageTypeChecker::GetAccessForRequest(
|
||||
DeviceStorageRequestType(mRequestType), aAccess);
|
||||
nsCString access;
|
||||
rv = DeviceStorageTypeChecker::GetAccessForRequest(
|
||||
DeviceStorageRequestType(mRequestType), access);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
|
||||
return CreatePermissionArray(type, access, aTypes);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
|
||||
@ -3191,8 +3188,10 @@ nsDOMDeviceStorage::EnumerateInternal(const nsAString& aPath,
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
child->SendPContentPermissionRequestConstructor(r, type,
|
||||
NS_LITERAL_CSTRING("read"),
|
||||
nsTArray<PermissionRequest> permArray;
|
||||
permArray.AppendElement(PermissionRequest(type, NS_LITERAL_CSTRING("read")));
|
||||
child->SendPContentPermissionRequestConstructor(r,
|
||||
permArray,
|
||||
IPC::Principal(mPrincipal));
|
||||
|
||||
r->Sendprompt();
|
||||
|
@ -452,7 +452,7 @@ GamepadService::SetWindowHasSeenGamepad(nsGlobalWindow* aWindow,
|
||||
|
||||
if (aHasSeen) {
|
||||
aWindow->SetHasSeenGamepadInput(true);
|
||||
nsCOMPtr<nsISupports> window = nsGlobalWindow::ToSupports(aWindow);
|
||||
nsCOMPtr<nsISupports> window = ToSupports(aWindow);
|
||||
nsRefPtr<Gamepad> gamepad = mGamepads[aIndex]->Clone(window);
|
||||
aWindow->AddGamepad(aIndex, gamepad);
|
||||
} else {
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#include "mozilla/dom/StkCommandEvent.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "nsJSON.h"
|
||||
#include "SimToolKit.h"
|
||||
|
@ -30,13 +30,5 @@
|
||||
"Window unforgeable attribute: document": true,
|
||||
"Window unforgeable attribute: location": true,
|
||||
"Window unforgeable attribute: top": true,
|
||||
"Window replaceable attribute: locationbar": true,
|
||||
"Window replaceable attribute: menubar": true,
|
||||
"Window replaceable attribute: personalbar": true,
|
||||
"Window replaceable attribute: scrollbars": true,
|
||||
"Window replaceable attribute: statusbar": true,
|
||||
"Window replaceable attribute: toolbar": true,
|
||||
"Window replaceable attribute: frames": true,
|
||||
"Window replaceable attribute: length": true,
|
||||
"constructor": true
|
||||
}
|
||||
|
@ -1,4 +1,2 @@
|
||||
{
|
||||
"btoa(null) == \"bnVsbA==\"": true,
|
||||
"atob(null) == \"\u009e\u00e9e\"": true
|
||||
}
|
||||
|
@ -7,15 +7,13 @@
|
||||
interface nsIPrincipal;
|
||||
interface nsIDOMWindow;
|
||||
interface nsIDOMElement;
|
||||
interface nsIArray;
|
||||
|
||||
/**
|
||||
* Interface allows access to a content to request
|
||||
* permission to perform a privileged operation such as
|
||||
* geolocation.
|
||||
* Interface provides the request type and its access.
|
||||
*/
|
||||
[scriptable, uuid(1de67000-2de8-11e2-81c1-0800200c9a66)]
|
||||
interface nsIContentPermissionRequest : nsISupports {
|
||||
|
||||
[scriptable, builtinclass, uuid(384b6cc4-a66b-4bea-98e0-eb10562a9ba4)]
|
||||
interface nsIContentPermissionType : nsISupports {
|
||||
/**
|
||||
* The type of the permission request, such as
|
||||
* "geolocation".
|
||||
@ -27,8 +25,22 @@ interface nsIContentPermissionRequest : nsISupports {
|
||||
* "read".
|
||||
*/
|
||||
readonly attribute ACString access;
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface allows access to a content to request
|
||||
* permission to perform a privileged operation such as
|
||||
* geolocation.
|
||||
*/
|
||||
[scriptable, uuid(69a39d88-d1c4-4ba9-9b19-bafc7a1bb783)]
|
||||
interface nsIContentPermissionRequest : nsISupports {
|
||||
/**
|
||||
* The array will include the request types. Elements of this array are
|
||||
* nsIContentPermissionType object.
|
||||
*/
|
||||
readonly attribute nsIArray types;
|
||||
|
||||
/*
|
||||
* The principal of the permission request.
|
||||
*/
|
||||
readonly attribute nsIPrincipal principal;
|
||||
|
@ -16,6 +16,7 @@ include protocol PIndexedDB;
|
||||
include DOMTypes;
|
||||
include JavaScriptTypes;
|
||||
include URIParams;
|
||||
include PContentPermission;
|
||||
|
||||
include "gfxMatrix.h";
|
||||
include "FrameMetrics.h";
|
||||
@ -209,10 +210,8 @@ parent:
|
||||
* Initiates an asynchronous request for permission for the
|
||||
* provided principal.
|
||||
*
|
||||
* @param aType
|
||||
* The type of permission to request.
|
||||
* @param aAccess
|
||||
* Access type. "read" for example.
|
||||
* @param aRequests
|
||||
* The array of permissions to request.
|
||||
* @param aPrincipal
|
||||
* The principal of the request.
|
||||
*
|
||||
@ -220,7 +219,7 @@ parent:
|
||||
* principals that can live in the content process should
|
||||
* provided.
|
||||
*/
|
||||
PContentPermissionRequest(nsCString aType, nsCString aAccess, Principal principal);
|
||||
PContentPermissionRequest(PermissionRequest[] aRequests, Principal aPrincipal);
|
||||
|
||||
PContentDialog(uint32_t aType, nsCString aName, nsCString aFeatures,
|
||||
int32_t[] aIntParams, nsString[] aStringParams);
|
||||
|
14
dom/ipc/PContentPermission.ipdlh
Normal file
14
dom/ipc/PContentPermission.ipdlh
Normal file
@ -0,0 +1,14 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct PermissionRequest {
|
||||
nsCString type;
|
||||
nsCString access;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user