Merge mozilla-central to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2013-10-28 13:10:47 +01:00
commit 5c5ba13e67
235 changed files with 5344 additions and 2528 deletions

View File

@ -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).

View File

@ -24,7 +24,6 @@
#include "nsINameSpaceManager.h"
#include "nsIPersistentProperties2.h"
#include "nsISelectionController.h"
#include "jsapi.h"
#include "nsIServiceManager.h"
#include "nsITextControlFrame.h"

View File

@ -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);

View File

@ -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]);

View File

@ -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);
},

View File

@ -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);

View File

@ -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;"

View File

@ -1277,7 +1277,7 @@ nsContextMenu.prototype = {
},
playPlugin: function() {
gPluginHandler._showClickToPlayNotification(this.browser, this.target);
gPluginHandler._showClickToPlayNotification(this.browser, this.target, true);
},
hidePlugin: function() {

View File

@ -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]

View File

@ -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();
}

View File

@ -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;

View File

@ -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");
}

View File

@ -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");
}

View File

@ -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();
}

View File

@ -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");

View File

@ -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;

View File

@ -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");

View File

@ -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>

View File

@ -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>

View File

@ -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;

View File

@ -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) {

View File

@ -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;
}

View File

@ -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);

View File

@ -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 {

View File

@ -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();
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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>

View File

@ -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;
}

View File

@ -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

View File

@ -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,

View File

@ -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"));

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 {

View File

@ -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"

View File

@ -84,8 +84,6 @@
#include "nsIBaseWindow.h"
#include "nsIWidget.h"
#include "jsapi.h"
#include "nsNodeInfoManager.h"
#include "nsICategoryManager.h"
#include "nsIDOMDocumentType.h"

View File

@ -79,7 +79,7 @@
#include "nsIBaseWindow.h"
#include "nsIWidget.h"
#include "jsapi.h"
#include "js/GCAPI.h"
#include "nsNodeInfoManager.h"
#include "nsICategoryManager.h"

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -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"

View File

@ -24,7 +24,6 @@
#include "nsIScriptSecurityManager.h"
#include "nsIXPConnect.h"
#include "jsapi.h"
#include "nsITimer.h"

View File

@ -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;
};
}

View 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

View File

@ -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)) {

View File

@ -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)
{}

View File

@ -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;
}

View File

@ -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.

View File

@ -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

View 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

View File

@ -8,8 +8,10 @@ MODULE = 'content'
EXPORTS += [
'ContainerWriter.h',
'EncodedFrameContainer.h',
'MediaEncoder.h',
'TrackEncoder.h',
'TrackMetadataBase.h',
]
SOURCES += [

View File

@ -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;
}
}

View File

@ -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;

View File

@ -33,7 +33,6 @@
#include "nsRuleProcessorData.h"
#include "nsIWeakReference.h"
#include "jsapi.h"
#include "nsIXPConnect.h"
#include "nsDOMCID.h"
#include "nsIDOMScriptObjectFactory.h"

View File

@ -14,7 +14,6 @@
#include "nsXULContentSink.h"
#include "jsapi.h"
#include "jsfriendapi.h"
#include "nsCOMPtr.h"

View File

@ -22,7 +22,6 @@
#include "nsNetUtil.h"
#include "nsAppDirectoryServiceDefs.h"
#include "jsapi.h"
#include "js/Tracer.h"
#include "mozilla/Preferences.h"

View File

@ -33,7 +33,6 @@
#include "mozAutoDocUpdate.h"
#include "nsTextNode.h"
#include "jsapi.h"
#include "pldhash.h"
#include "rdf.h"

View File

@ -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

View File

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

View File

@ -3,3 +3,5 @@
[test_apps_service.xul]
[test_operator_app_install.js]
[test_operator_app_install.xul]
# bug 928262
skip-if = os == "win"

View File

@ -5,7 +5,6 @@
#include "mozilla/dom/DOMException.h"
#include "jsapi.h"
#include "jsprf.h"
#include "js/OldDebugAPI.h"
#include "mozilla/HoldDropJSObjects.h"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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();
}

View File

@ -451,7 +451,10 @@ GetWrapperCache(nsWrapperCache* cache)
}
inline nsWrapperCache*
GetWrapperCache(nsGlobalWindow* not_allowed);
GetWrapperCache(nsGlobalWindow*)
{
return nullptr;
}
inline nsWrapperCache*
GetWrapperCache(void* p)

View File

@ -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')

View File

@ -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")

View File

@ -13,7 +13,6 @@
#include "XPCWrapper.h"
#include "WrapperFactory.h"
#include "nsDOMClassInfo.h"
#include "nsGlobalWindow.h"
#include "nsWrapperCacheInlines.h"
#include "mozilla/dom/BindingUtils.h"

View File

@ -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

View File

@ -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>&);

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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");

View File

@ -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"

View File

@ -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"

View File

@ -16,7 +16,6 @@
#include <camera/Camera.h>
#include "jsapi.h"
#include "GonkCameraControl.h"
#include "DOMCameraManager.h"
#include "CameraCommon.h"

View File

@ -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();

View File

@ -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 {

View File

@ -4,7 +4,6 @@
#include "mozilla/dom/StkCommandEvent.h"
#include "jsapi.h"
#include "jsfriendapi.h"
#include "nsJSON.h"
#include "SimToolKit.h"

View File

@ -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
}

View File

@ -1,4 +1,2 @@
{
"btoa(null) == \"bnVsbA==\"": true,
"atob(null) == \"\u009e\u00e9e\"": true
}

View File

@ -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;

View File

@ -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);

View 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