mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
commit
e016c33f6e
@ -47,11 +47,6 @@ LOCAL_INCLUDES += [
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
# The midl generated code include Windows headers which defines min and max
|
||||
# macros which conflicts with std::min/max. Suppress the macros:
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
DEFINES['NOMINMAX'] = True
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
@ -19,10 +19,6 @@ LOCAL_INCLUDES += [
|
||||
'/accessible/xul',
|
||||
]
|
||||
|
||||
# The midl generated code include Windows headers which defines min and max
|
||||
# macros which conflicts with std::min/max. Suppress the macros:
|
||||
DEFINES['NOMINMAX'] = True
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
@ -19,9 +19,4 @@ LOCAL_INCLUDES += [
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
# The midl generated code include Windows headers which defines min and max
|
||||
# macros which conflicts with std::min/max. Suppress the macros:
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
DEFINES['NOMINMAX'] = True
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
@ -7,13 +7,15 @@
|
||||
%htmlDTD;
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%brandDTD;
|
||||
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
|
||||
%globalDTD;
|
||||
<!ENTITY % aboutAccountsDTD SYSTEM "chrome://browser/locale/aboutAccounts.dtd">
|
||||
%aboutAccountsDTD;
|
||||
<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
|
||||
%syncBrandDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" dir="&locale.dir;">
|
||||
<head>
|
||||
<title>&syncBrand.fullName.label;</title>
|
||||
<meta name="viewport" content="width=device-width"/>
|
||||
|
@ -5885,20 +5885,24 @@
|
||||
<handlers>
|
||||
<handler event="mouseover"><![CDATA[
|
||||
let anonid = event.originalTarget.getAttribute("anonid");
|
||||
let iconVisible = this.hasAttribute("soundplaying") ||
|
||||
this.hasAttribute("muted");
|
||||
if (anonid == "close-button")
|
||||
this.mOverCloseButton = true;
|
||||
else if ((anonid == "soundplaying-icon") ||
|
||||
((anonid == "overlay-icon") && this.hasAttribute("soundplaying")))
|
||||
((anonid == "overlay-icon") && iconVisible))
|
||||
this._overPlayingIcon = true;
|
||||
|
||||
this._mouseenter();
|
||||
]]></handler>
|
||||
<handler event="mouseout"><![CDATA[
|
||||
let anonid = event.originalTarget.getAttribute("anonid");
|
||||
let iconVisible = this.hasAttribute("soundplaying") ||
|
||||
this.hasAttribute("muted");
|
||||
if (anonid == "close-button")
|
||||
this.mOverCloseButton = false;
|
||||
else if ((anonid == "soundplaying-icon") ||
|
||||
((anonid == "overlay-icon") && this.hasAttribute("soundplaying")))
|
||||
((anonid == "overlay-icon") && iconVisible))
|
||||
this._overPlayingIcon = false;
|
||||
|
||||
this._mouseleave();
|
||||
@ -5928,8 +5932,10 @@
|
||||
}
|
||||
|
||||
let anonid = event.originalTarget.getAttribute("anonid");
|
||||
let iconVisible = this.hasAttribute("soundplaying") ||
|
||||
this.hasAttribute("muted");
|
||||
if ((anonid == "soundplaying-icon") ||
|
||||
((anonid == "overlay-icon") && this.hasAttribute("soundplaying"))) {
|
||||
((anonid == "overlay-icon") && iconVisible)) {
|
||||
this._toggleMuteAudio();
|
||||
}
|
||||
]]>
|
||||
|
@ -473,7 +473,6 @@ skip-if = buildapp == 'mulet'
|
||||
[browser_zbug569342.js]
|
||||
skip-if = e10s # Bug 1094240 - has findbar-related failures
|
||||
[browser_registerProtocolHandler_notification.js]
|
||||
skip-if = e10s # Bug 940206 - nsIWebContentHandlerRegistrar::registerProtocolHandler doesn't work in e10s
|
||||
[browser_no_mcb_on_http_site.js]
|
||||
[browser_bug1104165-switchtab-decodeuri.js]
|
||||
[browser_bug1003461-switchtab-override.js]
|
||||
|
@ -87,11 +87,23 @@ function* test_playing_icon_on_tab(tab, browser, isPinned) {
|
||||
|
||||
yield test_tooltip(icon, "This tab is playing audio");
|
||||
|
||||
yield test_mute_tab(tab, icon, true);
|
||||
|
||||
yield ContentTask.spawn(browser, {}, function* () {
|
||||
let audio = content.document.querySelector("audio");
|
||||
audio.pause();
|
||||
});
|
||||
yield wait_for_tab_playing_event(tab, false);
|
||||
|
||||
ok(tab.hasAttribute("muted") &&
|
||||
!tab.hasAttribute("soundplaying"), "Tab should still be muted but not playing");
|
||||
|
||||
yield test_tooltip(icon, "This tab has been muted");
|
||||
|
||||
yield test_mute_tab(tab, icon, false);
|
||||
|
||||
ok(!tab.hasAttribute("muted") &&
|
||||
!tab.hasAttribute("soundplaying"), "Tab should not be be muted or playing");
|
||||
}
|
||||
|
||||
function* test_on_browser(browser) {
|
||||
|
@ -3,6 +3,7 @@
|
||||
* 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/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
@ -132,6 +133,83 @@ ServiceInfo.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
const Utils = {
|
||||
makeURI(aURL, aOriginCharset, aBaseURI) {
|
||||
return Services.io.newURI(aURL, aOriginCharset, aBaseURI);
|
||||
},
|
||||
|
||||
checkAndGetURI(aURIString, aContentWindow) {
|
||||
try {
|
||||
let baseURI = aContentWindow.document.baseURIObject;
|
||||
var uri = this.makeURI(aURIString, null, baseURI);
|
||||
} catch (ex) {
|
||||
throw NS_ERROR_DOM_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
// For security reasons we reject non-http(s) urls (see bug 354316),
|
||||
// we may need to revise this once we support more content types
|
||||
// XXX this should be a "security exception" according to spec, but that
|
||||
// isn't defined yet.
|
||||
if (uri.scheme != "http" && uri.scheme != "https")
|
||||
throw("Permission denied to add " + uri.spec + " as a content or protocol handler");
|
||||
|
||||
// We also reject handlers registered from a different host (see bug 402287)
|
||||
// The pref allows us to test the feature
|
||||
var pb = Services.prefs;
|
||||
if ((!pb.prefHasUserValue(PREF_ALLOW_DIFFERENT_HOST) ||
|
||||
!pb.getBoolPref(PREF_ALLOW_DIFFERENT_HOST)) &&
|
||||
aContentWindow.location.hostname != uri.host)
|
||||
throw("Permission denied to add " + uri.spec + " as a content or protocol handler");
|
||||
|
||||
// If the uri doesn't contain '%s', it won't be a good handler
|
||||
if (uri.spec.indexOf("%s") < 0)
|
||||
throw NS_ERROR_DOM_SYNTAX_ERR;
|
||||
|
||||
return uri;
|
||||
},
|
||||
|
||||
// NB: Throws if aProtocol is not allowed.
|
||||
checkProtocolHandlerAllowed(aProtocol, aURIString) {
|
||||
// First, check to make sure this isn't already handled internally (we don't
|
||||
// want to let them take over, say "chrome").
|
||||
var handler = Services.io.getProtocolHandler(aProtocol);
|
||||
if (!(handler instanceof Ci.nsIExternalProtocolHandler)) {
|
||||
// This is handled internally, so we don't want them to register
|
||||
// XXX this should be a "security exception" according to spec, but that
|
||||
// isn't defined yet.
|
||||
throw(`Permission denied to add ${aURIString} as a protocol handler`);
|
||||
}
|
||||
|
||||
// check if it is in the black list
|
||||
var pb = Services.prefs;
|
||||
var allowed;
|
||||
try {
|
||||
allowed = pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "." + aProtocol);
|
||||
}
|
||||
catch (e) {
|
||||
allowed = pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "-default");
|
||||
}
|
||||
if (!allowed) {
|
||||
// XXX this should be a "security exception" according to spec
|
||||
throw(`Not allowed to register a protocol handler for ${aProtocol}`);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Mappings from known feed types to our internal content type.
|
||||
*/
|
||||
_mappings: {
|
||||
"application/rss+xml": TYPE_MAYBE_FEED,
|
||||
"application/atom+xml": TYPE_MAYBE_FEED,
|
||||
},
|
||||
|
||||
resolveContentType(aContentType) {
|
||||
if (aContentType in this._mappings)
|
||||
return this._mappings[aContentType];
|
||||
return aContentType;
|
||||
}
|
||||
};
|
||||
|
||||
function WebContentConverterRegistrar() {
|
||||
this._contentTypes = { };
|
||||
this._autoHandleContentTypes = { };
|
||||
@ -139,9 +217,7 @@ function WebContentConverterRegistrar() {
|
||||
|
||||
WebContentConverterRegistrar.prototype = {
|
||||
get stringBundle() {
|
||||
var sb = Cc["@mozilla.org/intl/stringbundle;1"].
|
||||
getService(Ci.nsIStringBundleService).
|
||||
createBundle(STRING_BUNDLE_URI);
|
||||
var sb = Services.strings.createBundle(STRING_BUNDLE_URI);
|
||||
delete WebContentConverterRegistrar.prototype.stringBundle;
|
||||
return WebContentConverterRegistrar.prototype.stringBundle = sb;
|
||||
},
|
||||
@ -159,7 +235,7 @@ WebContentConverterRegistrar.prototype = {
|
||||
*/
|
||||
getAutoHandler:
|
||||
function WCCR_getAutoHandler(contentType) {
|
||||
contentType = this._resolveContentType(contentType);
|
||||
contentType = Utils.resolveContentType(contentType);
|
||||
if (contentType in this._autoHandleContentTypes)
|
||||
return this._autoHandleContentTypes[contentType];
|
||||
return null;
|
||||
@ -172,19 +248,17 @@ WebContentConverterRegistrar.prototype = {
|
||||
function WCCR_setAutoHandler(contentType, handler) {
|
||||
if (handler && !this._typeIsRegistered(contentType, handler.uri))
|
||||
throw Cr.NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
contentType = this._resolveContentType(contentType);
|
||||
|
||||
contentType = Utils.resolveContentType(contentType);
|
||||
this._setAutoHandler(contentType, handler);
|
||||
|
||||
var ps =
|
||||
Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService);
|
||||
|
||||
var ps = Services.prefs;
|
||||
var autoBranch = ps.getBranch(PREF_CONTENTHANDLERS_AUTO);
|
||||
if (handler)
|
||||
autoBranch.setCharPref(contentType, handler.uri);
|
||||
else if (autoBranch.prefHasUserValue(contentType))
|
||||
autoBranch.clearUserPref(contentType);
|
||||
|
||||
|
||||
ps.savePrefFile(null);
|
||||
},
|
||||
|
||||
@ -218,7 +292,7 @@ WebContentConverterRegistrar.prototype = {
|
||||
loadPreferredHandler:
|
||||
function WCCR_loadPreferredHandler(request) {
|
||||
var channel = request.QueryInterface(Ci.nsIChannel);
|
||||
var contentType = this._resolveContentType(channel.contentType);
|
||||
var contentType = Utils.resolveContentType(channel.contentType);
|
||||
var handler = this.getAutoHandler(contentType);
|
||||
if (handler) {
|
||||
request.cancel(Cr.NS_ERROR_FAILURE);
|
||||
@ -268,15 +342,7 @@ WebContentConverterRegistrar.prototype = {
|
||||
this._contentTypes[contentType].filter(notURI);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
_mappings: {
|
||||
"application/rss+xml": TYPE_MAYBE_FEED,
|
||||
"application/atom+xml": TYPE_MAYBE_FEED,
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* These are types for which there is a separate content converter aside
|
||||
* from our built in generic one. We should not automatically register
|
||||
@ -285,57 +351,6 @@ WebContentConverterRegistrar.prototype = {
|
||||
_blockedTypes: {
|
||||
"application/vnd.mozilla.maybe.feed": true,
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines the "internal" content type based on the _mappings.
|
||||
* @param contentType
|
||||
* @returns The resolved contentType value.
|
||||
*/
|
||||
_resolveContentType:
|
||||
function WCCR__resolveContentType(contentType) {
|
||||
if (contentType in this._mappings)
|
||||
return this._mappings[contentType];
|
||||
return contentType;
|
||||
},
|
||||
|
||||
_makeURI: function(aURL, aOriginCharset, aBaseURI) {
|
||||
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
return ioService.newURI(aURL, aOriginCharset, aBaseURI);
|
||||
},
|
||||
|
||||
_checkAndGetURI:
|
||||
function WCCR_checkAndGetURI(aURIString, aContentWindow)
|
||||
{
|
||||
try {
|
||||
let baseURI = aContentWindow.document.baseURIObject;
|
||||
var uri = this._makeURI(aURIString, null, baseURI);
|
||||
} catch (ex) {
|
||||
// not supposed to throw according to spec
|
||||
return;
|
||||
}
|
||||
|
||||
// For security reasons we reject non-http(s) urls (see bug 354316),
|
||||
// we may need to revise this once we support more content types
|
||||
// XXX this should be a "security exception" according to spec, but that
|
||||
// isn't defined yet.
|
||||
if (uri.scheme != "http" && uri.scheme != "https")
|
||||
throw("Permission denied to add " + uri.spec + " as a content or protocol handler");
|
||||
|
||||
// We also reject handlers registered from a different host (see bug 402287)
|
||||
// The pref allows us to test the feature
|
||||
var pb = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
if ((!pb.prefHasUserValue(PREF_ALLOW_DIFFERENT_HOST) ||
|
||||
!pb.getBoolPref(PREF_ALLOW_DIFFERENT_HOST)) &&
|
||||
aContentWindow.location.hostname != uri.host)
|
||||
throw("Permission denied to add " + uri.spec + " as a content or protocol handler");
|
||||
|
||||
// If the uri doesn't contain '%s', it won't be a good handler
|
||||
if (uri.spec.indexOf("%s") < 0)
|
||||
throw NS_ERROR_DOM_SYNTAX_ERR;
|
||||
|
||||
return uri;
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines if a web handler is already registered.
|
||||
@ -366,52 +381,41 @@ WebContentConverterRegistrar.prototype = {
|
||||
* See nsIWebContentHandlerRegistrar
|
||||
*/
|
||||
registerProtocolHandler:
|
||||
function WCCR_registerProtocolHandler(aProtocol, aURIString, aTitle, aContentWindow) {
|
||||
function WCCR_registerProtocolHandler(aProtocol, aURIString, aTitle, aBrowserOrWindow) {
|
||||
LOG("registerProtocolHandler(" + aProtocol + "," + aURIString + "," + aTitle + ")");
|
||||
|
||||
var uri = this._checkAndGetURI(aURIString, aContentWindow);
|
||||
var haveWindow = (aBrowserOrWindow instanceof Ci.nsIDOMWindow);
|
||||
var uri;
|
||||
if (haveWindow) {
|
||||
uri = Utils.checkAndGetURI(aURIString, aBrowserOrWindow);
|
||||
} else {
|
||||
// aURIString must not be a relative URI.
|
||||
uri = Utils.makeURI(aURIString, null);
|
||||
}
|
||||
|
||||
// If the protocol handler is already registered, just return early.
|
||||
if (this._protocolHandlerRegistered(aProtocol, uri.spec)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var browserWindow = this._getBrowserWindowForContentWindow(aContentWindow);
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(browserWindow)) {
|
||||
var browser;
|
||||
if (haveWindow) {
|
||||
let browserWindow =
|
||||
this._getBrowserWindowForContentWindow(aBrowserOrWindow);
|
||||
browser = this._getBrowserForContentWindow(browserWindow,
|
||||
aBrowserOrWindow);
|
||||
} else {
|
||||
browser = aBrowserOrWindow;
|
||||
}
|
||||
if (PrivateBrowsingUtils.isBrowserPrivate(browser)) {
|
||||
// Inside the private browsing mode, we don't want to alert the user to save
|
||||
// a protocol handler. We log it to the error console so that web developers
|
||||
// would have some way to tell what's going wrong.
|
||||
Cc["@mozilla.org/consoleservice;1"].
|
||||
getService(Ci.nsIConsoleService).
|
||||
Services.console.
|
||||
logStringMessage("Web page denied access to register a protocol handler inside private browsing mode");
|
||||
return;
|
||||
}
|
||||
|
||||
// First, check to make sure this isn't already handled internally (we don't
|
||||
// want to let them take over, say "chrome").
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
var handler = ios.getProtocolHandler(aProtocol);
|
||||
if (!(handler instanceof Ci.nsIExternalProtocolHandler)) {
|
||||
// This is handled internally, so we don't want them to register
|
||||
// XXX this should be a "security exception" according to spec, but that
|
||||
// isn't defined yet.
|
||||
throw("Permission denied to add " + aURIString + "as a protocol handler");
|
||||
}
|
||||
|
||||
// check if it is in the black list
|
||||
var pb = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
var allowed;
|
||||
try {
|
||||
allowed = pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "." + aProtocol);
|
||||
}
|
||||
catch (e) {
|
||||
allowed = pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "-default");
|
||||
}
|
||||
if (!allowed) {
|
||||
// XXX this should be a "security exception" according to spec
|
||||
throw("Not allowed to register a protocol handler for " + aProtocol);
|
||||
}
|
||||
Utils.checkProtocolHandlerAllowed(aProtocol, aURIString);
|
||||
|
||||
// Now Ask the user and provide the proper callback
|
||||
var message = this._getFormattedString("addProtocolHandler",
|
||||
@ -451,8 +455,7 @@ WebContentConverterRegistrar.prototype = {
|
||||
hs.store(handlerInfo);
|
||||
}
|
||||
};
|
||||
var browserElement = this._getBrowserForContentWindow(browserWindow, aContentWindow);
|
||||
var notificationBox = browserWindow.gBrowser.getNotificationBox(browserElement);
|
||||
var notificationBox = browser.getTabBrowser().getNotificationBox(browser);
|
||||
notificationBox.appendNotification(message,
|
||||
notificationValue,
|
||||
notificationIcon,
|
||||
@ -465,23 +468,34 @@ WebContentConverterRegistrar.prototype = {
|
||||
* If a DOM window is provided, then the request came from content, so we
|
||||
* prompt the user to confirm the registration.
|
||||
*/
|
||||
registerContentHandler:
|
||||
function WCCR_registerContentHandler(aContentType, aURIString, aTitle, aContentWindow) {
|
||||
registerContentHandler:
|
||||
function WCCR_registerContentHandler(aContentType, aURIString, aTitle, aWindowOrBrowser) {
|
||||
LOG("registerContentHandler(" + aContentType + "," + aURIString + "," + aTitle + ")");
|
||||
|
||||
// We only support feed types at present.
|
||||
// XXX this should be a "security exception" according to spec, but that
|
||||
// isn't defined yet.
|
||||
var contentType = this._resolveContentType(aContentType);
|
||||
var contentType = Utils.resolveContentType(aContentType);
|
||||
if (contentType != TYPE_MAYBE_FEED)
|
||||
return;
|
||||
|
||||
if (aContentWindow) {
|
||||
var uri = this._checkAndGetURI(aURIString, aContentWindow);
|
||||
|
||||
var browserWindow = this._getBrowserWindowForContentWindow(aContentWindow);
|
||||
var browserElement = this._getBrowserForContentWindow(browserWindow, aContentWindow);
|
||||
var notificationBox = browserWindow.gBrowser.getNotificationBox(browserElement);
|
||||
if (aWindowOrBrowser) {
|
||||
var haveWindow = (aWindowOrBrowser instanceof Ci.nsIDOMWindow);
|
||||
var uri;
|
||||
var notificationBox;
|
||||
if (haveWindow) {
|
||||
uri = Utils.checkAndGetURI(aURIString, aWindowOrBrowser);
|
||||
|
||||
var browserWindow = this._getBrowserWindowForContentWindow(aWindowOrBrowser);
|
||||
var browserElement = this._getBrowserForContentWindow(browserWindow, aWindowOrBrowser);
|
||||
notificationBox = browserElement.getTabBrowser().getNotificationBox(browserElement);
|
||||
} else {
|
||||
// uri was vetted in the content process.
|
||||
uri = Utils.makeURI(aURIString, null);
|
||||
notificationBox = aWindowOrBrowser.getTabBrowser()
|
||||
.getNotificationBox(aWindowOrBrowser);
|
||||
}
|
||||
|
||||
this._appendFeedReaderNotification(uri, aTitle, notificationBox);
|
||||
}
|
||||
else
|
||||
@ -612,9 +626,7 @@ WebContentConverterRegistrar.prototype = {
|
||||
*/
|
||||
_saveContentHandlerToPrefs:
|
||||
function WCCR__saveContentHandlerToPrefs(contentType, uri, title) {
|
||||
var ps =
|
||||
Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService);
|
||||
var ps = Services.prefs;
|
||||
var i = 0;
|
||||
var typeBranch = null;
|
||||
while (true) {
|
||||
@ -694,8 +706,7 @@ WebContentConverterRegistrar.prototype = {
|
||||
if (contentType == TYPE_MAYBE_FEED) {
|
||||
// Make the new handler the last-selected reader in the preview page
|
||||
// and make sure the preview page is shown the next time a feed is visited
|
||||
var pb = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).getBranch(null);
|
||||
var pb = Services.prefs.getBranch(null);
|
||||
pb.setCharPref(PREF_SELECTED_READER, "web");
|
||||
|
||||
var supportsString =
|
||||
@ -800,9 +811,7 @@ WebContentConverterRegistrar.prototype = {
|
||||
* preferences.
|
||||
*/
|
||||
_init: function WCCR__init() {
|
||||
var ps =
|
||||
Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService);
|
||||
var ps = Services.prefs;
|
||||
|
||||
var kids = ps.getBranch(PREF_CONTENTHANDLERS_BRANCH)
|
||||
.getChildList("");
|
||||
@ -850,9 +859,7 @@ WebContentConverterRegistrar.prototype = {
|
||||
* See nsIObserver
|
||||
*/
|
||||
observe: function WCCR_observe(subject, topic, data) {
|
||||
var os =
|
||||
Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
var os = Services.obs;
|
||||
switch (topic) {
|
||||
case "app-startup":
|
||||
os.addObserver(this, "browser-ui-startup-complete", false);
|
||||
@ -890,4 +897,71 @@ WebContentConverterRegistrar.prototype = {
|
||||
}]
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WebContentConverterRegistrar]);
|
||||
function WebContentConverterRegistrarContent() {
|
||||
}
|
||||
|
||||
WebContentConverterRegistrarContent.prototype = {
|
||||
/**
|
||||
* See nsIWebContentHandlerRegistrar
|
||||
*/
|
||||
registerContentHandler(aContentType, aURIString, aTitle, aBrowserOrWindow) {
|
||||
// aBrowserOrWindow must be a window.
|
||||
let messageManager = aBrowserOrWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsITabChild)
|
||||
.messageManager;
|
||||
|
||||
let uri = Utils.checkAndGetURI(aURIString, aBrowserOrWindow);
|
||||
if (Utils.resolveContentType(aContentType) != TYPE_MAYBE_FEED) {
|
||||
return;
|
||||
}
|
||||
|
||||
messageManager.sendAsyncMessage("WCCR:registerContentHandler",
|
||||
{ contentType: aContentType,
|
||||
uri: uri.spec,
|
||||
title: aTitle });
|
||||
},
|
||||
|
||||
registerProtocolHandler(aProtocol, aURIString, aTitle, aBrowserOrWindow) {
|
||||
// aBrowserOrWindow must be a window.
|
||||
let messageManager = aBrowserOrWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsITabChild)
|
||||
.messageManager;
|
||||
|
||||
let uri = Utils.checkAndGetURI(aURIString, aBrowserOrWindow);
|
||||
Utils.checkProtocolHandlerAllowed(aProtocol, aURIString);
|
||||
|
||||
messageManager.sendAsyncMessage("WCCR:registerProtocolHandler",
|
||||
{ protocol: aProtocol,
|
||||
uri: uri.spec,
|
||||
title: aTitle });
|
||||
},
|
||||
|
||||
/**
|
||||
* See nsIFactory
|
||||
*/
|
||||
createInstance: function WCCR_createInstance(outer, iid) {
|
||||
if (outer != null)
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
return this.QueryInterface(iid);
|
||||
},
|
||||
|
||||
classID: WCCR_CLASSID,
|
||||
|
||||
/**
|
||||
* See nsISupports
|
||||
*/
|
||||
QueryInterface: XPCOMUtils.generateQI(
|
||||
[Ci.nsIWebContentHandlerRegistrar,
|
||||
Ci.nsIFactory])
|
||||
};
|
||||
|
||||
this.NSGetFactory =
|
||||
(Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_CONTENT) ?
|
||||
XPCOMUtils.generateNSGetFactory([WebContentConverterRegistrarContent]) :
|
||||
XPCOMUtils.generateNSGetFactory([WebContentConverterRegistrar]);
|
||||
|
@ -1,5 +1,5 @@
|
||||
[DEFAULT]
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || e10s
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g'
|
||||
support-files =
|
||||
bug368464-data.xml
|
||||
bug408328-data.xml
|
||||
@ -10,6 +10,9 @@ support-files =
|
||||
valid-unsniffable-feed.xml
|
||||
|
||||
[test_bug436801.html]
|
||||
skip-if = e10s
|
||||
[test_bug494328.html]
|
||||
skip-if = e10s
|
||||
[test_bug589543.html]
|
||||
skip-if = e10s
|
||||
[test_registerHandler.html]
|
||||
|
@ -39,45 +39,45 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=402788
|
||||
ok(navigator.registerContentHandler, "navigator.registerContentHandler should be defined");
|
||||
|
||||
// testing a generic case
|
||||
is(true, testRegisterHandler(true, "foo", "http://mochi.test:8888/%s", "Foo handler"), "registering a foo protocol handler should work");
|
||||
is(true, testRegisterHandler(false, "application/rss+xml", "http://mochi.test:8888/%s", "Foo handler"), "registering a foo content handler should work");
|
||||
is(testRegisterHandler(true, "foo", "http://mochi.test:8888/%s", "Foo handler"), true, "registering a foo protocol handler should work");
|
||||
is(testRegisterHandler(false, "application/rss+xml", "http://mochi.test:8888/%s", "Foo handler"), true, "registering a foo content handler should work");
|
||||
|
||||
// testing with wrong uris
|
||||
is(false, testRegisterHandler(true, "foo", "http://mochi.test:8888/", "Foo handler"), "a protocol handler uri should contain %s");
|
||||
is(false, testRegisterHandler(false, "application/rss+xml", "http://mochi.test:8888/", "Foo handler"), "a content handler uri should contain %s");
|
||||
is(testRegisterHandler(true, "foo", "http://mochi.test:8888/", "Foo handler"), false, "a protocol handler uri should contain %s");
|
||||
is(testRegisterHandler(false, "application/rss+xml", "http://mochi.test:8888/", "Foo handler"), false, "a content handler uri should contain %s");
|
||||
|
||||
// the spec explicitly allows relative urls to be passed
|
||||
is(true, testRegisterHandler(true, "foo", "foo/%s", "Foo handler"), "a protocol handler uri should be valid");
|
||||
is(true, testRegisterHandler(false, "application/rss+xml", "foo/%s", "Foo handler"), "a content handler uri should be valid");
|
||||
is(testRegisterHandler(true, "foo", "foo/%s", "Foo handler"), true, "a protocol handler uri should be valid");
|
||||
is(testRegisterHandler(false, "application/rss+xml", "foo/%s", "Foo handler"), true, "a content handler uri should be valid");
|
||||
|
||||
// we should only accept to register when the handler has the same host as the current page (bug 402287)
|
||||
is(false, testRegisterHandler(true, "foo", "http://remotehost:8888/%s", "Foo handler"), "registering a foo protocol handler with a different host should not work");
|
||||
is(false, testRegisterHandler(false, "application/rss+xml", "http://remotehost:8888/%s", "Foo handler"), "registering a foo content handler with a different host should not work");
|
||||
is(testRegisterHandler(true, "foo", "http://remotehost:8888/%s", "Foo handler"), false, "registering a foo protocol handler with a different host should not work");
|
||||
is(testRegisterHandler(false, "application/rss+xml", "http://remotehost:8888/%s", "Foo handler"), false, "registering a foo content handler with a different host should not work");
|
||||
|
||||
// restriction to http(s) for the uri of the handler (bug 401343)
|
||||
// https should work (http already tested in the generic case)
|
||||
is(true, testRegisterHandler(true, "foo", "https://mochi.test:8888/%s", "Foo handler"), "registering a foo protocol handler with https scheme should work");
|
||||
is(true, testRegisterHandler(false, "application/rss+xml", "https://mochi.test:8888/%s", "Foo handler"), "registering a foo content handler with https scheme should work");
|
||||
is(testRegisterHandler(true, "foo", "https://mochi.test:8888/%s", "Foo handler"), true, "registering a foo protocol handler with https scheme should work");
|
||||
is(testRegisterHandler(false, "application/rss+xml", "https://mochi.test:8888/%s", "Foo handler"), true, "registering a foo content handler with https scheme should work");
|
||||
// ftp should not work
|
||||
is(false, testRegisterHandler(true, "foo", "ftp://mochi.test:8888/%s", "Foo handler"), "registering a foo protocol handler with ftp scheme should not work");
|
||||
is(false, testRegisterHandler(false, "application/rss+xml", "ftp://mochi.test:8888/%s", "Foo handler"), "registering a foo content handler with ftp scheme should not work");
|
||||
is(testRegisterHandler(true, "foo", "ftp://mochi.test:8888/%s", "Foo handler"), false, "registering a foo protocol handler with ftp scheme should not work");
|
||||
is(testRegisterHandler(false, "application/rss+xml", "ftp://mochi.test:8888/%s", "Foo handler"), false, "registering a foo content handler with ftp scheme should not work");
|
||||
// chrome should not work
|
||||
is(false, testRegisterHandler(true, "foo", "chrome://mochi.test:8888/%s", "Foo handler"), "registering a foo protocol handler with chrome scheme should not work");
|
||||
is(false, testRegisterHandler(false, "application/rss+xml", "chrome://mochi.test:8888/%s", "Foo handler"), "registering a foo content handler with chrome scheme should not work");
|
||||
is(testRegisterHandler(true, "foo", "chrome://mochi.test:8888/%s", "Foo handler"), false, "registering a foo protocol handler with chrome scheme should not work");
|
||||
is(testRegisterHandler(false, "application/rss+xml", "chrome://mochi.test:8888/%s", "Foo handler"), false, "registering a foo content handler with chrome scheme should not work");
|
||||
// foo should not work
|
||||
is(false, testRegisterHandler(true, "foo", "foo://mochi.test:8888/%s", "Foo handler"), "registering a foo protocol handler with foo scheme should not work");
|
||||
is(false, testRegisterHandler(false, "application/rss+xml", "foo://mochi.test:8888/%s", "Foo handler"), "registering a foo content handler with foo scheme should not work");
|
||||
is(testRegisterHandler(true, "foo", "foo://mochi.test:8888/%s", "Foo handler"), false, "registering a foo protocol handler with foo scheme should not work");
|
||||
is(testRegisterHandler(false, "application/rss+xml", "foo://mochi.test:8888/%s", "Foo handler"), false, "registering a foo content handler with foo scheme should not work");
|
||||
|
||||
// for security reasons, protocol handlers should never be registered for some schemes (chrome, vbscript, ...) (bug 402788)
|
||||
is(false, testRegisterHandler(true, "chrome", "http://mochi.test:8888/%s", "chrome handler"), "registering a chrome protocol handler should not work");
|
||||
is(false, testRegisterHandler(true, "vbscript", "http://mochi.test:8888/%s", "vbscript handler"), "registering a vbscript protocol handler should not work");
|
||||
is(false, testRegisterHandler(true, "javascript", "http://mochi.test:8888/%s", "javascript handler"), "registering a javascript protocol handler should not work");
|
||||
is(false, testRegisterHandler(true, "moz-icon", "http://mochi.test:8888/%s", "moz-icon handler"), "registering a moz-icon protocol handler should not work");
|
||||
is(testRegisterHandler(true, "chrome", "http://mochi.test:8888/%s", "chrome handler"), false, "registering a chrome protocol handler should not work");
|
||||
is(testRegisterHandler(true, "vbscript", "http://mochi.test:8888/%s", "vbscript handler"), false, "registering a vbscript protocol handler should not work");
|
||||
is(testRegisterHandler(true, "javascript", "http://mochi.test:8888/%s", "javascript handler"), false, "registering a javascript protocol handler should not work");
|
||||
is(testRegisterHandler(true, "moz-icon", "http://mochi.test:8888/%s", "moz-icon handler"), false, "registering a moz-icon protocol handler should not work");
|
||||
|
||||
// for security reasons, content handlers should never be registered for some types (html, ...)
|
||||
is(true, testRegisterHandler(false, "application/rss+xml", "http://mochi.test:8888/%s", "Foo handler"), "registering rss content handlers should work");
|
||||
is(true, testRegisterHandler(false, "application/atom+xml", "http://mochi.test:8888/%s", "Foo handler"), "registering atom content handlers should work");
|
||||
todo(false, testRegisterHandler(false, "text/html", "http://mochi.test:8888/%s", "Foo handler"), "registering html content handlers should not work"); // bug 403798
|
||||
is(testRegisterHandler(false, "application/rss+xml", "http://mochi.test:8888/%s", "Foo handler"), true, "registering rss content handlers should work");
|
||||
is(testRegisterHandler(false, "application/atom+xml", "http://mochi.test:8888/%s", "Foo handler"), true, "registering atom content handlers should work");
|
||||
todo_is(testRegisterHandler(false, "text/html", "http://mochi.test:8888/%s", "Foo handler"), false, "registering html content handlers should not work"); // bug 403798
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
@ -94,6 +94,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "RemotePrompt",
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ContentPrefServiceParent",
|
||||
"resource://gre/modules/ContentPrefServiceParent.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Feeds",
|
||||
"resource:///modules/Feeds.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SelfSupportBackend",
|
||||
"resource:///modules/SelfSupportBackend.jsm");
|
||||
|
||||
@ -762,6 +765,7 @@ BrowserGlue.prototype = {
|
||||
|
||||
ContentClick.init();
|
||||
RemotePrompt.init();
|
||||
Feeds.init();
|
||||
ContentPrefServiceParent.init();
|
||||
|
||||
LoginManagerParent.init();
|
||||
|
@ -38,7 +38,6 @@ support-files =
|
||||
[browser_privatebrowsing_placestitle.js]
|
||||
[browser_privatebrowsing_popupblocker.js]
|
||||
[browser_privatebrowsing_protocolhandler.js]
|
||||
skip-if = e10s # Bug 940206 - nsIWebContentHandlerRegistrar::registerProtocolHandler doesn't work in e10s
|
||||
[browser_privatebrowsing_sidebar.js]
|
||||
[browser_privatebrowsing_theming.js]
|
||||
[browser_privatebrowsing_ui.js]
|
||||
|
@ -12,9 +12,35 @@ Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
|
||||
"resource://gre/modules/BrowserUtils.jsm");
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const { interfaces: Ci, classes: Cc } = Components;
|
||||
|
||||
this.Feeds = {
|
||||
init() {
|
||||
let mm = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
|
||||
mm.addMessageListener("WCCR:registerProtocolHandler", this);
|
||||
},
|
||||
|
||||
receiveMessage(aMessage) {
|
||||
switch (aMessage.name) {
|
||||
case "WCCR:registerProtocolHandler": {
|
||||
let data = aMessage.data;
|
||||
let registrar = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
|
||||
getService(Ci.nsIWebContentHandlerRegistrar);
|
||||
registrar.registerProtocolHandler(data.protocol, data.uri, data.title,
|
||||
aMessage.target);
|
||||
break;
|
||||
}
|
||||
|
||||
case "WCCR:registerContentHandler": {
|
||||
let data = aMessage.data;
|
||||
let registrar = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
|
||||
getService(Ci.nsIWebContentHandlerRegistrar);
|
||||
registrar.registerContentHandler(data.contentType, data.uri, data.title,
|
||||
aMessage.target);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* isValidFeed: checks whether the given data represents a valid feed.
|
||||
|
@ -101,20 +101,27 @@
|
||||
list-style-image: url("chrome://browser/skin/tabbrowser/crashed.svg");
|
||||
}
|
||||
|
||||
.tab-icon-overlay[soundplaying][pinned] {
|
||||
.tab-icon-overlay[soundplaying][pinned],
|
||||
.tab-icon-overlay[muted][pinned] {
|
||||
display: -moz-box;
|
||||
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio");
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.tab-icon-overlay[soundplaying][pinned]:hover,
|
||||
.tab-icon-overlay[muted][pinned]:hover {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.tab-icon-overlay[soundplaying][pinned] {
|
||||
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio");
|
||||
}
|
||||
|
||||
.tab-icon-overlay[soundplaying][pinned]:hover {
|
||||
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-hover");
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.tab-icon-overlay[soundplaying][pinned]:hover:active {
|
||||
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-pressed");
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.tab-icon-overlay[muted][pinned] {
|
||||
@ -179,7 +186,7 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.tab-icon-sound:not([soundplaying]),
|
||||
.tab-icon-sound:not([soundplaying]):not([muted]),
|
||||
.tab-icon-sound[pinned] {
|
||||
display: none;
|
||||
}
|
||||
@ -414,6 +421,7 @@
|
||||
.tab-background-middle,
|
||||
.tabs-newtab-button,
|
||||
.tab-icon-overlay[soundplaying],
|
||||
.tab-icon-overlay[muted],
|
||||
.tab-icon-sound,
|
||||
.tab-close-button {
|
||||
pointer-events: auto;
|
||||
|
@ -17,11 +17,6 @@
|
||||
// Silence "warning: #include_next is a GCC extension"
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifdef _WIN32
|
||||
// Suppress windef.h min and max macros - they make std::min/max not compile.
|
||||
#define NOMINMAX 1
|
||||
#endif
|
||||
|
||||
// mozalloc.h wants <new>; break the cycle by always explicitly
|
||||
// including <new> here. NB: this is a tad sneaky. Sez the gcc docs:
|
||||
//
|
||||
|
@ -12,9 +12,6 @@
|
||||
# error "STL code can only be used with -fno-exceptions"
|
||||
#endif
|
||||
|
||||
// Suppress windef.h min and max macros - they make std::min/max not compile.
|
||||
#define NOMINMAX 1
|
||||
|
||||
// Code built with !_HAS_EXCEPTIONS calls std::_Throw(), but the win2k
|
||||
// CRT doesn't export std::_Throw(). So we define it.
|
||||
#ifndef mozilla_Throw_h
|
||||
|
@ -2332,6 +2332,8 @@ ia64*-hpux*)
|
||||
AC_DEFINE(HW_THREADS)
|
||||
AC_DEFINE(STDC_HEADERS)
|
||||
AC_DEFINE(WIN32_LEAN_AND_MEAN)
|
||||
dnl See http://support.microsoft.com/kb/143208 to use STL
|
||||
AC_DEFINE(NOMINMAX)
|
||||
TARGET_MD_ARCH=win32
|
||||
_PLATFORM_DEFAULT_TOOLKIT='cairo-windows'
|
||||
BIN_SUFFIX='.exe'
|
||||
|
@ -1134,12 +1134,14 @@ nsFocusManager::ActivateOrDeactivate(nsPIDOMWindow* aWindow, bool aActive)
|
||||
aWindow->ActivateOrDeactivate(aActive);
|
||||
|
||||
// Send the activate event.
|
||||
nsContentUtils::DispatchEventOnlyToChrome(aWindow->GetExtantDoc(),
|
||||
aWindow,
|
||||
aActive ?
|
||||
NS_LITERAL_STRING("activate") :
|
||||
NS_LITERAL_STRING("deactivate"),
|
||||
true, true, nullptr);
|
||||
if (aWindow->GetExtantDoc()) {
|
||||
nsContentUtils::DispatchEventOnlyToChrome(aWindow->GetExtantDoc(),
|
||||
aWindow,
|
||||
aActive ?
|
||||
NS_LITERAL_STRING("activate") :
|
||||
NS_LITERAL_STRING("deactivate"),
|
||||
true, true, nullptr);
|
||||
}
|
||||
|
||||
// Look for any remote child frames, iterate over them and send the activation notification.
|
||||
nsContentUtils::CallOnAllRemoteChildren(aWindow, ActivateOrDeactivateChild,
|
||||
|
@ -2694,136 +2694,128 @@ protected:
|
||||
mozilla::dom::VisibilityState mVisibilityState;
|
||||
|
||||
// True if BIDI is enabled.
|
||||
bool mBidiEnabled;
|
||||
bool mBidiEnabled : 1;
|
||||
// True if a MathML element has ever been owned by this document.
|
||||
bool mMathMLEnabled;
|
||||
bool mMathMLEnabled : 1;
|
||||
|
||||
// True if this document is the initial document for a window. This should
|
||||
// basically be true only for documents that exist in newly-opened windows or
|
||||
// documents created to satisfy a GetDocument() on a window when there's no
|
||||
// document in it.
|
||||
bool mIsInitialDocumentInWindow;
|
||||
bool mIsInitialDocumentInWindow : 1;
|
||||
|
||||
// True if we're loaded as data and therefor has any dangerous stuff, such
|
||||
// as scripts and plugins, disabled.
|
||||
bool mLoadedAsData;
|
||||
bool mLoadedAsData : 1;
|
||||
|
||||
// This flag is only set in XMLDocument, for e.g. documents used in XBL. We
|
||||
// don't want animations to play in such documents, so we need to store the
|
||||
// flag here so that we can check it in nsDocument::GetAnimationController.
|
||||
bool mLoadedAsInteractiveData;
|
||||
bool mLoadedAsInteractiveData : 1;
|
||||
|
||||
// If true, whoever is creating the document has gotten it to the
|
||||
// point where it's safe to start layout on it.
|
||||
bool mMayStartLayout;
|
||||
bool mMayStartLayout : 1;
|
||||
|
||||
// True iff we've ever fired a DOMTitleChanged event for this document
|
||||
bool mHaveFiredTitleChange;
|
||||
bool mHaveFiredTitleChange : 1;
|
||||
|
||||
// True iff IsShowing() should be returning true
|
||||
bool mIsShowing;
|
||||
bool mIsShowing : 1;
|
||||
|
||||
// True iff the document "page" is not hidden (i.e. currently in the
|
||||
// bfcache)
|
||||
bool mVisible;
|
||||
bool mVisible : 1;
|
||||
|
||||
// True if our content viewer has been removed from the docshell
|
||||
// (it may still be displayed, but in zombie state). Form control data
|
||||
// has been saved.
|
||||
bool mRemovedFromDocShell;
|
||||
bool mRemovedFromDocShell : 1;
|
||||
|
||||
// True iff DNS prefetch is allowed for this document. Note that if the
|
||||
// document has no window, DNS prefetch won't be performed no matter what.
|
||||
bool mAllowDNSPrefetch;
|
||||
bool mAllowDNSPrefetch : 1;
|
||||
|
||||
// True when this document is a static clone of a normal document
|
||||
bool mIsStaticDocument;
|
||||
bool mIsStaticDocument : 1;
|
||||
|
||||
// True while this document is being cloned to a static document.
|
||||
bool mCreatingStaticClone;
|
||||
bool mCreatingStaticClone : 1;
|
||||
|
||||
// True iff the document is being unlinked or deleted.
|
||||
bool mInUnlinkOrDeletion;
|
||||
bool mInUnlinkOrDeletion : 1;
|
||||
|
||||
// True if document has ever had script handling object.
|
||||
bool mHasHadScriptHandlingObject;
|
||||
bool mHasHadScriptHandlingObject : 1;
|
||||
|
||||
// True if we're an SVG document being used as an image.
|
||||
bool mIsBeingUsedAsImage;
|
||||
bool mIsBeingUsedAsImage : 1;
|
||||
|
||||
// True is this document is synthetic : stand alone image, video, audio
|
||||
// file, etc.
|
||||
bool mIsSyntheticDocument;
|
||||
bool mIsSyntheticDocument : 1;
|
||||
|
||||
// True if this document has links whose state needs updating
|
||||
bool mHasLinksToUpdate;
|
||||
bool mHasLinksToUpdate : 1;
|
||||
|
||||
// True if a layout flush might not be a no-op
|
||||
bool mNeedLayoutFlush;
|
||||
bool mNeedLayoutFlush : 1;
|
||||
|
||||
// True if a style flush might not be a no-op
|
||||
bool mNeedStyleFlush;
|
||||
bool mNeedStyleFlush : 1;
|
||||
|
||||
// True if a DOMMutationObserver is perhaps attached to a node in the document.
|
||||
bool mMayHaveDOMMutationObservers;
|
||||
bool mMayHaveDOMMutationObservers : 1;
|
||||
|
||||
// True if an nsIAnimationObserver is perhaps attached to a node in the document.
|
||||
bool mMayHaveAnimationObservers;
|
||||
bool mMayHaveAnimationObservers : 1;
|
||||
|
||||
// True if a document has loaded Mixed Active Script (see nsMixedContentBlocker.cpp)
|
||||
bool mHasMixedActiveContentLoaded;
|
||||
bool mHasMixedActiveContentLoaded : 1;
|
||||
|
||||
// True if a document has blocked Mixed Active Script (see nsMixedContentBlocker.cpp)
|
||||
bool mHasMixedActiveContentBlocked;
|
||||
bool mHasMixedActiveContentBlocked : 1;
|
||||
|
||||
// True if a document has loaded Mixed Display/Passive Content (see nsMixedContentBlocker.cpp)
|
||||
bool mHasMixedDisplayContentLoaded;
|
||||
bool mHasMixedDisplayContentLoaded : 1;
|
||||
|
||||
// True if a document has blocked Mixed Display/Passive Content (see nsMixedContentBlocker.cpp)
|
||||
bool mHasMixedDisplayContentBlocked;
|
||||
bool mHasMixedDisplayContentBlocked : 1;
|
||||
|
||||
// True if a document has blocked Tracking Content
|
||||
bool mHasTrackingContentBlocked;
|
||||
bool mHasTrackingContentBlocked : 1;
|
||||
|
||||
// True if a document has loaded Tracking Content
|
||||
bool mHasTrackingContentLoaded;
|
||||
bool mHasTrackingContentLoaded : 1;
|
||||
|
||||
// True if DisallowBFCaching has been called on this document.
|
||||
bool mBFCacheDisallowed;
|
||||
bool mBFCacheDisallowed : 1;
|
||||
|
||||
// If true, we have an input encoding. If this is false, then the
|
||||
// document was created entirely in memory
|
||||
bool mHaveInputEncoding;
|
||||
bool mHaveInputEncoding : 1;
|
||||
|
||||
bool mHasHadDefaultView;
|
||||
bool mHasHadDefaultView : 1;
|
||||
|
||||
// Whether style sheet change events will be dispatched for this document
|
||||
bool mStyleSheetChangeEventsEnabled;
|
||||
bool mStyleSheetChangeEventsEnabled : 1;
|
||||
|
||||
// Whether the document was created by a srcdoc iframe.
|
||||
bool mIsSrcdocDocument;
|
||||
bool mIsSrcdocDocument : 1;
|
||||
|
||||
// Records whether we've done a document.open. If this is true, it's possible
|
||||
// for nodes from this document to have outdated wrappers in their wrapper
|
||||
// caches.
|
||||
bool mDidDocumentOpen;
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
* This is true while FlushPendingLinkUpdates executes. Calls to
|
||||
* [Un]RegisterPendingLinkUpdate will assert when this is true.
|
||||
*/
|
||||
bool mIsLinkUpdateRegistrationsForbidden;
|
||||
#endif
|
||||
bool mDidDocumentOpen : 1;
|
||||
|
||||
// Is the current mFontFaceSet valid?
|
||||
bool mFontFaceSetDirty;
|
||||
bool mFontFaceSetDirty : 1;
|
||||
|
||||
// Has GetUserFontSet() been called?
|
||||
bool mGetUserFontSetCalled;
|
||||
bool mGetUserFontSetCalled : 1;
|
||||
|
||||
// Do we currently have an event posted to call FlushUserFontSet?
|
||||
bool mPostedFlushUserFontSet;
|
||||
bool mPostedFlushUserFontSet : 1;
|
||||
|
||||
enum Type {
|
||||
eUnknown, // should never be used
|
||||
@ -2834,17 +2826,25 @@ protected:
|
||||
eXUL
|
||||
};
|
||||
|
||||
uint8_t mType;
|
||||
Type mType;
|
||||
|
||||
uint8_t mDefaultElementType;
|
||||
|
||||
enum {
|
||||
enum Tri {
|
||||
eTriUnset = 0,
|
||||
eTriFalse,
|
||||
eTriTrue
|
||||
};
|
||||
|
||||
uint8_t mAllowXULXBL;
|
||||
Tri mAllowXULXBL;
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
* This is true while FlushPendingLinkUpdates executes. Calls to
|
||||
* [Un]RegisterPendingLinkUpdate will assert when this is true.
|
||||
*/
|
||||
bool mIsLinkUpdateRegistrationsForbidden;
|
||||
#endif
|
||||
|
||||
// The document's script global object, the object from which the
|
||||
// document can get its script context and scope. This is the
|
||||
|
@ -95,6 +95,24 @@ nsStructuredCloneContainer::InitFromBase64(const nsAString &aData,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsStructuredCloneContainer::DeserializeToJsval(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
{
|
||||
aValue.setNull();
|
||||
JS::Rooted<JS::Value> jsStateObj(aCx);
|
||||
bool hasTransferable = false;
|
||||
bool success = JS_ReadStructuredClone(aCx, mData, mSize, mVersion,
|
||||
&jsStateObj, nullptr, nullptr) &&
|
||||
JS_StructuredCloneHasTransferables(mData, mSize,
|
||||
&hasTransferable);
|
||||
// We want to be sure that mData doesn't contain transferable objects
|
||||
MOZ_ASSERT(!hasTransferable);
|
||||
NS_ENSURE_STATE(success && !hasTransferable);
|
||||
|
||||
aValue.set(jsStateObj);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsStructuredCloneContainer::DeserializeToVariant(JSContext *aCx,
|
||||
@ -106,14 +124,8 @@ nsStructuredCloneContainer::DeserializeToVariant(JSContext *aCx,
|
||||
|
||||
// Deserialize to a JS::Value.
|
||||
JS::Rooted<JS::Value> jsStateObj(aCx);
|
||||
bool hasTransferable = false;
|
||||
bool success = JS_ReadStructuredClone(aCx, mData, mSize, mVersion,
|
||||
&jsStateObj, nullptr, nullptr) &&
|
||||
JS_StructuredCloneHasTransferables(mData, mSize,
|
||||
&hasTransferable);
|
||||
// We want to be sure that mData doesn't contain transferable objects
|
||||
MOZ_ASSERT(!hasTransferable);
|
||||
NS_ENSURE_STATE(success && !hasTransferable);
|
||||
nsresult rv = DeserializeToJsval(aCx, &jsStateObj);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Now wrap the JS::Value as an nsIVariant.
|
||||
nsCOMPtr<nsIVariant> varStateObj;
|
||||
|
1
dom/cache/PCacheStorage.ipdl
vendored
1
dom/cache/PCacheStorage.ipdl
vendored
@ -6,6 +6,7 @@ include protocol PBackground;
|
||||
include protocol PBlob; // FIXME: bug 792908
|
||||
include protocol PCache;
|
||||
include protocol PCacheOp;
|
||||
include protocol PCachePushStream;
|
||||
include protocol PCacheStreamControl;
|
||||
include protocol PFileDescriptorSet;
|
||||
|
||||
|
@ -4,9 +4,6 @@
|
||||
# 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/.
|
||||
|
||||
# http://support.microsoft.com/kb/143208
|
||||
DEFINES['NOMINMAX'] = True
|
||||
|
||||
GeckoCppUnitTests([
|
||||
'TestWebGLElementArrayCache',
|
||||
])
|
||||
|
@ -36,9 +36,6 @@ EXPORTS.mozilla.dom += [
|
||||
'WebGLVertexArrayObject.h',
|
||||
]
|
||||
|
||||
# http://support.microsoft.com/kb/143208
|
||||
DEFINES['NOMINMAX'] = True
|
||||
|
||||
# Canvas 2D and common sources
|
||||
UNIFIED_SOURCES += [
|
||||
'CanvasImageCache.cpp',
|
||||
|
@ -499,29 +499,29 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
* scroll.
|
||||
* @param aOptions Set following flags.
|
||||
*/
|
||||
const unsigned long WHEEL_EVENT_CAUSED_BY_NO_LINE_OR_PAGE_DELTA_DEVICE = 0x0001;
|
||||
// @deprecated Use WHEEL_EVENT_CAUSED_BY_NO_LINE_OR_PAGE_DELTA_DEVICE.
|
||||
const unsigned long WHEEL_EVENT_CAUSED_BY_PIXEL_ONLY_DEVICE = 0x0001;
|
||||
const unsigned long WHEEL_EVENT_CAUSED_BY_MOMENTUM = 0x0002;
|
||||
const unsigned long WHEEL_EVENT_CUSTOMIZED_BY_USER_PREFS = 0x0004;
|
||||
// If any of the following flags is specified this method will throw an
|
||||
// exception in case the relevant overflowDelta has an unexpected value.
|
||||
const unsigned long WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_ZERO = 0x0010;
|
||||
const unsigned long WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_POSITIVE = 0x0020;
|
||||
const unsigned long WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_NEGATIVE = 0x0040;
|
||||
const unsigned long WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_ZERO = 0x0100;
|
||||
const unsigned long WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_POSITIVE = 0x0200;
|
||||
const unsigned long WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_NEGATIVE = 0x0400;
|
||||
void sendWheelEvent(in float aX,
|
||||
in float aY,
|
||||
in double aDeltaX,
|
||||
in double aDeltaY,
|
||||
in double aDeltaZ,
|
||||
in unsigned long aDeltaMode,
|
||||
in long aModifiers,
|
||||
in long aLineOrPageDeltaX,
|
||||
in long aLineOrPageDeltaY,
|
||||
in unsigned long aOptions);
|
||||
const unsigned long WHEEL_EVENT_CAUSED_BY_NO_LINE_OR_PAGE_DELTA_DEVICE = 0x0001;
|
||||
// @deprecated Use WHEEL_EVENT_CAUSED_BY_NO_LINE_OR_PAGE_DELTA_DEVICE.
|
||||
const unsigned long WHEEL_EVENT_CAUSED_BY_PIXEL_ONLY_DEVICE = 0x0001;
|
||||
const unsigned long WHEEL_EVENT_CAUSED_BY_MOMENTUM = 0x0002;
|
||||
const unsigned long WHEEL_EVENT_CUSTOMIZED_BY_USER_PREFS = 0x0004;
|
||||
// If any of the following flags is specified this method will throw an
|
||||
// exception in case the relevant overflowDelta has an unexpected value.
|
||||
const unsigned long WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_ZERO = 0x0010;
|
||||
const unsigned long WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_POSITIVE = 0x0020;
|
||||
const unsigned long WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_NEGATIVE = 0x0040;
|
||||
const unsigned long WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_ZERO = 0x0100;
|
||||
const unsigned long WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_POSITIVE = 0x0200;
|
||||
const unsigned long WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_NEGATIVE = 0x0400;
|
||||
void sendWheelEvent(in float aX,
|
||||
in float aY,
|
||||
in double aDeltaX,
|
||||
in double aDeltaY,
|
||||
in double aDeltaZ,
|
||||
in unsigned long aDeltaMode,
|
||||
in long aModifiers,
|
||||
in long aLineOrPageDeltaX,
|
||||
in long aLineOrPageDeltaY,
|
||||
in unsigned long aOptions);
|
||||
|
||||
/**
|
||||
* Synthesize a key event to the window. The event types supported are:
|
||||
@ -1359,16 +1359,16 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
/**
|
||||
* Returns a handle which represents current recording start position.
|
||||
*/
|
||||
void startFrameTimeRecording([retval] out unsigned long startIndex);
|
||||
void startFrameTimeRecording([retval] out unsigned long startIndex);
|
||||
|
||||
/**
|
||||
* Returns number of recorded frames since startIndex was issued,
|
||||
* and allocates+populates 2 arraye with the recorded data.
|
||||
* - Allocation is infallible. Should be released even if size is 0.
|
||||
*/
|
||||
void stopFrameTimeRecording(in unsigned long startIndex,
|
||||
[optional] out unsigned long frameCount,
|
||||
[retval, array, size_is(frameCount)] out float frameIntervals);
|
||||
void stopFrameTimeRecording(in unsigned long startIndex,
|
||||
[optional] out unsigned long frameCount,
|
||||
[retval, array, size_is(frameCount)] out float frameIntervals);
|
||||
|
||||
/**
|
||||
* Signals that we're begining to tab switch. This is used by painting code to
|
||||
@ -1697,7 +1697,7 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
* After calling the method, the window for which this DOMWindowUtils
|
||||
* was created can be closed using scripts.
|
||||
*/
|
||||
void allowScriptsToClose();
|
||||
void allowScriptsToClose();
|
||||
|
||||
/**
|
||||
* Is the parent window's main widget visible? If it isn't, we probably
|
||||
@ -1710,109 +1710,109 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
*/
|
||||
readonly attribute boolean isParentWindowMainWidgetVisible;
|
||||
|
||||
/**
|
||||
* In certain cases the event handling of nodes, form controls in practice,
|
||||
* may be disabled. Such cases are for example the existence of disabled
|
||||
* attribute or -moz-user-input: none/disabled.
|
||||
*/
|
||||
boolean isNodeDisabledForEvents(in nsIDOMNode aNode);
|
||||
/**
|
||||
* In certain cases the event handling of nodes, form controls in practice,
|
||||
* may be disabled. Such cases are for example the existence of disabled
|
||||
* attribute or -moz-user-input: none/disabled.
|
||||
*/
|
||||
boolean isNodeDisabledForEvents(in nsIDOMNode aNode);
|
||||
|
||||
/**
|
||||
* Setting paintFlashing to true will flash newly painted area.
|
||||
*/
|
||||
attribute boolean paintFlashing;
|
||||
/**
|
||||
* Setting paintFlashing to true will flash newly painted area.
|
||||
*/
|
||||
attribute boolean paintFlashing;
|
||||
|
||||
/**
|
||||
* Add a "synchronous section", in the form of an nsIRunnable run once the
|
||||
* event loop has reached a "stable state". |runnable| must not cause any
|
||||
* queued events to be processed (i.e. must not spin the event loop).
|
||||
* We've reached a stable state when the currently executing task/event has
|
||||
* finished, see:
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#synchronous-section
|
||||
* In practice this runs aRunnable once the currently executing event
|
||||
* finishes. If called multiple times per task/event, all the runnables will
|
||||
* be executed, in the order in which runInStableState() was called.
|
||||
*
|
||||
* XXX - This can wreak havoc if you're not using this for very simple
|
||||
* purposes, eg testing or setting a flag.
|
||||
*/
|
||||
void runInStableState(in nsIRunnable runnable);
|
||||
/**
|
||||
* Add a "synchronous section", in the form of an nsIRunnable run once the
|
||||
* event loop has reached a "stable state". |runnable| must not cause any
|
||||
* queued events to be processed (i.e. must not spin the event loop).
|
||||
* We've reached a stable state when the currently executing task/event has
|
||||
* finished, see:
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#synchronous-section
|
||||
* In practice this runs aRunnable once the currently executing event
|
||||
* finishes. If called multiple times per task/event, all the runnables will
|
||||
* be executed, in the order in which runInStableState() was called.
|
||||
*
|
||||
* XXX - This can wreak havoc if you're not using this for very simple
|
||||
* purposes, eg testing or setting a flag.
|
||||
*/
|
||||
void runInStableState(in nsIRunnable runnable);
|
||||
|
||||
/**
|
||||
* Run the given runnable before the next iteration of the event loop (this
|
||||
* includes native events too). If a nested loop is spawned within the current
|
||||
* event then the runnable will not be run until that loop has terminated.
|
||||
*
|
||||
* XXX - This can wreak havoc if you're not using this for very simple
|
||||
* purposes, eg testing or setting a flag.
|
||||
*/
|
||||
void runBeforeNextEvent(in nsIRunnable runnable);
|
||||
/**
|
||||
* Run the given runnable before the next iteration of the event loop (this
|
||||
* includes native events too). If a nested loop is spawned within the current
|
||||
* event then the runnable will not be run until that loop has terminated.
|
||||
*
|
||||
* XXX - This can wreak havoc if you're not using this for very simple
|
||||
* purposes, eg testing or setting a flag.
|
||||
*/
|
||||
void runBeforeNextEvent(in nsIRunnable runnable);
|
||||
|
||||
/*
|
||||
* Returns the value of a given property animated on the compositor thread.
|
||||
* If the property is NOT currently being animated on the compositor thread,
|
||||
* returns an empty string.
|
||||
*/
|
||||
AString getOMTAStyle(in nsIDOMElement aElement, in AString aProperty,
|
||||
[optional] in AString aPseudoElement);
|
||||
/*
|
||||
* Returns the value of a given property animated on the compositor thread.
|
||||
* If the property is NOT currently being animated on the compositor thread,
|
||||
* returns an empty string.
|
||||
*/
|
||||
AString getOMTAStyle(in nsIDOMElement aElement, in AString aProperty,
|
||||
[optional] in AString aPseudoElement);
|
||||
|
||||
/**
|
||||
* Special function that gets a property syncronously from the last composite
|
||||
* that occured.
|
||||
*
|
||||
* Supported properties:
|
||||
* "overdraw": Report a percentage between 0 and 999 indicate how many times
|
||||
* each pixels on the destination window have been touched.
|
||||
* "missed_hwc": Report a bool if hardware composer is supported but was
|
||||
* not used for the last frame.
|
||||
*/
|
||||
float requestCompositorProperty(in AString aProperty);
|
||||
/**
|
||||
* Special function that gets a property syncronously from the last composite
|
||||
* that occured.
|
||||
*
|
||||
* Supported properties:
|
||||
* "overdraw": Report a percentage between 0 and 999 indicate how many times
|
||||
* each pixels on the destination window have been touched.
|
||||
* "missed_hwc": Report a bool if hardware composer is supported but was
|
||||
* not used for the last frame.
|
||||
*/
|
||||
float requestCompositorProperty(in AString aProperty);
|
||||
|
||||
/**
|
||||
* If aHandlingInput is true, this informs the event state manager that
|
||||
* we're handling user input. Otherwise, this is a no-op (as by default
|
||||
* we're not handling user input).
|
||||
* Remember to call destruct() on the return value!
|
||||
* See also nsIDOMWindowUtils::isHandlingUserInput.
|
||||
*/
|
||||
nsIJSRAIIHelper setHandlingUserInput(in boolean aHandlingInput);
|
||||
/**
|
||||
* If aHandlingInput is true, this informs the event state manager that
|
||||
* we're handling user input. Otherwise, this is a no-op (as by default
|
||||
* we're not handling user input).
|
||||
* Remember to call destruct() on the return value!
|
||||
* See also nsIDOMWindowUtils::isHandlingUserInput.
|
||||
*/
|
||||
nsIJSRAIIHelper setHandlingUserInput(in boolean aHandlingInput);
|
||||
|
||||
/**
|
||||
* Get the content- and compositor-side APZ test data instances.
|
||||
* The return values are of type APZTestData (see APZTestData.webidl).
|
||||
*/
|
||||
[implicit_jscontext] jsval getContentAPZTestData();
|
||||
[implicit_jscontext] jsval getCompositorAPZTestData();
|
||||
/**
|
||||
* Get the content- and compositor-side APZ test data instances.
|
||||
* The return values are of type APZTestData (see APZTestData.webidl).
|
||||
*/
|
||||
[implicit_jscontext] jsval getContentAPZTestData();
|
||||
[implicit_jscontext] jsval getCompositorAPZTestData();
|
||||
|
||||
/**
|
||||
* Posts an eRestyle_Self restyle event for the given element.
|
||||
*/
|
||||
void postRestyleSelfEvent(in nsIDOMElement aElement);
|
||||
/**
|
||||
* Posts an eRestyle_Self restyle event for the given element.
|
||||
*/
|
||||
void postRestyleSelfEvent(in nsIDOMElement aElement);
|
||||
|
||||
/**
|
||||
* With this it's possible to mute all the MediaElements in this window.
|
||||
* We have audioMuted and audioVolume to preserve the volume across
|
||||
* mute/umute.
|
||||
*/
|
||||
attribute boolean audioMuted;
|
||||
/**
|
||||
* With this it's possible to mute all the MediaElements in this window.
|
||||
* We have audioMuted and audioVolume to preserve the volume across
|
||||
* mute/umute.
|
||||
*/
|
||||
attribute boolean audioMuted;
|
||||
|
||||
/**
|
||||
* range: greater or equal to 0. The real volume level is affected by the
|
||||
* volume of all ancestor windows.
|
||||
*/
|
||||
attribute float audioVolume;
|
||||
/**
|
||||
* range: greater or equal to 0. The real volume level is affected by the
|
||||
* volume of all ancestor windows.
|
||||
*/
|
||||
attribute float audioVolume;
|
||||
|
||||
/**
|
||||
* This method doesn't do anything useful. It was solely added for the
|
||||
* purpose of the test for bug 503926.
|
||||
*/
|
||||
void xpconnectArgument(in nsIDOMWindowUtils aThis);
|
||||
/**
|
||||
* This method doesn't do anything useful. It was solely added for the
|
||||
* purpose of the test for bug 503926.
|
||||
*/
|
||||
void xpconnectArgument(in nsIDOMWindowUtils aThis);
|
||||
|
||||
/**
|
||||
* Helper for JS components that need to send permission requests with
|
||||
* e10s support properly.
|
||||
*/
|
||||
void askPermission(in nsIContentPermissionRequest aRequest);
|
||||
/**
|
||||
* Helper for JS components that need to send permission requests with
|
||||
* e10s support properly.
|
||||
*/
|
||||
void askPermission(in nsIContentPermissionRequest aRequest);
|
||||
|
||||
/**
|
||||
* Number of frames constructed (excluding breaking) for the curent
|
||||
|
@ -27,7 +27,7 @@ interface nsIDocument;
|
||||
* string containing a copy of the container's serialized data, using
|
||||
* getDataAsBase64.
|
||||
*/
|
||||
[scriptable, uuid(63eeafec-63f5-42c3-aea9-5c04678784e7)]
|
||||
[scriptable, uuid(c664aae7-0d67-4155-a2dd-a3861778626f)]
|
||||
interface nsIStructuredCloneContainer : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -45,9 +45,17 @@ interface nsIStructuredCloneContainer : nsISupports
|
||||
[implicit_jscontext]
|
||||
void initFromBase64(in AString aData,in unsigned long aFormatVersion);
|
||||
|
||||
/**
|
||||
* Deserializes this structured clone container returning it as a jsval.
|
||||
* Can be called on main and worker threads.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
jsval deserializeToJsval();
|
||||
|
||||
/**
|
||||
* Deserialize the object this container holds, returning it wrapped as
|
||||
* an nsIVariant.
|
||||
* Main thread only!
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
nsIVariant deserializeToVariant();
|
||||
|
@ -11,7 +11,7 @@
|
||||
* uses service workers to notify applications. This interface exists to allow
|
||||
* privileged code to receive messages without migrating to service workers.
|
||||
*/
|
||||
[scriptable, uuid(abde228b-7d14-4cab-b1f9-9f87750ede0f)]
|
||||
[scriptable, uuid(74586476-d73f-4867-bece-87c1dea35750)]
|
||||
interface nsIPushNotificationService : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -48,7 +48,12 @@ interface nsIPushNotificationService : nsISupports
|
||||
jsval registration(in string scope, in jsval originAttributes);
|
||||
|
||||
/**
|
||||
* Clear all subscriptions
|
||||
* Clear all subscriptions.
|
||||
*/
|
||||
jsval clearAll();
|
||||
jsval clearAll();
|
||||
|
||||
/**
|
||||
* Clear subscriptions for a domain.
|
||||
*/
|
||||
jsval clearForDomain(in string domain);
|
||||
};
|
||||
|
@ -6,8 +6,6 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIDOMWindow;
|
||||
|
||||
/**
|
||||
* nsIWebContentHandlerRegistrar
|
||||
*
|
||||
@ -19,7 +17,7 @@ interface nsIDOMWindow;
|
||||
* can invoke it.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(e6a75410-c93e-42bf-84ca-a5c3ec34a2f1)]
|
||||
[scriptable, uuid(65a3fafd-0e4a-4b06-8b4e-6a611da63d98)]
|
||||
interface nsIWebContentHandlerRegistrar : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -30,11 +28,11 @@ interface nsIWebContentHandlerRegistrar : nsISupports
|
||||
void registerContentHandler(in DOMString mimeType,
|
||||
in DOMString uri,
|
||||
in DOMString title,
|
||||
in nsIDOMWindow contentWindow);
|
||||
in nsISupports windowOrBrowser);
|
||||
void registerProtocolHandler(in DOMString protocol,
|
||||
in DOMString uri,
|
||||
in DOMString title,
|
||||
in nsIDOMWindow contentWindow);
|
||||
in nsISupports windowOrBrowser);
|
||||
};
|
||||
|
||||
%{ C++
|
||||
|
@ -193,6 +193,7 @@
|
||||
#include "mozilla/RemoteSpellCheckEngineChild.h"
|
||||
#include "GMPServiceChild.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "nscore.h" // for NS_FREE_PERMANENT_DATA
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::docshell;
|
||||
@ -762,6 +763,14 @@ ContentChild::AppendProcessId(nsACString& aName)
|
||||
aName.Append(nsPrintfCString("(pid %u)", pid));
|
||||
}
|
||||
|
||||
void
|
||||
ContentChild::InitGraphicsDeviceData()
|
||||
{
|
||||
// Initialize the graphics platform. This may contact the parent process
|
||||
// to read device preferences.
|
||||
gfxPlatform::GetPlatform();
|
||||
}
|
||||
|
||||
void
|
||||
ContentChild::InitXPCOM()
|
||||
{
|
||||
@ -1897,7 +1906,7 @@ ContentChild::ActorDestroy(ActorDestroyReason why)
|
||||
QuickExit();
|
||||
}
|
||||
|
||||
#if !defined(DEBUG) && !defined(MOZ_ASAN)
|
||||
#ifndef NS_FREE_PERMANENT_DATA
|
||||
// In release builds, there's no point in the content process
|
||||
// going through the full XPCOM shutdown path, because it doesn't
|
||||
// keep persistent state.
|
||||
|
@ -76,6 +76,7 @@ public:
|
||||
IPC::Channel* aChannel);
|
||||
void InitProcessAttributes();
|
||||
void InitXPCOM();
|
||||
void InitGraphicsDeviceData();
|
||||
|
||||
static ContentChild* GetSingleton() {
|
||||
return sSingleton;
|
||||
|
@ -5148,6 +5148,13 @@ ContentParent::RecvProfile(const nsCString& aProfile)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvGetGraphicsDeviceInitData(DeviceInitData* aOut)
|
||||
{
|
||||
gfxPlatform::GetPlatform()->GetDeviceInitData(aOut);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -862,6 +862,7 @@ private:
|
||||
virtual bool RecvGamepadListenerAdded() override;
|
||||
virtual bool RecvGamepadListenerRemoved() override;
|
||||
virtual bool RecvProfile(const nsCString& aProfile) override;
|
||||
virtual bool RecvGetGraphicsDeviceInitData(DeviceInitData* aOut) override;
|
||||
|
||||
// If you add strong pointers to cycle collected objects here, be sure to
|
||||
// release these objects in ShutDownProcess. See the comment there for more
|
||||
|
@ -76,10 +76,11 @@ bool
|
||||
ContentProcess::Init()
|
||||
{
|
||||
mContent.Init(IOThreadChild::message_loop(),
|
||||
ParentPid(),
|
||||
IOThreadChild::channel());
|
||||
ParentPid(),
|
||||
IOThreadChild::channel());
|
||||
mXREEmbed.Start();
|
||||
mContent.InitXPCOM();
|
||||
mContent.InitGraphicsDeviceData();
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
|
||||
SetUpSandboxEnvironment();
|
||||
|
@ -60,6 +60,7 @@ include PluginTypes;
|
||||
include ProtocolTypes;
|
||||
include PContentPermission;
|
||||
include BrowserConfiguration;
|
||||
include GraphicsMessages;
|
||||
|
||||
// Workaround to prevent error if PContentChild.cpp & PContentBridgeParent.cpp
|
||||
// are put into different UnifiedProtocolsXX.cpp files.
|
||||
@ -1053,6 +1054,12 @@ parent:
|
||||
|
||||
async Profile(nsCString aProfile);
|
||||
|
||||
/**
|
||||
* Request graphics initialization information from the parent.
|
||||
*/
|
||||
sync GetGraphicsDeviceInitData()
|
||||
returns (DeviceInitData aData);
|
||||
|
||||
both:
|
||||
AsyncMessage(nsString aMessage, ClonedMessageData aData,
|
||||
CpowEntry[] aCpows, Principal aPrincipal);
|
||||
|
@ -3237,9 +3237,15 @@ TabParent::RecvInvokeDragSession(nsTArray<IPCDataTransfer>&& aTransfers,
|
||||
const int32_t& aDragAreaX, const int32_t& aDragAreaY)
|
||||
{
|
||||
mInitialDataTransferItems.Clear();
|
||||
nsPresContext* pc = mFrameElement->OwnerDoc()->GetShell()->GetPresContext();
|
||||
EventStateManager* esm = pc->EventStateManager();
|
||||
nsIPresShell* shell = mFrameElement->OwnerDoc()->GetShell();
|
||||
if (!shell) {
|
||||
if (Manager()->IsContentParent()) {
|
||||
unused << Manager()->AsContentParent()->SendEndDragSession(true, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
EventStateManager* esm = shell->GetPresContext()->EventStateManager();
|
||||
for (uint32_t i = 0; i < aTransfers.Length(); ++i) {
|
||||
auto& items = aTransfers[i].items();
|
||||
nsTArray<DataTransferItem>* itemArray = mInitialDataTransferItems.AppendElement();
|
||||
|
@ -6,7 +6,6 @@ BlockMixedActiveContent = Blocked loading mixed active content "%1$S"
|
||||
# CORS
|
||||
# LOCALIZATION NOTE: Do not translate "Access-Control-Allow-Origin", Access-Control-Allow-Credentials, Access-Control-Allow-Methods, Access-Control-Allow-Headers
|
||||
CORSDisabled=Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at %1$S. (Reason: CORS disabled).
|
||||
CORSRequestFailed=Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at %1$S. (Reason: CORS request failed).
|
||||
CORSRequestNotHttp=Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at %1$S. (Reason: CORS request not http).
|
||||
CORSMissingAllowOrigin=Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at %1$S. (Reason: CORS header 'Access-Control-Allow-Origin' missing).
|
||||
CORSAllowOriginNotMatchingOrigin=Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at %1$S. (Reason: CORS header 'Access-Control-Allow-Origin' does not match '%2$S').
|
||||
|
@ -41,6 +41,3 @@ FINAL_LIBRARY = 'xul'
|
||||
LOCAL_INCLUDES += [
|
||||
'/media/webrtc/trunk/webrtc/modules/video_capture/windows',
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
DEFINES['NOMINMAX'] = True
|
||||
|
@ -23,8 +23,5 @@ FINAL_LIBRARY = 'xul'
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
DEFINES['NOMINMAX'] = True
|
||||
|
||||
if CONFIG['MOZ_GONK_MEDIACODEC']:
|
||||
DEFINES['MOZ_GONK_MEDIACODEC'] = True
|
||||
|
@ -177,6 +177,16 @@ public:
|
||||
(*aData)[3] == 0x6b) {
|
||||
return true;
|
||||
}
|
||||
// 0xa3 // SimpleBlock
|
||||
if (aData->Length() >= 1 &&
|
||||
(*aData)[0] == 0xa3) {
|
||||
return true;
|
||||
}
|
||||
// 0xa1 // Block
|
||||
if (aData->Length() >= 1 &&
|
||||
(*aData)[0] == 0xa1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -99,8 +99,7 @@ IsTypeSupported(const nsAString& aType)
|
||||
}
|
||||
return NS_OK;
|
||||
} else if (DecoderTraits::IsWebMType(mimeTypeUTF8)) {
|
||||
if (!Preferences::GetBool("media.mediasource.webm.enabled", false) ||
|
||||
Preferences::GetBool("media.mediasource.format-reader", false)) {
|
||||
if (!Preferences::GetBool("media.mediasource.webm.enabled", false)) {
|
||||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||
}
|
||||
if (hasCodecs &&
|
||||
|
@ -23,6 +23,3 @@ include('/ipc/chromium/chromium-config.mozbuild')
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
DEFINES['NOMINMAX'] = True
|
||||
|
@ -82,6 +82,3 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
DEFINES['NOMINMAX'] = True
|
||||
|
@ -31,9 +31,6 @@ include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
DEFINES['NOMINMAX'] = True
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
|
||||
|
@ -133,47 +133,6 @@ public:
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// Inverse-transform the FFTSize()/2+1 points of data in each
|
||||
// of aRealDataIn and aImagDataIn and store the resulting
|
||||
// FFTSize() points in aRealDataOut.
|
||||
void PerformInverseFFT(float* aRealDataIn,
|
||||
float *aImagDataIn,
|
||||
float *aRealDataOut)
|
||||
{
|
||||
EnsureIFFT();
|
||||
const uint32_t inputSize = mFFTSize / 2 + 1;
|
||||
#if defined(MOZ_LIBAV_FFT)
|
||||
AlignedTArray<FFTSample> inputBuffer(inputSize * 2);
|
||||
for (uint32_t i = 0; i < inputSize; ++i) {
|
||||
inputBuffer[2*i] = aRealDataIn[i];
|
||||
inputBuffer[(2*i)+1] = aImagDataIn[i];
|
||||
}
|
||||
av_rdft_calc(mAvIRDFT, inputBuffer.Elements());
|
||||
PodCopy(aRealDataOut, inputBuffer.Elements(), FFTSize());
|
||||
// TODO: Once bug 877662 lands, change this to use SSE.
|
||||
for (uint32_t i = 0; i < mFFTSize; ++i) {
|
||||
aRealDataOut[i] /= mFFTSize;
|
||||
}
|
||||
#else
|
||||
AlignedTArray<ComplexU> inputBuffer(inputSize);
|
||||
for (uint32_t i = 0; i < inputSize; ++i) {
|
||||
inputBuffer[i].r = aRealDataIn[i];
|
||||
inputBuffer[i].i = aImagDataIn[i];
|
||||
}
|
||||
#if defined(BUILD_ARM_NEON)
|
||||
if (mozilla::supports_neon()) {
|
||||
omxSP_FFTInv_CCSToR_F32_Sfs(inputBuffer.Elements()->f,
|
||||
aRealDataOut, mOmxIFFT);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
kiss_fftri(mKissIFFT, &(inputBuffer.Elements()->c), aRealDataOut);
|
||||
for (uint32_t i = 0; i < mFFTSize; ++i) {
|
||||
aRealDataOut[i] /= mFFTSize;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Multiply(const FFTBlock& aFrame)
|
||||
{
|
||||
@ -217,10 +176,18 @@ public:
|
||||
{
|
||||
return mOutputBuffer[aIndex].r;
|
||||
}
|
||||
float& RealData(uint32_t aIndex)
|
||||
{
|
||||
return mOutputBuffer[aIndex].r;
|
||||
}
|
||||
float ImagData(uint32_t aIndex) const
|
||||
{
|
||||
return mOutputBuffer[aIndex].i;
|
||||
}
|
||||
float& ImagData(uint32_t aIndex)
|
||||
{
|
||||
return mOutputBuffer[aIndex].i;
|
||||
}
|
||||
|
||||
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
|
@ -178,9 +178,11 @@ void PeriodicWave::createBandLimitedTables(const float* realData, const float* i
|
||||
float normalizationScale = 1;
|
||||
|
||||
unsigned fftSize = m_periodicWaveSize;
|
||||
unsigned halfSize = fftSize / 2 + 1;
|
||||
unsigned halfSize = fftSize / 2;
|
||||
unsigned i;
|
||||
|
||||
// Limit the number of components used to those for frequencies below the
|
||||
// Nyquist of the fixed length inverse FFT.
|
||||
numberOfComponents = std::min(numberOfComponents, halfSize);
|
||||
|
||||
m_bandLimitedTables.SetCapacity(m_numberOfRanges);
|
||||
@ -188,46 +190,27 @@ void PeriodicWave::createBandLimitedTables(const float* realData, const float* i
|
||||
for (unsigned rangeIndex = 0; rangeIndex < m_numberOfRanges; ++rangeIndex) {
|
||||
// This FFTBlock is used to cull partials (represented by frequency bins).
|
||||
FFTBlock frame(fftSize);
|
||||
nsAutoArrayPtr<float> realP(new float[halfSize]);
|
||||
nsAutoArrayPtr<float> imagP(new float[halfSize]);
|
||||
|
||||
// Copy from loaded frequency data and scale.
|
||||
float scale = fftSize;
|
||||
AudioBufferCopyWithScale(realData, scale, realP, numberOfComponents);
|
||||
AudioBufferCopyWithScale(imagData, scale, imagP, numberOfComponents);
|
||||
|
||||
// If fewer components were provided than 1/2 FFT size,
|
||||
// then clear the remaining bins.
|
||||
for (i = numberOfComponents; i < halfSize; ++i) {
|
||||
realP[i] = 0;
|
||||
imagP[i] = 0;
|
||||
}
|
||||
|
||||
// Generate complex conjugate because of the way the
|
||||
// inverse FFT is defined.
|
||||
float minusOne = -1;
|
||||
AudioBufferInPlaceScale(imagP, minusOne, halfSize);
|
||||
|
||||
// Find the starting bin where we should start culling.
|
||||
// We need to clear out the highest frequencies to band-limit
|
||||
// the waveform.
|
||||
// Find the starting bin where we should start culling the aliasing
|
||||
// partials for this pitch range. We need to clear out the highest
|
||||
// frequencies to band-limit the waveform.
|
||||
unsigned numberOfPartials = numberOfPartialsForRange(rangeIndex);
|
||||
// Also limit to the number of components that are provided.
|
||||
numberOfPartials = std::min(numberOfPartials, numberOfComponents - 1);
|
||||
|
||||
// Cull the aliasing partials for this pitch range.
|
||||
for (i = numberOfPartials + 1; i < halfSize; ++i) {
|
||||
realP[i] = 0;
|
||||
imagP[i] = 0;
|
||||
// Copy from loaded frequency data and generate complex conjugate
|
||||
// because of the way the inverse FFT is defined.
|
||||
// The coefficients of higher partials remain zero, as initialized in
|
||||
// the FFTBlock constructor.
|
||||
for (i = 0; i < numberOfPartials + 1; ++i) {
|
||||
frame.RealData(i) = realData[i];
|
||||
frame.ImagData(i) = -imagData[i];
|
||||
}
|
||||
// Clear nyquist if necessary.
|
||||
if (numberOfPartials < halfSize)
|
||||
realP[halfSize-1] = 0;
|
||||
|
||||
// Clear any DC-offset.
|
||||
realP[0] = 0;
|
||||
|
||||
// Clear values which have no effect.
|
||||
imagP[0] = 0;
|
||||
imagP[halfSize-1] = 0;
|
||||
frame.RealData(0) = 0;
|
||||
// Clear value which has no effect.
|
||||
frame.ImagData(0) = 0;
|
||||
|
||||
// Create the band-limited table.
|
||||
AlignedAudioFloatArray* table = new AlignedAudioFloatArray(m_periodicWaveSize);
|
||||
@ -235,7 +218,7 @@ void PeriodicWave::createBandLimitedTables(const float* realData, const float* i
|
||||
|
||||
// Apply an inverse FFT to generate the time-domain table data.
|
||||
float* data = m_bandLimitedTables[rangeIndex]->Elements();
|
||||
frame.PerformInverseFFT(realP, imagP, data);
|
||||
frame.GetInverseWithoutScaling(data);
|
||||
|
||||
// For the first range (which has the highest power), calculate
|
||||
// its peak value then compute normalization scale.
|
||||
@ -256,18 +239,16 @@ void PeriodicWave::generateBasicWaveform(OscillatorType shape)
|
||||
{
|
||||
const float piFloat = M_PI;
|
||||
unsigned fftSize = periodicWaveSize();
|
||||
unsigned halfSize = fftSize / 2 + 1;
|
||||
unsigned halfSize = fftSize / 2;
|
||||
|
||||
AudioFloatArray real(halfSize);
|
||||
AudioFloatArray imag(halfSize);
|
||||
float* realP = real.Elements();
|
||||
float* imagP = imag.Elements();
|
||||
|
||||
// Clear DC and Nyquist.
|
||||
// Clear DC and imag value which is ignored.
|
||||
realP[0] = 0;
|
||||
imagP[0] = 0;
|
||||
realP[halfSize-1] = 0;
|
||||
imagP[halfSize-1] = 0;
|
||||
|
||||
for (unsigned n = 1; n < halfSize; ++n) {
|
||||
float omega = 2 * piFloat * n;
|
||||
|
@ -83,9 +83,6 @@ if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']:
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
DEFINES['NOMINMAX'] = True
|
||||
|
||||
|
||||
if CONFIG['_MSC_VER']:
|
||||
CXXFLAGS += [
|
||||
|
@ -696,8 +696,8 @@ Notification::Notification(nsIGlobalObject* aGlobal, const nsAString& aID,
|
||||
: DOMEventTargetHelper(),
|
||||
mWorkerPrivate(nullptr), mObserver(nullptr),
|
||||
mID(aID), mTitle(aTitle), mBody(aBody), mDir(aDir), mLang(aLang),
|
||||
mTag(aTag), mIconUrl(aIconUrl), mBehavior(aBehavior), mIsClosed(false),
|
||||
mIsStored(false), mTaskCount(0)
|
||||
mTag(aTag), mIconUrl(aIconUrl), mBehavior(aBehavior), mData(JS::NullValue()),
|
||||
mIsClosed(false), mIsStored(false), mTaskCount(0)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
// We can only call this on the main thread because
|
||||
@ -827,13 +827,6 @@ Notification::PersistNotification()
|
||||
nsString alertName;
|
||||
GetAlertName(alertName);
|
||||
|
||||
nsString dataString;
|
||||
nsCOMPtr<nsIStructuredCloneContainer> scContainer;
|
||||
scContainer = GetDataCloneContainer();
|
||||
if (scContainer) {
|
||||
scContainer->GetDataAsBase64(dataString);
|
||||
}
|
||||
|
||||
nsAutoString behavior;
|
||||
if (!mBehavior.ToJSON(behavior)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -848,7 +841,7 @@ Notification::PersistNotification()
|
||||
mTag,
|
||||
mIconUrl,
|
||||
alertName,
|
||||
dataString,
|
||||
mDataAsBase64,
|
||||
behavior,
|
||||
mScope);
|
||||
|
||||
@ -913,6 +906,8 @@ Notification::CreateInternal(nsIGlobalObject* aGlobal,
|
||||
|
||||
Notification::~Notification()
|
||||
{
|
||||
mData.setUndefined();
|
||||
mozilla::DropJSObjects(this);
|
||||
AssertIsOnTargetThread();
|
||||
MOZ_ASSERT(!mFeature);
|
||||
MOZ_ASSERT(!mTempRef);
|
||||
@ -920,15 +915,16 @@ Notification::~Notification()
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(Notification)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(Notification, DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mData)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDataObjectContainer)
|
||||
tmp->mData.setUndefined();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Notification, DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mData)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDataObjectContainer)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(Notification, DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mData);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(Notification, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(Notification, DOMEventTargetHelper)
|
||||
|
||||
@ -1394,13 +1390,6 @@ Notification::ShowInternal()
|
||||
}
|
||||
MOZ_ASSERT(observer);
|
||||
|
||||
// mDataObjectContainer might be uninitialized here because the notification
|
||||
// was constructed with an undefined data property.
|
||||
nsString dataStr;
|
||||
if (mDataObjectContainer) {
|
||||
mDataObjectContainer->GetDataAsBase64(dataStr);
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G
|
||||
nsCOMPtr<nsIAppNotificationService> appNotifier =
|
||||
do_GetService("@mozilla.org/system-alerts-service;1");
|
||||
@ -1428,7 +1417,7 @@ Notification::ShowInternal()
|
||||
ops.mDir = DirectionToString(mDir);
|
||||
ops.mLang = mLang;
|
||||
ops.mTag = mTag;
|
||||
ops.mData = dataStr;
|
||||
ops.mData = mDataAsBase64;
|
||||
ops.mMozbehavior = mBehavior;
|
||||
ops.mMozbehavior.mSoundFile = soundUrl;
|
||||
|
||||
@ -1471,7 +1460,7 @@ Notification::ShowInternal()
|
||||
alertService->ShowAlertNotification(iconUrl, mTitle, mBody, true,
|
||||
uniqueCookie, observer, alertName,
|
||||
DirectionToString(mDir), mLang,
|
||||
dataStr, GetPrincipal(),
|
||||
mDataAsBase64, GetPrincipal(),
|
||||
inPrivateBrowsing);
|
||||
}
|
||||
|
||||
@ -1977,52 +1966,76 @@ Notification::GetOrigin(nsIPrincipal* aPrincipal, nsString& aOrigin)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIStructuredCloneContainer* Notification::GetDataCloneContainer()
|
||||
{
|
||||
return mDataObjectContainer;
|
||||
}
|
||||
|
||||
void
|
||||
Notification::GetData(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aRetval)
|
||||
{
|
||||
if (!mData && mDataObjectContainer) {
|
||||
if (mData.isNull() && !mDataAsBase64.IsEmpty()) {
|
||||
nsresult rv;
|
||||
rv = mDataObjectContainer->DeserializeToVariant(aCx, getter_AddRefs(mData));
|
||||
nsRefPtr<nsStructuredCloneContainer> container =
|
||||
new nsStructuredCloneContainer();
|
||||
rv = container->InitFromBase64(mDataAsBase64, JS_STRUCTURED_CLONE_VERSION,
|
||||
aCx);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRetval.setNull();
|
||||
return;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> data(aCx);
|
||||
rv = container->DeserializeToJsval(aCx, &data);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRetval.setNull();
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.isGCThing()) {
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
mData = data;
|
||||
}
|
||||
if (!mData) {
|
||||
if (mData.isNull()) {
|
||||
aRetval.setNull();
|
||||
return;
|
||||
}
|
||||
VariantToJsval(aCx, mData, aRetval);
|
||||
|
||||
JS::ExposeValueToActiveJS(mData);
|
||||
aRetval.set(mData);
|
||||
}
|
||||
|
||||
void
|
||||
Notification::InitFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aData,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (mDataObjectContainer || aData.isNull()) {
|
||||
if (!mDataAsBase64.IsEmpty() || aData.isNull()) {
|
||||
return;
|
||||
}
|
||||
mDataObjectContainer = new nsStructuredCloneContainer();
|
||||
aRv = mDataObjectContainer->InitFromJSVal(aData, aCx);
|
||||
nsRefPtr<nsStructuredCloneContainer> dataObjectContainer =
|
||||
new nsStructuredCloneContainer();
|
||||
aRv = dataObjectContainer->InitFromJSVal(aData, aCx);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
dataObjectContainer->GetDataAsBase64(mDataAsBase64);
|
||||
}
|
||||
|
||||
void Notification::InitFromBase64(JSContext* aCx, const nsAString& aData,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (mDataObjectContainer || aData.IsEmpty()) {
|
||||
if (!mDataAsBase64.IsEmpty() || aData.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto container = new nsStructuredCloneContainer();
|
||||
// To and fro to ensure it is valid base64.
|
||||
nsRefPtr<nsStructuredCloneContainer> container =
|
||||
new nsStructuredCloneContainer();
|
||||
aRv = container->InitFromBase64(aData, JS_STRUCTURED_CLONE_VERSION,
|
||||
aCx);
|
||||
mDataObjectContainer = container;
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
container->GetDataAsBase64(mDataAsBase64);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
class nsIPrincipal;
|
||||
class nsIStructuredCloneContainer;
|
||||
class nsIVariant;
|
||||
|
||||
namespace mozilla {
|
||||
@ -126,7 +125,7 @@ public:
|
||||
IMPL_EVENT_HANDLER(close)
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Notification, DOMEventTargetHelper)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(Notification, DOMEventTargetHelper)
|
||||
|
||||
static bool PrefEnabled(JSContext* aCx, JSObject* aObj);
|
||||
// Returns if Notification.get() is allowed for the current global.
|
||||
@ -205,8 +204,6 @@ public:
|
||||
return mIsStored;
|
||||
}
|
||||
|
||||
nsIStructuredCloneContainer* GetDataCloneContainer();
|
||||
|
||||
static bool RequestPermissionEnabledForScope(JSContext* aCx, JSObject* /* unused */);
|
||||
|
||||
static void RequestPermission(const GlobalObject& aGlobal,
|
||||
@ -359,11 +356,11 @@ protected:
|
||||
const nsString mLang;
|
||||
const nsString mTag;
|
||||
const nsString mIconUrl;
|
||||
nsCOMPtr<nsIStructuredCloneContainer> mDataObjectContainer;
|
||||
nsString mDataAsBase64;
|
||||
const NotificationBehavior mBehavior;
|
||||
|
||||
// It's null until GetData is first called
|
||||
nsCOMPtr<nsIVariant> mData;
|
||||
JS::Heap<JS::Value> mData;
|
||||
|
||||
nsString mAlertName;
|
||||
nsString mScope;
|
||||
|
@ -154,6 +154,36 @@ this.PushDB.prototype = {
|
||||
);
|
||||
},
|
||||
|
||||
// testFn(record) is called with a database record and should return true if
|
||||
// that record should be deleted.
|
||||
clearIf: function(testFn) {
|
||||
debug("clearIf()");
|
||||
return new Promise((resolve, reject) =>
|
||||
this.newTxn(
|
||||
"readwrite",
|
||||
this._dbStoreName,
|
||||
(aTxn, aStore) => {
|
||||
aTxn.result = undefined;
|
||||
|
||||
aStore.openCursor().onsuccess = event => {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (testFn(this.toPushRecord(cursor.value))) {
|
||||
let deleteRequest = cursor.delete();
|
||||
deleteRequest.onerror = e => {
|
||||
debug("Failed to delete entry even when test succeeded!");
|
||||
}
|
||||
}
|
||||
cursor.continue();
|
||||
}
|
||||
}
|
||||
},
|
||||
resolve,
|
||||
reject
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
getByPushEndpoint: function(aPushEndpoint) {
|
||||
debug("getByPushEndpoint()");
|
||||
|
||||
|
@ -58,6 +58,10 @@ PushNotificationService.prototype = {
|
||||
return PushService._clearAll();
|
||||
},
|
||||
|
||||
clearForDomain: function(domain) {
|
||||
return PushService._clearForDomain(domain);
|
||||
},
|
||||
|
||||
observe: function observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "app-startup":
|
||||
|
@ -1027,7 +1027,47 @@ this.PushService = {
|
||||
_clearAll: function _clearAll() {
|
||||
return this._checkActivated()
|
||||
.then(_ => this._db.clearAll())
|
||||
.catch(_ => {
|
||||
.catch(_ => Promise.resolve());
|
||||
},
|
||||
|
||||
_clearForDomain: function(domain) {
|
||||
/**
|
||||
* Copied from ForgetAboutSite.jsm.
|
||||
*
|
||||
* Returns true if the string passed in is part of the root domain of the
|
||||
* current string. For example, if this is "www.mozilla.org", and we pass in
|
||||
* "mozilla.org", this will return true. It would return false the other way
|
||||
* around.
|
||||
*/
|
||||
function hasRootDomain(str, aDomain)
|
||||
{
|
||||
let index = str.indexOf(aDomain);
|
||||
// If aDomain is not found, we know we do not have it as a root domain.
|
||||
if (index == -1)
|
||||
return false;
|
||||
|
||||
// If the strings are the same, we obviously have a match.
|
||||
if (str == aDomain)
|
||||
return true;
|
||||
|
||||
// Otherwise, we have aDomain as our root domain iff the index of aDomain is
|
||||
// aDomain.length subtracted from our length and (since we do not have an
|
||||
// exact match) the character before the index is a dot or slash.
|
||||
let prevChar = str[index - 1];
|
||||
return (index == (str.length - aDomain.length)) &&
|
||||
(prevChar == "." || prevChar == "/");
|
||||
}
|
||||
|
||||
let clear = (db, domain) => {
|
||||
db.clearIf(record => {
|
||||
return hasRootDomain(record.origin, domain);
|
||||
});
|
||||
}
|
||||
|
||||
return this._checkActivated()
|
||||
.then(_ => clear(this._db, domain))
|
||||
.catch(e => {
|
||||
debug("Error forgetting about domain! " + e);
|
||||
return Promise.resolve();
|
||||
});
|
||||
},
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
let {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
|
@ -538,14 +538,8 @@ nsCORSListenerProxy::CheckRequestApproved(nsIRequest* aRequest)
|
||||
// Check if the request failed
|
||||
nsresult status;
|
||||
nsresult rv = aRequest->GetStatus(&status);
|
||||
if (NS_FAILED(rv)) {
|
||||
LogBlockedRequest(aRequest, "CORSRequestFailed", nullptr);
|
||||
return rv;
|
||||
}
|
||||
if (NS_FAILED(status)) {
|
||||
LogBlockedRequest(aRequest, "CORSRequestFailed", nullptr);
|
||||
return status;
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_SUCCESS(status, status);
|
||||
|
||||
// Test that things worked on a HTTP level
|
||||
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aRequest);
|
||||
|
@ -20,7 +20,9 @@ if (self.Notification) {
|
||||
lang: "",
|
||||
body: "This is a notification body",
|
||||
tag: "sometag",
|
||||
icon: "icon.png"
|
||||
icon: "icon.png",
|
||||
data: ["a complex object that should be", { "structured": "cloned" }],
|
||||
mozbehavior: { vibrationPattern: [30, 200, 30] },
|
||||
};
|
||||
var notification = new Notification("This is a title", options);
|
||||
|
||||
@ -36,6 +38,8 @@ if (self.Notification) {
|
||||
is(notification.body, options.body, "body should get set");
|
||||
is(notification.tag, options.tag, "tag should get set");
|
||||
is(notification.icon, options.icon, "icon should get set");
|
||||
is(notification.data[0], "a complex object that should be", "data item 0 should be a matching string");
|
||||
is(notification.data[1]["structured"], "cloned", "data item 1 should be a matching object literal");
|
||||
|
||||
// store notification in test context
|
||||
this.notification = notification;
|
||||
|
@ -13,11 +13,11 @@
|
||||
}
|
||||
|
||||
navigator.serviceWorker.ready.then(function(swr) {
|
||||
swr.showNotification("Hi there. The ServiceWorker should receive a click event for this.");
|
||||
swr.showNotification("Hi there. The ServiceWorker should receive a click event for this.", { data: { complex: ["jsval", 5] }});
|
||||
});
|
||||
|
||||
navigator.serviceWorker.onmessage = function(msg) {
|
||||
testWindow.callback();
|
||||
testWindow.callback(msg.data.result);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -9,7 +9,11 @@ onnotificationclick = function(e) {
|
||||
}
|
||||
|
||||
clients.forEach(function(client) {
|
||||
client.postMessage("done");
|
||||
client.postMessage({ result: e.notification.data &&
|
||||
e.notification.data['complex'] &&
|
||||
e.notification.data['complex'][0] == "jsval" &&
|
||||
e.notification.data['complex'][1] == 5 });
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -23,11 +23,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=916893
|
||||
function testFrame(src) {
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.src = src;
|
||||
window.callback = function() {
|
||||
window.callback = function(result) {
|
||||
window.callback = null;
|
||||
document.body.removeChild(iframe);
|
||||
iframe = null;
|
||||
ok(true, "Got notificationclick event.");
|
||||
ok(result, "Got notificationclick event with correct data.");
|
||||
MockServices.unregister();
|
||||
SimpleTest.finish();
|
||||
};
|
||||
|
@ -20,8 +20,6 @@ WIN_LIBS= \
|
||||
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
#define NOMINMAX 1
|
||||
|
||||
#include "plstr.h"
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
|
@ -98,7 +98,6 @@ if CONFIG['GNU_CXX']:
|
||||
if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
|
||||
CXXFLAGS += ['-I\'%s/include/\'' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
|
||||
|
||||
DEFINES['NOMINMAX'] = True
|
||||
DEFINES['_CRT_SECURE_NO_DEPRECATE'] = True
|
||||
DEFINES['_HAS_EXCEPTIONS'] = 0
|
||||
|
||||
|
@ -30,7 +30,6 @@ if CONFIG['GNU_CXX']:
|
||||
if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
|
||||
CXXFLAGS += ['-I\'%s/include/\'' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
|
||||
|
||||
DEFINES['NOMINMAX'] = True
|
||||
DEFINES['_CRT_SECURE_NO_DEPRECATE'] = True
|
||||
DEFINES['_HAS_EXCEPTIONS'] = 0
|
||||
|
||||
|
@ -193,7 +193,6 @@ if CONFIG['GNU_CXX']:
|
||||
if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
|
||||
CXXFLAGS += ['-I\'%s/include/\'' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
|
||||
|
||||
DEFINES['NOMINMAX'] = True
|
||||
DEFINES['_CRT_SECURE_NO_DEPRECATE'] = True
|
||||
DEFINES['_HAS_EXCEPTIONS'] = 0
|
||||
|
||||
|
25
gfx/ipc/GraphicsMessages.ipdlh
Normal file
25
gfx/ipc/GraphicsMessages.ipdlh
Normal file
@ -0,0 +1,25 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* 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 gfx {
|
||||
|
||||
struct DeviceInitData
|
||||
{
|
||||
bool useAcceleration;
|
||||
|
||||
// Windows only.
|
||||
bool useD3D11;
|
||||
bool useD3D11WARP;
|
||||
bool useD3D11ImageBridge;
|
||||
bool d3d11TextureSharingWorks;
|
||||
bool useD2D;
|
||||
bool useD2D1;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
@ -26,6 +26,10 @@ SOURCES += [
|
||||
'SharedDIB.cpp',
|
||||
]
|
||||
|
||||
IPDL_SOURCES = [
|
||||
'GraphicsMessages.ipdlh',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
@ -496,17 +496,20 @@ public:
|
||||
}
|
||||
void SetCompositionTime(TimeStamp aTimeStamp) {
|
||||
mCompositionTime = aTimeStamp;
|
||||
mCompositeAgainTime = TimeStamp();
|
||||
}
|
||||
|
||||
void CompositeAgainAt(TimeStamp aTimeStamp) {
|
||||
if (mCompositeAgainTime.IsNull() ||
|
||||
mCompositeAgainTime > aTimeStamp) {
|
||||
mCompositeAgainTime = aTimeStamp;
|
||||
if (!mCompositionTime.IsNull() && !mCompositeUntilTime.IsNull() &&
|
||||
mCompositionTime >= mCompositeUntilTime) {
|
||||
mCompositeUntilTime = TimeStamp();
|
||||
}
|
||||
}
|
||||
TimeStamp GetCompositeAgainTime() const {
|
||||
return mCompositeAgainTime;
|
||||
|
||||
void CompositeUntil(TimeStamp aTimeStamp) {
|
||||
if (mCompositeUntilTime.IsNull() ||
|
||||
mCompositeUntilTime < aTimeStamp) {
|
||||
mCompositeUntilTime = aTimeStamp;
|
||||
}
|
||||
}
|
||||
TimeStamp GetCompositeUntilTime() const {
|
||||
return mCompositeUntilTime;
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -529,9 +532,10 @@ protected:
|
||||
TimeStamp mCompositionTime;
|
||||
/**
|
||||
* When nonnull, during rendering, some compositable indicated that it will
|
||||
* change its rendering at this time (and this is the earliest such time).
|
||||
* change its rendering at this time. In order not to miss it, we composite
|
||||
* on every vsync until this time occurs (this is the latest such time).
|
||||
*/
|
||||
TimeStamp mCompositeAgainTime;
|
||||
TimeStamp mCompositeUntilTime;
|
||||
|
||||
uint32_t mCompositorID;
|
||||
DiagnosticTypes mDiagnosticTypes;
|
||||
|
@ -152,11 +152,7 @@ already_AddRefed<PaintedLayer>
|
||||
ClientLayerManager::CreatePaintedLayerWithHint(PaintedLayerCreationHint aHint)
|
||||
{
|
||||
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
|
||||
if (
|
||||
#ifdef MOZ_B2G
|
||||
aHint == SCROLLABLE &&
|
||||
#endif
|
||||
gfxPrefs::LayersTilesEnabled()
|
||||
if (gfxPrefs::LayersTilesEnabled()
|
||||
#ifndef MOZ_X11
|
||||
&& (AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_OPENGL ||
|
||||
AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_D3D9 ||
|
||||
|
@ -69,15 +69,6 @@ public:
|
||||
|
||||
virtual void RenderLayerWithReadback(ReadbackProcessor *aReadback) override;
|
||||
|
||||
virtual bool IsOptimizedFor(LayerManager::PaintedLayerCreationHint aCreationHint) override
|
||||
{
|
||||
#ifdef MOZ_B2G
|
||||
return aCreationHint == GetCreationHint();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void ClearCachedResources() override
|
||||
{
|
||||
if (mContentClient) {
|
||||
|
@ -186,7 +186,7 @@ ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
|
||||
|
||||
// Mark the area we just drew into the back buffer as invalid in the front buffer as they're
|
||||
// now out of sync.
|
||||
mTile.mInvalidFront.OrWith(paintRegion);
|
||||
mTile.mInvalidFront.OrWith(tileDirtyRegion);
|
||||
|
||||
// The new buffer is now validated, remove the dirty region from it.
|
||||
mTile.mInvalidBack.SubOut(tileDirtyRegion);
|
||||
|
@ -19,6 +19,8 @@
|
||||
|
||||
class nsIntRegion;
|
||||
|
||||
#define BIAS_TIME_MS 1.0
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
class Matrix4x4;
|
||||
@ -102,6 +104,22 @@ ImageHost::UseTextureHost(const nsTArray<TimedTexture>& aTextures)
|
||||
img.mFrontBuffer->PrepareTextureSource(img.mTextureSource);
|
||||
}
|
||||
mImages.SwapElements(newImages);
|
||||
|
||||
// Video producers generally send replacement images with the same frameID but
|
||||
// slightly different timestamps in order to sync with the audio clock. This
|
||||
// means that any CompositeUntil() call we made in Composite() may no longer
|
||||
// guarantee that we'll composite until the next frame is ready. Fix that here.
|
||||
if (GetCompositor() && mLastFrameID >= 0) {
|
||||
for (size_t i = 0; i < mImages.Length(); ++i) {
|
||||
bool frameComesAfter = mImages[i].mFrameID > mLastFrameID ||
|
||||
mImages[i].mProducerID != mLastProducerID;
|
||||
if (frameComesAfter && !mImages[i].mTimeStamp.IsNull()) {
|
||||
GetCompositor()->CompositeUntil(mImages[i].mTimeStamp +
|
||||
TimeDuration::FromMilliseconds(BIAS_TIME_MS));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -124,9 +142,9 @@ GetBiasedTime(const TimeStamp& aInput, ImageHost::Bias aBias)
|
||||
{
|
||||
switch (aBias) {
|
||||
case ImageHost::BIAS_NEGATIVE:
|
||||
return aInput - TimeDuration::FromMilliseconds(1.0);
|
||||
return aInput - TimeDuration::FromMilliseconds(BIAS_TIME_MS);
|
||||
case ImageHost::BIAS_POSITIVE:
|
||||
return aInput + TimeDuration::FromMilliseconds(1.0);
|
||||
return aInput + TimeDuration::FromMilliseconds(BIAS_TIME_MS);
|
||||
default:
|
||||
return aInput;
|
||||
}
|
||||
@ -257,7 +275,7 @@ ImageHost::Composite(LayerComposite* aLayer,
|
||||
}
|
||||
|
||||
if (uint32_t(imageIndex) + 1 < mImages.Length()) {
|
||||
GetCompositor()->CompositeAgainAt(mImages[imageIndex + 1].mTimeStamp);
|
||||
GetCompositor()->CompositeUntil(mImages[imageIndex + 1].mTimeStamp + TimeDuration::FromMilliseconds(BIAS_TIME_MS));
|
||||
}
|
||||
|
||||
TimedImage* img = &mImages[imageIndex];
|
||||
|
@ -195,14 +195,17 @@ public:
|
||||
TextureHost* host = mTiledBuffer.GetTile(0).mTextureHost;
|
||||
if (host) {
|
||||
MOZ_ASSERT(!mTiledBuffer.GetTile(0).mTextureHostOnWhite, "Component alpha not supported!");
|
||||
LayerRenderState state = host->GetRenderState();
|
||||
|
||||
// Offset by the distance between the start of the valid (visible) region and the top-left
|
||||
// of the tile.
|
||||
gfx::IntPoint offset = mTiledBuffer.GetTileOffset(mTiledBuffer.GetPlacement().TilePosition(0));
|
||||
|
||||
state.SetOffset(offset - GetValidRegion().GetBounds().TopLeft());
|
||||
return host->GetRenderState();
|
||||
// Don't try to use HWC if the content doesn't start at the top-left of the tile.
|
||||
if (offset != GetValidRegion().GetBounds().TopLeft()) {
|
||||
return LayerRenderState();
|
||||
}
|
||||
|
||||
LayerRenderState state = host->GetRenderState();
|
||||
state.SetOffset(offset);
|
||||
return state;
|
||||
}
|
||||
}
|
||||
return LayerRenderState();
|
||||
|
@ -1180,8 +1180,9 @@ CompositorParent::CompositeToTarget(DrawTarget* aTarget, const gfx::IntRect* aRe
|
||||
// We're not really taking advantage of the stored composite-again-time here.
|
||||
// We might be able to skip the next few composites altogether. However,
|
||||
// that's a bit complex to implement and we'll get most of the advantage
|
||||
// by skipping compositing when we detect there's nothing invalid.
|
||||
if (!mCompositor->GetCompositeAgainTime().IsNull() ||
|
||||
// by skipping compositing when we detect there's nothing invalid. This is why
|
||||
// we do "composite until" rather than "composite again at".
|
||||
if (!mCompositor->GetCompositeUntilTime().IsNull() ||
|
||||
mLayerManager->DebugOverlayWantsNextFrame()) {
|
||||
ScheduleComposition();
|
||||
}
|
||||
|
@ -54,7 +54,6 @@ FINAL_LIBRARY = 'gkmedias'
|
||||
|
||||
DEFINES['PACKAGE_VERSION'] = '"moz"'
|
||||
DEFINES['PACKAGE_BUGREPORT'] = '"http://bugzilla.mozilla.org/"'
|
||||
DEFINES['NOMINMAX'] = True
|
||||
|
||||
if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
|
||||
DEFINES['OTS_DLL'] = True
|
||||
|
@ -111,6 +111,8 @@ class mozilla::gl::SkiaGLGlue : public GenericAtomicRefCounted {
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "VsyncSource.h"
|
||||
#include "SoftwareVsyncSource.h"
|
||||
#include "nscore.h" // for NS_FREE_PERMANENT_DATA
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
@ -259,7 +261,7 @@ void CrashStatsLogForwarder::UpdateCrashReport()
|
||||
mCrashCriticalKey.get(), message.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CrashStatsLogForwarder::Log(const std::string& aString)
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
@ -645,7 +647,7 @@ gfxPlatform::Shutdown()
|
||||
#endif
|
||||
|
||||
// This is a bit iffy - we're assuming that we were the ones that set the
|
||||
// log forwarder in the Factory, so that it's our responsibility to
|
||||
// log forwarder in the Factory, so that it's our responsibility to
|
||||
// delete it.
|
||||
delete mozilla::gfx::Factory::GetLogForwarder();
|
||||
mozilla::gfx::Factory::SetLogForwarder(nullptr);
|
||||
@ -714,7 +716,7 @@ gfxPlatform::~gfxPlatform()
|
||||
// cairo_debug_* function unconditionally.
|
||||
//
|
||||
// because cairo can assert and thus crash on shutdown, don't do this in release builds
|
||||
#if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) || defined(MOZ_VALGRIND)
|
||||
#ifdef NS_FREE_PERMANENT_DATA
|
||||
#ifdef USE_SKIA
|
||||
// must do Skia cleanup before Cairo cleanup, because Skia may be referencing
|
||||
// Cairo objects e.g. through SkCairoFTTypeface
|
||||
@ -1201,7 +1203,7 @@ gfxPlatform::CreateDrawTargetForData(unsigned char* aData, const IntSize& aSize,
|
||||
NS_ASSERTION(mContentBackend != BackendType::NONE, "No backend.");
|
||||
|
||||
BackendType backendType = mContentBackend;
|
||||
|
||||
|
||||
if (!Factory::DoesBackendSupportDataDrawtarget(mContentBackend)) {
|
||||
backendType = BackendType::CAIRO;
|
||||
}
|
||||
@ -2487,3 +2489,24 @@ gfxPlatform::NotifyCompositorCreated(LayersBackend aBackend)
|
||||
obsvc->NotifyObservers(nullptr, "compositor:created", nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatform::GetDeviceInitData(mozilla::gfx::DeviceInitData* aOut)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
aOut->useAcceleration() = ShouldUseLayersAcceleration();
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatform::UpdateDeviceInitData()
|
||||
{
|
||||
if (XRE_IsParentProcess()) {
|
||||
// The parent process figures out device initialization on its own.
|
||||
return;
|
||||
}
|
||||
|
||||
mozilla::gfx::DeviceInitData data;
|
||||
mozilla::dom::ContentChild::GetSingleton()->SendGetGraphicsDeviceInitData(&data);
|
||||
|
||||
SetDeviceInitData(data);
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ class DataSourceSurface;
|
||||
class ScaledFont;
|
||||
class DrawEventRecorder;
|
||||
class VsyncSource;
|
||||
class DeviceInitData;
|
||||
|
||||
inline uint32_t
|
||||
BackendTypeBit(BackendType b)
|
||||
@ -485,7 +486,8 @@ public:
|
||||
virtual bool CanUseHardwareVideoDecoding();
|
||||
static bool CanUseDirect3D11ANGLE();
|
||||
|
||||
// Returns whether or not layers acceleration should be used.
|
||||
// Returns whether or not layers acceleration should be used. This should
|
||||
// only be called on the parent process.
|
||||
bool ShouldUseLayersAcceleration();
|
||||
|
||||
// Returns a prioritized list of all available compositor backends.
|
||||
@ -646,6 +648,10 @@ public:
|
||||
virtual void TestDeviceReset(DeviceResetReason aReason)
|
||||
{}
|
||||
|
||||
// Return information on how child processes should initialize graphics
|
||||
// devices. Currently this is only used on Windows.
|
||||
virtual void GetDeviceInitData(mozilla::gfx::DeviceInitData* aOut);
|
||||
|
||||
protected:
|
||||
gfxPlatform();
|
||||
virtual ~gfxPlatform();
|
||||
@ -678,6 +684,17 @@ protected:
|
||||
void InitBackendPrefs(uint32_t aCanvasBitmask, mozilla::gfx::BackendType aCanvasDefault,
|
||||
uint32_t aContentBitmask, mozilla::gfx::BackendType aContentDefault);
|
||||
|
||||
/**
|
||||
* If in a child process, triggers a refresh of device preferences.
|
||||
*/
|
||||
void UpdateDeviceInitData();
|
||||
|
||||
/**
|
||||
* Called when new device preferences are available.
|
||||
*/
|
||||
virtual void SetDeviceInitData(mozilla::gfx::DeviceInitData& aData)
|
||||
{}
|
||||
|
||||
/**
|
||||
* returns the first backend named in the pref gfx.canvas.azure.backends
|
||||
* which is a component of aBackendBitmask, a bitmask of backend types
|
||||
|
@ -373,6 +373,16 @@ public:
|
||||
|
||||
NS_IMPL_ISUPPORTS(D3D9SharedTextureReporter, nsIMemoryReporter)
|
||||
|
||||
// Device init data should only be used on child processes, so we protect it
|
||||
// behind a getter here.
|
||||
static DeviceInitData sDeviceInitDataDoNotUseDirectly;
|
||||
static inline DeviceInitData&
|
||||
GetParentDevicePrefs()
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsContentProcess());
|
||||
return sDeviceInitDataDoNotUseDirectly;
|
||||
}
|
||||
|
||||
gfxWindowsPlatform::gfxWindowsPlatform()
|
||||
: mRenderMode(RENDER_GDI)
|
||||
, mIsWARP(false)
|
||||
@ -403,6 +413,7 @@ gfxWindowsPlatform::gfxWindowsPlatform()
|
||||
mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_10_0);
|
||||
mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_9_3);
|
||||
|
||||
UpdateDeviceInitData();
|
||||
InitializeDevices();
|
||||
UpdateRenderMode();
|
||||
|
||||
@ -518,6 +529,9 @@ gfxWindowsPlatform::HandleDeviceReset()
|
||||
imgLoader::Singleton()->ClearCache(false);
|
||||
gfxAlphaBoxBlur::ShutdownBlurCache();
|
||||
|
||||
// Since we got a device reset, we must ask the parent process for an updated
|
||||
// list of which devices to create.
|
||||
UpdateDeviceInitData();
|
||||
InitializeDevices();
|
||||
return true;
|
||||
}
|
||||
@ -1900,6 +1914,12 @@ CanUseWARP()
|
||||
return true;
|
||||
}
|
||||
|
||||
// The child process can only use WARP if the parent process is also using
|
||||
// WARP.
|
||||
if (XRE_IsContentProcess()) {
|
||||
return GetParentDevicePrefs().useD3D11WARP();
|
||||
}
|
||||
|
||||
// It seems like nvdxgiwrap makes a mess of WARP. See bug 1154703.
|
||||
if (!IsWin8OrLater() ||
|
||||
gfxPrefs::LayersD3D11DisableWARP() ||
|
||||
@ -1918,6 +1938,14 @@ gfxWindowsPlatform::CheckD3D11Support(bool* aCanUseHardware)
|
||||
return mD3D11Status;
|
||||
}
|
||||
|
||||
if (XRE_IsContentProcess()) {
|
||||
if (!GetParentDevicePrefs().useD3D11()) {
|
||||
return FeatureStatus::Blocked;
|
||||
}
|
||||
*aCanUseHardware = !GetParentDevicePrefs().useD3D11WARP();
|
||||
return FeatureStatus::Available;
|
||||
}
|
||||
|
||||
if (gfxPrefs::LayersD3D11ForceWARP()) {
|
||||
*aCanUseHardware = false;
|
||||
return FeatureStatus::Available;
|
||||
@ -1982,6 +2010,12 @@ gfxWindowsPlatform::AttemptD3D11DeviceCreation()
|
||||
// Only test this when not using WARP since it can fail and cause
|
||||
// GetDeviceRemovedReason to return weird values.
|
||||
mDoesD3D11TextureSharingWork = ::DoesD3D11TextureSharingWork(mD3D11Device);
|
||||
|
||||
// Assert that the child and parent process both computed texture sharing
|
||||
// properly.
|
||||
MOZ_ASSERT_IF(XRE_IsContentProcess(),
|
||||
mDoesD3D11TextureSharingWork == GetParentDevicePrefs().d3d11TextureSharingWorks());
|
||||
|
||||
mD3D11Device->SetExceptionMode(0);
|
||||
mIsWARP = false;
|
||||
}
|
||||
@ -2078,31 +2112,31 @@ gfxWindowsPlatform::AttemptD3D11ImageBridgeDeviceCreation()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::SetDeviceInitData(mozilla::gfx::DeviceInitData& aData)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsContentProcess());
|
||||
sDeviceInitDataDoNotUseDirectly = aData;
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::InitializeDevices()
|
||||
{
|
||||
// Don't retry acceleration if it failed earlier.
|
||||
// If acceleration is disabled, we refuse to initialize anything.
|
||||
mAcceleration = CheckAccelerationSupport();
|
||||
if (IsFeatureStatusFailure(mAcceleration)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we previously crashed initializing devices, or if we're in safe mode,
|
||||
// bail out now.
|
||||
// If we previously crashed initializing devices, bail out now. This is
|
||||
// effectively a parent-process only check, since the content process
|
||||
// cannot create a lock file.
|
||||
DriverInitCrashDetection detectCrashes;
|
||||
if (detectCrashes.DisableAcceleration() || InSafeMode()) {
|
||||
if (detectCrashes.DisableAcceleration()) {
|
||||
mAcceleration = FeatureStatus::Blocked;
|
||||
return;
|
||||
}
|
||||
|
||||
// If acceleration is disabled, we refuse to initialize anything.
|
||||
if (!ShouldUseLayersAcceleration()) {
|
||||
mAcceleration = FeatureStatus::Disabled;
|
||||
return;
|
||||
}
|
||||
|
||||
// At this point, as far as we know, we can probably accelerate.
|
||||
mAcceleration = FeatureStatus::Available;
|
||||
|
||||
// If we're going to prefer D3D9, stop here. The rest of this function
|
||||
// attempts to use D3D11 features.
|
||||
if (gfxPrefs::LayersPreferD3D9()) {
|
||||
@ -2117,6 +2151,38 @@ gfxWindowsPlatform::InitializeDevices()
|
||||
}
|
||||
}
|
||||
|
||||
FeatureStatus
|
||||
gfxWindowsPlatform::CheckAccelerationSupport()
|
||||
{
|
||||
// Don't retry acceleration if it failed earlier.
|
||||
if (IsFeatureStatusFailure(mAcceleration)) {
|
||||
return mAcceleration;
|
||||
}
|
||||
if (XRE_IsContentProcess()) {
|
||||
return GetParentDevicePrefs().useAcceleration()
|
||||
? FeatureStatus::Available
|
||||
: FeatureStatus::Blocked;
|
||||
}
|
||||
if (InSafeMode()) {
|
||||
return FeatureStatus::Blocked;
|
||||
}
|
||||
if (!ShouldUseLayersAcceleration()) {
|
||||
return FeatureStatus::Disabled;
|
||||
}
|
||||
return FeatureStatus::Available;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxWindowsPlatform::CanUseD3D11ImageBridge()
|
||||
{
|
||||
if (XRE_IsContentProcess()) {
|
||||
if (!GetParentDevicePrefs().useD3D11ImageBridge()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !mIsWARP;
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::InitializeD3D11()
|
||||
{
|
||||
@ -2170,7 +2236,7 @@ gfxWindowsPlatform::InitializeD3D11()
|
||||
mD3D11Status = FeatureStatus::Available;
|
||||
MOZ_ASSERT(mD3D11Device);
|
||||
|
||||
if (!mIsWARP) {
|
||||
if (CanUseD3D11ImageBridge()) {
|
||||
AttemptD3D11ImageBridgeDeviceCreation();
|
||||
}
|
||||
|
||||
@ -2206,6 +2272,12 @@ gfxWindowsPlatform::CheckD2DSupport()
|
||||
return mD2DStatus;
|
||||
}
|
||||
|
||||
if (XRE_IsContentProcess()) {
|
||||
return GetParentDevicePrefs().useD2D()
|
||||
? FeatureStatus::Available
|
||||
: FeatureStatus::Blocked;
|
||||
}
|
||||
|
||||
if (!gfxPrefs::Direct2DForceEnabled() && IsD2DBlacklisted()) {
|
||||
return FeatureStatus::Blacklisted;
|
||||
}
|
||||
@ -2266,6 +2338,11 @@ gfxWindowsPlatform::CheckD2D1Support()
|
||||
if (!Factory::SupportsD2D1()) {
|
||||
return FeatureStatus::Unavailable;
|
||||
}
|
||||
if (XRE_IsContentProcess()) {
|
||||
return GetParentDevicePrefs().useD2D1()
|
||||
? FeatureStatus::Available
|
||||
: FeatureStatus::Blocked;
|
||||
}
|
||||
if (!gfxPrefs::Direct2DUse1_1()) {
|
||||
return FeatureStatus::Disabled;
|
||||
}
|
||||
@ -2609,3 +2686,24 @@ gfxWindowsPlatform::GetD3D11Version()
|
||||
}
|
||||
return device->GetFeatureLevel();
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::GetDeviceInitData(DeviceInitData* aOut)
|
||||
{
|
||||
// Check for device resets before giving back new graphics information.
|
||||
UpdateRenderMode();
|
||||
|
||||
gfxPlatform::GetDeviceInitData(aOut);
|
||||
|
||||
// IPDL initializes each field to false for us so we can early return.
|
||||
if (GetD3D11Status() != FeatureStatus::Available) {
|
||||
return;
|
||||
}
|
||||
|
||||
aOut->useD3D11() = true;
|
||||
aOut->useD3D11ImageBridge() = !!mD3D11ImageBridgeDevice;
|
||||
aOut->d3d11TextureSharingWorks() = mDoesD3D11TextureSharingWork;
|
||||
aOut->useD3D11WARP() = mIsWARP;
|
||||
aOut->useD2D() = (GetD2DStatus() == FeatureStatus::Available);
|
||||
aOut->useD2D1() = (GetD2D1Status() == FeatureStatus::Available);
|
||||
}
|
||||
|
@ -283,12 +283,15 @@ public:
|
||||
static mozilla::Atomic<size_t> sD3D9SurfaceImageUsed;
|
||||
static mozilla::Atomic<size_t> sD3D9SharedTextureUsed;
|
||||
|
||||
void GetDeviceInitData(mozilla::gfx::DeviceInitData* aOut) override;
|
||||
|
||||
protected:
|
||||
bool AccelerateLayersByDefault() override {
|
||||
return true;
|
||||
}
|
||||
void GetAcceleratedCompositorBackends(nsTArray<mozilla::layers::LayersBackend>& aBackends);
|
||||
virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size);
|
||||
void SetDeviceInitData(mozilla::gfx::DeviceInitData& aData) override;
|
||||
|
||||
protected:
|
||||
RenderMode mRenderMode;
|
||||
@ -307,6 +310,7 @@ private:
|
||||
|
||||
void DisableD2D();
|
||||
|
||||
mozilla::gfx::FeatureStatus CheckAccelerationSupport();
|
||||
mozilla::gfx::FeatureStatus CheckD3D11Support(bool* aCanUseHardware);
|
||||
mozilla::gfx::FeatureStatus CheckD2DSupport();
|
||||
mozilla::gfx::FeatureStatus CheckD2D1Support();
|
||||
@ -314,6 +318,7 @@ private:
|
||||
void AttemptWARPDeviceCreation();
|
||||
void AttemptD3D11ImageBridgeDeviceCreation();
|
||||
bool AttemptD3D11ContentDeviceCreation();
|
||||
bool CanUseD3D11ImageBridge();
|
||||
|
||||
IDXGIAdapter1 *GetDXGIAdapter();
|
||||
bool IsDeviceReset(HRESULT hr, DeviceResetReason* aReason);
|
||||
|
@ -96,7 +96,6 @@ public:
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mDecoder->Finish();
|
||||
mDecoder->GetImage()->FinalizeDecoder(mDecoder);
|
||||
return NS_OK;
|
||||
}
|
||||
@ -492,7 +491,6 @@ DecodePool::NotifyDecodeComplete(Decoder* aDecoder)
|
||||
return;
|
||||
}
|
||||
|
||||
aDecoder->Finish();
|
||||
aDecoder->GetImage()->FinalizeDecoder(aDecoder);
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,6 @@
|
||||
#include "DecodePool.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
@ -24,38 +22,41 @@ namespace mozilla {
|
||||
namespace image {
|
||||
|
||||
Decoder::Decoder(RasterImage* aImage)
|
||||
: mImage(aImage)
|
||||
, mProgress(NoProgress)
|
||||
, mImageData(nullptr)
|
||||
: mImageData(nullptr)
|
||||
, mImageDataLength(0)
|
||||
, mColormap(nullptr)
|
||||
, mColormapSize(0)
|
||||
, mImage(aImage)
|
||||
, mProgress(NoProgress)
|
||||
, mFrameCount(0)
|
||||
, mFailCode(NS_OK)
|
||||
, mChunkCount(0)
|
||||
, mFlags(0)
|
||||
, mBytesDecoded(0)
|
||||
, mInitialized(false)
|
||||
, mMetadataDecode(false)
|
||||
, mSendPartialInvalidations(false)
|
||||
, mImageIsTransient(false)
|
||||
, mImageIsLocked(false)
|
||||
, mFirstFrameDecode(false)
|
||||
, mInFrame(false)
|
||||
, mIsAnimated(false)
|
||||
, mDataDone(false)
|
||||
, mDecodeDone(false)
|
||||
, mDataError(false)
|
||||
, mDecodeAborted(false)
|
||||
, mShouldReportError(false)
|
||||
, mImageIsTransient(false)
|
||||
, mImageIsLocked(false)
|
||||
, mFrameCount(0)
|
||||
, mFailCode(NS_OK)
|
||||
, mInitialized(false)
|
||||
, mMetadataDecode(false)
|
||||
, mInFrame(false)
|
||||
, mIsAnimated(false)
|
||||
{ }
|
||||
|
||||
Decoder::~Decoder()
|
||||
{
|
||||
MOZ_ASSERT(mProgress == NoProgress,
|
||||
MOZ_ASSERT(mProgress == NoProgress || !mImage,
|
||||
"Destroying Decoder without taking all its progress changes");
|
||||
MOZ_ASSERT(mInvalidRect.IsEmpty(),
|
||||
MOZ_ASSERT(mInvalidRect.IsEmpty() || !mImage,
|
||||
"Destroying Decoder without taking all its invalidations");
|
||||
mInitialized = false;
|
||||
|
||||
if (!NS_IsMainThread()) {
|
||||
if (mImage && !NS_IsMainThread()) {
|
||||
// Dispatch mImage to main thread to prevent it from being destructed by the
|
||||
// decode thread.
|
||||
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
|
||||
@ -81,6 +82,11 @@ Decoder::Init()
|
||||
// No re-initializing
|
||||
MOZ_ASSERT(!mInitialized, "Can't re-initialize a decoder!");
|
||||
|
||||
// It doesn't make sense to decode anything but the first frame if we can't
|
||||
// store anything in the SurfaceCache, since only the last frame we decode
|
||||
// will be retrievable.
|
||||
MOZ_ASSERT(ShouldUseSurfaceCache() || IsFirstFrameDecode());
|
||||
|
||||
// Implementation-specific initialization
|
||||
InitInternal();
|
||||
|
||||
@ -224,50 +230,6 @@ Decoder::CompleteDecode()
|
||||
mProgress |= FLAG_HAS_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Decoder::Finish()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
MOZ_ASSERT(HasError() || !mInFrame, "Finishing while we're still in a frame");
|
||||
|
||||
// If we detected an error in CompleteDecode(), log it to the error console.
|
||||
if (mShouldReportError && !WasAborted()) {
|
||||
nsCOMPtr<nsIConsoleService> consoleService =
|
||||
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||
nsCOMPtr<nsIScriptError> errorObject =
|
||||
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
|
||||
|
||||
if (consoleService && errorObject && !HasDecoderError()) {
|
||||
nsAutoString msg(NS_LITERAL_STRING("Image corrupt or truncated."));
|
||||
nsAutoString src;
|
||||
if (mImage->GetURI()) {
|
||||
nsCString uri;
|
||||
if (mImage->GetURI()->GetSpecTruncatedTo1k(uri) == ImageURL::TruncatedTo1k) {
|
||||
msg += NS_LITERAL_STRING(" URI in this note truncated due to length.");
|
||||
}
|
||||
src = NS_ConvertUTF8toUTF16(uri);
|
||||
}
|
||||
if (NS_SUCCEEDED(errorObject->InitWithWindowID(
|
||||
msg,
|
||||
src,
|
||||
EmptyString(), 0, 0, nsIScriptError::errorFlag,
|
||||
"Image", mImage->InnerWindowID()
|
||||
))) {
|
||||
consoleService->LogMessage(errorObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set image metadata before calling DecodingComplete, because
|
||||
// DecodingComplete calls Optimize().
|
||||
mImageMetadata.SetOnImage(mImage);
|
||||
|
||||
if (HasSize()) {
|
||||
SetSizeOnImage();
|
||||
}
|
||||
|
||||
if (mDecodeDone && !IsMetadataDecode()) {
|
||||
MOZ_ASSERT(HasError() || mCurrentFrame, "Should have an error or a frame");
|
||||
@ -278,8 +240,6 @@ Decoder::Finish()
|
||||
if (!mIsAnimated && !mImageIsTransient && mCurrentFrame) {
|
||||
mCurrentFrame->SetOptimizable();
|
||||
}
|
||||
|
||||
mImage->OnDecodingComplete(mIsAnimated);
|
||||
}
|
||||
}
|
||||
|
||||
@ -334,7 +294,8 @@ Decoder::AllocateFrameInternal(uint32_t aFrameNum,
|
||||
}
|
||||
|
||||
const uint32_t bytesPerPixel = aPaletteDepth == 0 ? 4 : 1;
|
||||
if (!SurfaceCache::CanHold(aFrameRect.Size(), bytesPerPixel)) {
|
||||
if (ShouldUseSurfaceCache() &&
|
||||
!SurfaceCache::CanHold(aFrameRect.Size(), bytesPerPixel)) {
|
||||
NS_WARNING("Trying to add frame that's too large for the SurfaceCache");
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
@ -354,24 +315,26 @@ Decoder::AllocateFrameInternal(uint32_t aFrameNum,
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
|
||||
InsertOutcome outcome =
|
||||
SurfaceCache::Insert(frame, ImageKey(mImage.get()),
|
||||
RasterSurfaceKey(aTargetSize,
|
||||
aDecodeFlags,
|
||||
aFrameNum),
|
||||
Lifetime::Persistent);
|
||||
if (outcome == InsertOutcome::FAILURE) {
|
||||
// We couldn't insert the surface, almost certainly due to low memory. We
|
||||
// treat this as a permanent error to help the system recover; otherwise, we
|
||||
// might just end up attempting to decode this image again immediately.
|
||||
ref->Abort();
|
||||
return RawAccessFrameRef();
|
||||
} else if (outcome == InsertOutcome::FAILURE_ALREADY_PRESENT) {
|
||||
// Another decoder beat us to decoding this frame. We abort this decoder
|
||||
// rather than treat this as a real error.
|
||||
mDecodeAborted = true;
|
||||
ref->Abort();
|
||||
return RawAccessFrameRef();
|
||||
if (ShouldUseSurfaceCache()) {
|
||||
InsertOutcome outcome =
|
||||
SurfaceCache::Insert(frame, ImageKey(mImage.get()),
|
||||
RasterSurfaceKey(aTargetSize,
|
||||
aDecodeFlags,
|
||||
aFrameNum),
|
||||
Lifetime::Persistent);
|
||||
if (outcome == InsertOutcome::FAILURE) {
|
||||
// We couldn't insert the surface, almost certainly due to low memory. We
|
||||
// treat this as a permanent error to help the system recover; otherwise,
|
||||
// we might just end up attempting to decode this image again immediately.
|
||||
ref->Abort();
|
||||
return RawAccessFrameRef();
|
||||
} else if (outcome == InsertOutcome::FAILURE_ALREADY_PRESENT) {
|
||||
// Another decoder beat us to decoding this frame. We abort this decoder
|
||||
// rather than treat this as a real error.
|
||||
mDecodeAborted = true;
|
||||
ref->Abort();
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
}
|
||||
|
||||
nsIntRect refreshArea;
|
||||
@ -400,25 +363,14 @@ Decoder::AllocateFrameInternal(uint32_t aFrameNum,
|
||||
}
|
||||
|
||||
mFrameCount++;
|
||||
mImage->OnAddedFrame(mFrameCount, refreshArea);
|
||||
|
||||
if (mImage) {
|
||||
mImage->OnAddedFrame(mFrameCount, refreshArea);
|
||||
}
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
void
|
||||
Decoder::SetSizeOnImage()
|
||||
{
|
||||
MOZ_ASSERT(mImageMetadata.HasSize(), "Should have size");
|
||||
MOZ_ASSERT(mImageMetadata.HasOrientation(), "Should have orientation");
|
||||
|
||||
nsresult rv = mImage->SetSize(mImageMetadata.GetWidth(),
|
||||
mImageMetadata.GetHeight(),
|
||||
mImageMetadata.GetOrientation());
|
||||
if (NS_FAILED(rv)) {
|
||||
PostResizeError();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Hook stubs. Override these as necessary in decoder implementations.
|
||||
*/
|
||||
|
103
image/Decoder.h
103
image/Decoder.h
@ -42,12 +42,6 @@ public:
|
||||
*/
|
||||
nsresult Decode();
|
||||
|
||||
/**
|
||||
* Cleans up the decoder's state and notifies our image about success or
|
||||
* failure. May only be called on the main thread.
|
||||
*/
|
||||
void Finish();
|
||||
|
||||
/**
|
||||
* Given a maximum number of bytes we're willing to decode, @aByteLimit,
|
||||
* returns true if we should attempt to run this decoder synchronously.
|
||||
@ -107,7 +101,7 @@ public:
|
||||
MOZ_ASSERT(!mInitialized, "Shouldn't be initialized yet");
|
||||
mMetadataDecode = aMetadataDecode;
|
||||
}
|
||||
bool IsMetadataDecode() { return mMetadataDecode; }
|
||||
bool IsMetadataDecode() const { return mMetadataDecode; }
|
||||
|
||||
/**
|
||||
* If this decoder supports downscale-during-decode, sets the target size that
|
||||
@ -127,6 +121,22 @@ public:
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the requested sample size for this decoder. Used to implement the
|
||||
* -moz-sample-size media fragment.
|
||||
*
|
||||
* XXX(seth): Support for -moz-sample-size will be removed in bug 1120056.
|
||||
*/
|
||||
virtual void SetSampleSize(int aSampleSize) { }
|
||||
|
||||
/**
|
||||
* Set the requested resolution for this decoder. Used to implement the
|
||||
* -moz-resolution media fragment.
|
||||
*
|
||||
* XXX(seth): Support for -moz-resolution will be removed in bug 1118926.
|
||||
*/
|
||||
virtual void SetResolution(const gfx::IntSize& aResolution) { }
|
||||
|
||||
/**
|
||||
* Set whether should send partial invalidations.
|
||||
*
|
||||
@ -184,6 +194,18 @@ public:
|
||||
|
||||
bool ImageIsLocked() const { return mImageIsLocked; }
|
||||
|
||||
|
||||
/**
|
||||
* Set whether we should stop decoding after the first frame.
|
||||
*/
|
||||
void SetIsFirstFrameDecode()
|
||||
{
|
||||
MOZ_ASSERT(!mInitialized, "Shouldn't be initialized yet");
|
||||
mFirstFrameDecode = true;
|
||||
}
|
||||
|
||||
bool IsFirstFrameDecode() const { return mFirstFrameDecode; }
|
||||
|
||||
size_t BytesDecoded() const { return mBytesDecoded; }
|
||||
|
||||
// The amount of time we've spent inside Write() so far for this decoder.
|
||||
@ -202,19 +224,34 @@ public:
|
||||
return mInFrame ? mFrameCount - 1 : mFrameCount;
|
||||
}
|
||||
|
||||
// Did we discover that the image we're decoding is animated?
|
||||
bool HasAnimation() const { return mIsAnimated; }
|
||||
|
||||
// Error tracking
|
||||
bool HasError() const { return HasDataError() || HasDecoderError(); }
|
||||
bool HasDataError() const { return mDataError; }
|
||||
bool HasDecoderError() const { return NS_FAILED(mFailCode); }
|
||||
bool ShouldReportError() const { return mShouldReportError; }
|
||||
nsresult GetDecoderError() const { return mFailCode; }
|
||||
void PostResizeError() { PostDataError(); }
|
||||
|
||||
/// Did we finish decoding enough that calling Decode() again would be useless?
|
||||
bool GetDecodeDone() const
|
||||
{
|
||||
return mDecodeDone || (mMetadataDecode && HasSize()) ||
|
||||
HasError() || mDataDone;
|
||||
}
|
||||
|
||||
/// Did we finish decoding enough to set |RasterImage::mHasBeenDecoded|?
|
||||
// XXX(seth): This will be removed in bug 1187401.
|
||||
bool GetDecodeTotallyDone() const { return mDecodeDone && !IsMetadataDecode(); }
|
||||
|
||||
/// Are we in the middle of a frame right now? Used for assertions only.
|
||||
bool InFrame() const { return mInFrame; }
|
||||
|
||||
/// Should we store surfaces created by this decoder in the SurfaceCache?
|
||||
bool ShouldUseSurfaceCache() const { return bool(mImage); }
|
||||
|
||||
/**
|
||||
* Returns true if this decoder was aborted.
|
||||
*
|
||||
@ -237,7 +274,6 @@ public:
|
||||
uint32_t GetDecodeFlags() const { return DecodeFlags(mFlags); }
|
||||
|
||||
bool HasSize() const { return mImageMetadata.HasSize(); }
|
||||
void SetSizeOnImage();
|
||||
|
||||
nsIntSize GetSize() const
|
||||
{
|
||||
@ -254,9 +290,6 @@ public:
|
||||
*/
|
||||
RasterImage* GetImage() const { MOZ_ASSERT(mImage); return mImage.get(); }
|
||||
|
||||
// XXX(seth): This should be removed once we can optimize imgFrame objects
|
||||
// off-main-thread. It only exists to support the code in Finish() for
|
||||
// nsICODecoder.
|
||||
RawAccessFrameRef GetCurrentFrameRef()
|
||||
{
|
||||
return mCurrentFrame ? mCurrentFrame->RawAccessRef()
|
||||
@ -389,10 +422,13 @@ protected:
|
||||
uint8_t aPaletteDepth,
|
||||
imgFrame* aPreviousFrame);
|
||||
|
||||
/*
|
||||
* Member variables.
|
||||
*
|
||||
*/
|
||||
protected:
|
||||
uint8_t* mImageData; // Pointer to image data in either Cairo or 8bit format
|
||||
uint32_t mImageDataLength;
|
||||
uint32_t* mColormap; // Current colormap to be used in Cairo format
|
||||
uint32_t mColormapSize;
|
||||
|
||||
private:
|
||||
nsRefPtr<RasterImage> mImage;
|
||||
Maybe<SourceBufferIterator> mIterator;
|
||||
RawAccessFrameRef mCurrentFrame;
|
||||
@ -400,10 +436,9 @@ protected:
|
||||
nsIntRect mInvalidRect; // Tracks an invalidation region in the current frame.
|
||||
Progress mProgress;
|
||||
|
||||
uint8_t* mImageData; // Pointer to image data in either Cairo or 8bit format
|
||||
uint32_t mImageDataLength;
|
||||
uint32_t* mColormap; // Current colormap to be used in Cairo format
|
||||
uint32_t mColormapSize;
|
||||
uint32_t mFrameCount; // Number of frames, including anything in-progress
|
||||
|
||||
nsresult mFailCode;
|
||||
|
||||
// Telemetry data for this decoder.
|
||||
TimeDuration mDecodeTime;
|
||||
@ -411,24 +446,20 @@ protected:
|
||||
|
||||
uint32_t mFlags;
|
||||
size_t mBytesDecoded;
|
||||
bool mSendPartialInvalidations;
|
||||
bool mDataDone;
|
||||
bool mDecodeDone;
|
||||
bool mDataError;
|
||||
bool mDecodeAborted;
|
||||
bool mShouldReportError;
|
||||
bool mImageIsTransient;
|
||||
bool mImageIsLocked;
|
||||
|
||||
private:
|
||||
uint32_t mFrameCount; // Number of frames, including anything in-progress
|
||||
|
||||
nsresult mFailCode;
|
||||
|
||||
bool mInitialized;
|
||||
bool mMetadataDecode;
|
||||
bool mInFrame;
|
||||
bool mIsAnimated;
|
||||
bool mInitialized : 1;
|
||||
bool mMetadataDecode : 1;
|
||||
bool mSendPartialInvalidations : 1;
|
||||
bool mImageIsTransient : 1;
|
||||
bool mImageIsLocked : 1;
|
||||
bool mFirstFrameDecode : 1;
|
||||
bool mInFrame : 1;
|
||||
bool mIsAnimated : 1;
|
||||
bool mDataDone : 1;
|
||||
bool mDecodeDone : 1;
|
||||
bool mDataError : 1;
|
||||
bool mDecodeAborted : 1;
|
||||
bool mShouldReportError : 1;
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
|
@ -110,6 +110,8 @@ DecoderFactory::CreateDecoder(DecoderType aType,
|
||||
SourceBuffer* aSourceBuffer,
|
||||
const Maybe<IntSize>& aTargetSize,
|
||||
uint32_t aFlags,
|
||||
int aSampleSize,
|
||||
const IntSize& aResolution,
|
||||
bool aIsRedecode,
|
||||
bool aImageIsTransient,
|
||||
bool aImageIsLocked)
|
||||
@ -125,6 +127,8 @@ DecoderFactory::CreateDecoder(DecoderType aType,
|
||||
decoder->SetMetadataDecode(false);
|
||||
decoder->SetIterator(aSourceBuffer->Iterator());
|
||||
decoder->SetFlags(aFlags);
|
||||
decoder->SetSampleSize(aSampleSize);
|
||||
decoder->SetResolution(aResolution);
|
||||
decoder->SetSendPartialInvalidations(!aIsRedecode);
|
||||
decoder->SetImageIsTransient(aImageIsTransient);
|
||||
|
||||
@ -151,7 +155,9 @@ DecoderFactory::CreateDecoder(DecoderType aType,
|
||||
/* static */ already_AddRefed<Decoder>
|
||||
DecoderFactory::CreateMetadataDecoder(DecoderType aType,
|
||||
RasterImage* aImage,
|
||||
SourceBuffer* aSourceBuffer)
|
||||
SourceBuffer* aSourceBuffer,
|
||||
int aSampleSize,
|
||||
const IntSize& aResolution)
|
||||
{
|
||||
if (aType == DecoderType::UNKNOWN) {
|
||||
return nullptr;
|
||||
@ -164,6 +170,42 @@ DecoderFactory::CreateMetadataDecoder(DecoderType aType,
|
||||
// Initialize the decoder.
|
||||
decoder->SetMetadataDecode(true);
|
||||
decoder->SetIterator(aSourceBuffer->Iterator());
|
||||
decoder->SetSampleSize(aSampleSize);
|
||||
decoder->SetResolution(aResolution);
|
||||
|
||||
decoder->Init();
|
||||
if (NS_FAILED(decoder->GetDecoderError())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return decoder.forget();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<Decoder>
|
||||
DecoderFactory::CreateAnonymousDecoder(DecoderType aType,
|
||||
SourceBuffer* aSourceBuffer,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
if (aType == DecoderType::UNKNOWN) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Decoder> decoder =
|
||||
GetDecoder(aType, /* aImage = */ nullptr, /* aIsRedecode = */ false);
|
||||
MOZ_ASSERT(decoder, "Should have a decoder now");
|
||||
|
||||
// Initialize the decoder.
|
||||
decoder->SetMetadataDecode(false);
|
||||
decoder->SetIterator(aSourceBuffer->Iterator());
|
||||
decoder->SetFlags(aFlags);
|
||||
decoder->SetImageIsTransient(true);
|
||||
|
||||
// Without an image, the decoder can't store anything in the SurfaceCache, so
|
||||
// callers will only be able to retrieve the most recent frame via
|
||||
// Decoder::GetCurrentFrame(). That means that anonymous decoders should
|
||||
// always be first-frame-only decoders, because nobody ever wants the *last*
|
||||
// frame.
|
||||
decoder->SetIsFirstFrameDecode();
|
||||
|
||||
decoder->Init();
|
||||
if (NS_FAILED(decoder->GetDecoderError())) {
|
||||
|
@ -56,6 +56,10 @@ public:
|
||||
* downscale-during-decode.
|
||||
* @param aFlags Flags specifying what type of output the decoder should
|
||||
* produce; see GetDecodeFlags() in RasterImage.h.
|
||||
* @param aSampleSize The sample size requested using #-moz-samplesize (or 0
|
||||
* if none).
|
||||
* @param aResolution The resolution requested using #-moz-resolution (or an
|
||||
* empty rect if none).
|
||||
* @param aIsRedecode Specify 'true' if this image has been decoded before.
|
||||
* @param aImageIsTransient Specify 'true' if this image is transient.
|
||||
* @param aImageIsLocked Specify 'true' if this image is locked for the
|
||||
@ -68,6 +72,8 @@ public:
|
||||
SourceBuffer* aSourceBuffer,
|
||||
const Maybe<gfx::IntSize>& aTargetSize,
|
||||
uint32_t aFlags,
|
||||
int aSampleSize,
|
||||
const gfx::IntSize& aResolution,
|
||||
bool aIsRedecode,
|
||||
bool aImageIsTransient,
|
||||
bool aImageIsLocked);
|
||||
@ -83,11 +89,22 @@ public:
|
||||
* notifications as decoding progresses.
|
||||
* @param aSourceBuffer The SourceBuffer which the decoder will read its data
|
||||
* from.
|
||||
* @param aSampleSize The sample size requested using #-moz-samplesize (or 0
|
||||
* if none).
|
||||
* @param aResolution The resolution requested using #-moz-resolution (or an
|
||||
* empty rect if none).
|
||||
*/
|
||||
static already_AddRefed<Decoder>
|
||||
CreateMetadataDecoder(DecoderType aType,
|
||||
RasterImage* aImage,
|
||||
SourceBuffer* aSourceBuffer);
|
||||
SourceBuffer* aSourceBuffer,
|
||||
int aSampleSize,
|
||||
const gfx::IntSize& aResolution);
|
||||
|
||||
static already_AddRefed<Decoder>
|
||||
CreateAnonymousDecoder(DecoderType aType,
|
||||
SourceBuffer* aSourceBuffer,
|
||||
uint32_t aFlags);
|
||||
|
||||
private:
|
||||
virtual ~DecoderFactory() = 0;
|
||||
|
@ -221,6 +221,29 @@ ImageFactory::CreateRasterImage(nsIRequest* aRequest,
|
||||
aProgressTracker->SetImage(newImage);
|
||||
newImage->SetProgressTracker(aProgressTracker);
|
||||
|
||||
nsAutoCString ref;
|
||||
aURI->GetRef(ref);
|
||||
net::nsMediaFragmentURIParser parser(ref);
|
||||
if (parser.HasResolution()) {
|
||||
newImage->SetRequestedResolution(parser.GetResolution());
|
||||
}
|
||||
|
||||
if (parser.HasSampleSize()) {
|
||||
/* Get our principal */
|
||||
nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
if (chan) {
|
||||
nsContentUtils::GetSecurityManager()
|
||||
->GetChannelResultPrincipal(chan, getter_AddRefs(principal));
|
||||
}
|
||||
|
||||
if ((principal &&
|
||||
principal->GetAppStatus() == nsIPrincipal::APP_STATUS_CERTIFIED) ||
|
||||
gfxPrefs::ImageMozSampleSizeEnabled()) {
|
||||
newImage->SetRequestedSampleSize(parser.GetSampleSize());
|
||||
}
|
||||
}
|
||||
|
||||
rv = newImage->Init(aMimeType.get(), aImageFlags);
|
||||
NS_ENSURE_SUCCESS(rv, BadImage(newImage));
|
||||
|
||||
@ -245,29 +268,6 @@ ImageFactory::CreateRasterImage(nsIRequest* aRequest,
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoCString ref;
|
||||
aURI->GetRef(ref);
|
||||
net::nsMediaFragmentURIParser parser(ref);
|
||||
if (parser.HasResolution()) {
|
||||
newImage->SetRequestedResolution(parser.GetResolution());
|
||||
}
|
||||
|
||||
if (parser.HasSampleSize()) {
|
||||
/* Get our principal */
|
||||
nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
if (chan) {
|
||||
nsContentUtils::GetSecurityManager()
|
||||
->GetChannelResultPrincipal(chan, getter_AddRefs(principal));
|
||||
}
|
||||
|
||||
if ((principal &&
|
||||
principal->GetAppStatus() == nsIPrincipal::APP_STATUS_CERTIFIED) ||
|
||||
gfxPrefs::ImageMozSampleSizeEnabled()) {
|
||||
newImage->SetRequestedSampleSize(parser.GetSampleSize());
|
||||
}
|
||||
}
|
||||
|
||||
return newImage.forget();
|
||||
}
|
||||
|
||||
|
@ -14,9 +14,11 @@
|
||||
namespace mozilla {
|
||||
namespace image {
|
||||
|
||||
void
|
||||
ImageMetadata::SetOnImage(RasterImage* image)
|
||||
nsresult
|
||||
ImageMetadata::SetOnImage(RasterImage* aImage)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (mHotspotX != -1 && mHotspotY != -1) {
|
||||
nsCOMPtr<nsISupportsPRUint32> intwrapx =
|
||||
do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID);
|
||||
@ -24,11 +26,18 @@ ImageMetadata::SetOnImage(RasterImage* image)
|
||||
do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID);
|
||||
intwrapx->SetData(mHotspotX);
|
||||
intwrapy->SetData(mHotspotY);
|
||||
image->Set("hotspotX", intwrapx);
|
||||
image->Set("hotspotY", intwrapy);
|
||||
aImage->Set("hotspotX", intwrapx);
|
||||
aImage->Set("hotspotY", intwrapy);
|
||||
}
|
||||
|
||||
image->SetLoopCount(mLoopCount);
|
||||
aImage->SetLoopCount(mLoopCount);
|
||||
|
||||
if (HasSize()) {
|
||||
MOZ_ASSERT(HasOrientation(), "Should have orientation");
|
||||
rv = aImage->SetSize(GetWidth(), GetHeight(), GetOrientation());
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
} // namespace image
|
||||
|
@ -28,7 +28,7 @@ public:
|
||||
{ }
|
||||
|
||||
// Set the metadata this object represents on an image.
|
||||
void SetOnImage(RasterImage* image);
|
||||
nsresult SetOnImage(RasterImage* aImage);
|
||||
|
||||
void SetHotspot(uint16_t hotspotx, uint16_t hotspoty)
|
||||
{
|
||||
|
@ -4,14 +4,22 @@
|
||||
* 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 "imgIContainer.h"
|
||||
#include "ImageOps.h"
|
||||
|
||||
#include "ClippedImage.h"
|
||||
#include "DecodePool.h"
|
||||
#include "Decoder.h"
|
||||
#include "DecoderFactory.h"
|
||||
#include "DynamicImage.h"
|
||||
#include "FrozenImage.h"
|
||||
#include "OrientedImage.h"
|
||||
#include "Image.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "OrientedImage.h"
|
||||
#include "SourceBuffer.h"
|
||||
|
||||
#include "ImageOps.h"
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
namespace mozilla {
|
||||
namespace image {
|
||||
@ -68,5 +76,70 @@ ImageOps::CreateFromDrawable(gfxDrawable* aDrawable)
|
||||
return drawableImage.forget();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<gfx::SourceSurface>
|
||||
ImageOps::DecodeToSurface(nsIInputStream* aInputStream,
|
||||
const nsACString& aMimeType,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
MOZ_ASSERT(aInputStream);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Prepare the input stream.
|
||||
nsCOMPtr<nsIInputStream> inputStream = aInputStream;
|
||||
if (!NS_InputStreamIsBuffered(aInputStream)) {
|
||||
nsCOMPtr<nsIInputStream> bufStream;
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
|
||||
aInputStream, 1024);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
inputStream = bufStream;
|
||||
}
|
||||
}
|
||||
|
||||
// Figure out how much data we've been passed.
|
||||
uint64_t length;
|
||||
rv = inputStream->Available(&length);
|
||||
if (NS_FAILED(rv) || length > UINT32_MAX) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Write the data into a SourceBuffer.
|
||||
nsRefPtr<SourceBuffer> sourceBuffer = new SourceBuffer();
|
||||
sourceBuffer->ExpectLength(length);
|
||||
rv = sourceBuffer->AppendFromInputStream(inputStream, length);
|
||||
if (NS_FAILED(rv)) {
|
||||
return nullptr;
|
||||
}
|
||||
sourceBuffer->Complete(NS_OK);
|
||||
|
||||
// Create a decoder.
|
||||
DecoderType decoderType =
|
||||
DecoderFactory::GetDecoderType(PromiseFlatCString(aMimeType).get());
|
||||
nsRefPtr<Decoder> decoder =
|
||||
DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, aFlags);
|
||||
if (!decoder) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Run the decoder synchronously.
|
||||
decoder->Decode();
|
||||
if (!decoder->GetDecodeDone() || decoder->HasError()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Pull out the surface.
|
||||
RawAccessFrameRef frame = decoder->GetCurrentFrameRef();
|
||||
if (!frame) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<SourceSurface> surface = frame->GetSurface();
|
||||
if (!surface) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
@ -12,8 +12,14 @@
|
||||
|
||||
class gfxDrawable;
|
||||
class imgIContainer;
|
||||
class nsIInputStream;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace gfx {
|
||||
class SourceSurface;
|
||||
}
|
||||
|
||||
namespace image {
|
||||
|
||||
class Image;
|
||||
@ -61,6 +67,23 @@ public:
|
||||
static already_AddRefed<imgIContainer>
|
||||
CreateFromDrawable(gfxDrawable* aDrawable);
|
||||
|
||||
/**
|
||||
* Decodes an image from an nsIInputStream directly into a SourceSurface,
|
||||
* without ever creating an Image or imgIContainer (which are mostly
|
||||
* main-thread-only). That means that this function may be called
|
||||
* off-main-thread.
|
||||
*
|
||||
* @param aInputStream An input stream containing an encoded image.
|
||||
* @param aMimeType The MIME type of the image.
|
||||
* @param aFlags Flags of the imgIContainer::FLAG_DECODE_* variety.
|
||||
* @return A SourceSurface containing the first frame of the image at its
|
||||
* intrinsic size, or nullptr if the image cannot be decoded.
|
||||
*/
|
||||
static already_AddRefed<gfx::SourceSurface>
|
||||
DecodeToSurface(nsIInputStream* aInputStream,
|
||||
const nsACString& aMimeType,
|
||||
uint32_t aFlags);
|
||||
|
||||
private:
|
||||
// This is a static utility class, so disallow instantiation.
|
||||
virtual ~ImageOps() = 0;
|
||||
|
@ -21,7 +21,9 @@
|
||||
#include "ImageRegion.h"
|
||||
#include "Layers.h"
|
||||
#include "LookupResult.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "SourceBuffer.h"
|
||||
#include "SurfaceCache.h"
|
||||
@ -979,42 +981,6 @@ RasterImage::SetSize(int32_t aWidth, int32_t aHeight, Orientation aOrientation)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
RasterImage::OnDecodingComplete(bool aIsAnimated)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mError) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Flag that we've been decoded before.
|
||||
mHasBeenDecoded = true;
|
||||
|
||||
if (aIsAnimated) {
|
||||
if (mAnim) {
|
||||
mAnim->SetDoneDecoding(true);
|
||||
} else {
|
||||
// The OnAddedFrame event that will create mAnim is still in the event
|
||||
// queue. Wait for it.
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewRunnableMethod(this, &RasterImage::MarkAnimationDecoded);
|
||||
NS_DispatchToMainThread(runnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RasterImage::MarkAnimationDecoded()
|
||||
{
|
||||
MOZ_ASSERT(mAnim, "Should have an animation now");
|
||||
if (!mAnim) {
|
||||
return;
|
||||
}
|
||||
|
||||
mAnim->SetDoneDecoding(true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RasterImage::SetAnimationMode(uint16_t aAnimationMode)
|
||||
{
|
||||
@ -1222,20 +1188,16 @@ RasterImage::NotifyForLoadEvent(Progress aProgress)
|
||||
nsresult
|
||||
RasterImage::OnImageDataAvailable(nsIRequest*,
|
||||
nsISupports*,
|
||||
nsIInputStream* aInStr,
|
||||
uint64_t aOffset,
|
||||
nsIInputStream* aInputStream,
|
||||
uint64_t,
|
||||
uint32_t aCount)
|
||||
{
|
||||
nsresult rv;
|
||||
nsresult rv = mSourceBuffer->AppendFromInputStream(aInputStream, aCount);
|
||||
MOZ_ASSERT(rv == NS_OK || rv == NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// WriteToSourceBuffer always consumes everything it gets if it doesn't run
|
||||
// out of memory.
|
||||
uint32_t bytesRead;
|
||||
rv = aInStr->ReadSegments(WriteToSourceBuffer, this, aCount, &bytesRead);
|
||||
|
||||
MOZ_ASSERT(bytesRead == aCount || HasError() || NS_FAILED(rv),
|
||||
"WriteToSourceBuffer should consume everything if ReadSegments succeeds or "
|
||||
"the image must be in error!");
|
||||
if (MOZ_UNLIKELY(rv == NS_ERROR_OUT_OF_MEMORY)) {
|
||||
DoError();
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
@ -1445,8 +1407,8 @@ RasterImage::Decode(const IntSize& aSize, uint32_t aFlags)
|
||||
// Create a decoder.
|
||||
nsRefPtr<Decoder> decoder =
|
||||
DecoderFactory::CreateDecoder(mDecoderType, this, mSourceBuffer, targetSize,
|
||||
aFlags, mHasBeenDecoded, mTransient,
|
||||
imageIsLocked);
|
||||
aFlags, mRequestedSampleSize, mRequestedResolution,
|
||||
mHasBeenDecoded, mTransient, imageIsLocked);
|
||||
|
||||
// Make sure DecoderFactory was able to create a decoder successfully.
|
||||
if (!decoder) {
|
||||
@ -1499,7 +1461,9 @@ RasterImage::DecodeMetadata(uint32_t aFlags)
|
||||
|
||||
// Create a decoder.
|
||||
nsRefPtr<Decoder> decoder =
|
||||
DecoderFactory::CreateMetadataDecoder(mDecoderType, this, mSourceBuffer);
|
||||
DecoderFactory::CreateMetadataDecoder(mDecoderType, this, mSourceBuffer,
|
||||
mRequestedSampleSize,
|
||||
mRequestedResolution);
|
||||
|
||||
// Make sure DecoderFactory was able to create a decoder successfully.
|
||||
if (!decoder) {
|
||||
@ -1934,36 +1898,6 @@ RasterImage::HandleErrorWorker::Run()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIInputStream callback to copy the incoming image data directly to the
|
||||
// RasterImage without processing. The RasterImage is passed as the closure.
|
||||
// Always reads everything it gets, even if the data is erroneous.
|
||||
NS_METHOD
|
||||
RasterImage::WriteToSourceBuffer(nsIInputStream* /* unused */,
|
||||
void* aClosure,
|
||||
const char* aFromRawSegment,
|
||||
uint32_t /* unused */,
|
||||
uint32_t aCount,
|
||||
uint32_t* aWriteCount)
|
||||
{
|
||||
// Retrieve the RasterImage
|
||||
RasterImage* image = static_cast<RasterImage*>(aClosure);
|
||||
|
||||
// Copy the source data. Unless we hit OOM, we squelch the return value
|
||||
// here, because returning an error means that ReadSegments stops
|
||||
// reading data, violating our invariant that we read everything we get.
|
||||
// If we hit OOM then we fail and the load is aborted.
|
||||
nsresult rv = image->mSourceBuffer->Append(aFromRawSegment, aCount);
|
||||
if (rv == NS_ERROR_OUT_OF_MEMORY) {
|
||||
image->DoError();
|
||||
return rv;
|
||||
}
|
||||
|
||||
// We wrote everything we got
|
||||
*aWriteCount = aCount;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
RasterImage::ShouldAnimate()
|
||||
{
|
||||
@ -2010,9 +1944,40 @@ RasterImage::FinalizeDecoder(Decoder* aDecoder)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aDecoder);
|
||||
MOZ_ASSERT(aDecoder->HasError() || !aDecoder->InFrame(),
|
||||
"Finalizing a decoder in the middle of a frame");
|
||||
|
||||
// If the decoder detected an error, log it to the error console.
|
||||
if (aDecoder->ShouldReportError() && !aDecoder->WasAborted()) {
|
||||
ReportDecoderError(aDecoder);
|
||||
}
|
||||
|
||||
// Record all the metadata the decoder gathered about this image.
|
||||
nsresult rv = aDecoder->GetImageMetadata().SetOnImage(this);
|
||||
if (NS_FAILED(rv)) {
|
||||
aDecoder->PostResizeError();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mError || mHasSize || !aDecoder->HasSize(),
|
||||
"Should have handed off size by now");
|
||||
|
||||
if (aDecoder->GetDecodeTotallyDone() && !mError) {
|
||||
// Flag that we've been decoded before.
|
||||
mHasBeenDecoded = true;
|
||||
|
||||
if (aDecoder->HasAnimation()) {
|
||||
if (mAnim) {
|
||||
mAnim->SetDoneDecoding(true);
|
||||
} else {
|
||||
// The OnAddedFrame event that will create mAnim is still in the event
|
||||
// queue. Wait for it.
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewRunnableMethod(this, &RasterImage::MarkAnimationDecoded);
|
||||
NS_DispatchToMainThread(runnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send out any final notifications.
|
||||
NotifyProgress(aDecoder->TakeProgress(),
|
||||
aDecoder->TakeInvalidRect(),
|
||||
@ -2069,6 +2034,46 @@ RasterImage::FinalizeDecoder(Decoder* aDecoder)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RasterImage::MarkAnimationDecoded()
|
||||
{
|
||||
MOZ_ASSERT(mAnim, "Should have an animation now");
|
||||
if (!mAnim) {
|
||||
return;
|
||||
}
|
||||
|
||||
mAnim->SetDoneDecoding(true);
|
||||
}
|
||||
|
||||
void
|
||||
RasterImage::ReportDecoderError(Decoder* aDecoder)
|
||||
{
|
||||
nsCOMPtr<nsIConsoleService> consoleService =
|
||||
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||
nsCOMPtr<nsIScriptError> errorObject =
|
||||
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
|
||||
|
||||
if (consoleService && errorObject && !aDecoder->HasDecoderError()) {
|
||||
nsAutoString msg(NS_LITERAL_STRING("Image corrupt or truncated."));
|
||||
nsAutoString src;
|
||||
if (GetURI()) {
|
||||
nsCString uri;
|
||||
if (GetURI()->GetSpecTruncatedTo1k(uri) == ImageURL::TruncatedTo1k) {
|
||||
msg += NS_LITERAL_STRING(" URI in this note truncated due to length.");
|
||||
}
|
||||
src = NS_ConvertUTF8toUTF16(uri);
|
||||
}
|
||||
if (NS_SUCCEEDED(errorObject->InitWithWindowID(
|
||||
msg,
|
||||
src,
|
||||
EmptyString(), 0, 0, nsIScriptError::errorFlag,
|
||||
"Image", InnerWindowID()
|
||||
))) {
|
||||
consoleService->LogMessage(errorObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<imgIContainer>
|
||||
RasterImage::Unwrap()
|
||||
{
|
||||
|
@ -170,12 +170,6 @@ public:
|
||||
// Methods inherited from Image
|
||||
virtual void OnSurfaceDiscarded() override;
|
||||
|
||||
// Raster-specific methods
|
||||
static NS_METHOD WriteToSourceBuffer(nsIInputStream* aIn, void* aClosure,
|
||||
const char* aFromRawSegment,
|
||||
uint32_t aToOffset, uint32_t aCount,
|
||||
uint32_t* aWriteCount);
|
||||
|
||||
/* The total number of frames in this image. */
|
||||
uint32_t GetNumFrames() const { return mFrameCount; }
|
||||
|
||||
@ -206,12 +200,6 @@ public:
|
||||
*/
|
||||
void SetLoopCount(int32_t aLoopCount);
|
||||
|
||||
/// Notification that the entire image has been decoded.
|
||||
void OnDecodingComplete(bool aIsAnimated);
|
||||
|
||||
/// Helper method for OnDecodingComplete.
|
||||
void MarkAnimationDecoded();
|
||||
|
||||
/**
|
||||
* Sends the provided progress notifications to ProgressTracker.
|
||||
*
|
||||
@ -234,6 +222,10 @@ public:
|
||||
*/
|
||||
void FinalizeDecoder(Decoder* aDecoder);
|
||||
|
||||
// Helper methods for FinalizeDecoder.
|
||||
void MarkAnimationDecoded();
|
||||
void ReportDecoderError(Decoder* aDecoder);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Network callbacks.
|
||||
@ -269,18 +261,11 @@ public:
|
||||
mRequestedResolution = requestedResolution;
|
||||
}
|
||||
|
||||
nsIntSize GetRequestedResolution() {
|
||||
return mRequestedResolution;
|
||||
}
|
||||
/* Provide a hint for the requested dimension of the resulting image. */
|
||||
void SetRequestedSampleSize(int requestedSampleSize) {
|
||||
mRequestedSampleSize = requestedSampleSize;
|
||||
}
|
||||
|
||||
int GetRequestedSampleSize() {
|
||||
return mRequestedSampleSize;
|
||||
}
|
||||
|
||||
nsCString GetURIString() {
|
||||
nsCString spec;
|
||||
if (GetURI()) {
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include "mozilla/Likely.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "SurfaceCache.h"
|
||||
|
||||
@ -354,6 +355,46 @@ SourceBuffer::Append(const char* aData, size_t aLength)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static NS_METHOD
|
||||
AppendToSourceBuffer(nsIInputStream*,
|
||||
void* aClosure,
|
||||
const char* aFromRawSegment,
|
||||
uint32_t,
|
||||
uint32_t aCount,
|
||||
uint32_t* aWriteCount)
|
||||
{
|
||||
SourceBuffer* sourceBuffer = static_cast<SourceBuffer*>(aClosure);
|
||||
|
||||
// Copy the source data. Unless we hit OOM, we squelch the return value here,
|
||||
// because returning an error means that ReadSegments stops reading data, and
|
||||
// we want to ensure that we read everything we get. If we hit OOM then we
|
||||
// return a failed status to the caller.
|
||||
nsresult rv = sourceBuffer->Append(aFromRawSegment, aCount);
|
||||
if (rv == NS_ERROR_OUT_OF_MEMORY) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Report that we wrote everything we got.
|
||||
*aWriteCount = aCount;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SourceBuffer::AppendFromInputStream(nsIInputStream* aInputStream,
|
||||
uint32_t aCount)
|
||||
{
|
||||
uint32_t bytesRead;
|
||||
nsresult rv = aInputStream->ReadSegments(AppendToSourceBuffer, this,
|
||||
aCount, &bytesRead);
|
||||
|
||||
MOZ_ASSERT(bytesRead == aCount || rv == NS_ERROR_OUT_OF_MEMORY,
|
||||
"AppendToSourceBuffer should consume everything unless "
|
||||
"we run out of memory");
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::Complete(nsresult aStatus)
|
||||
{
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include "mozilla/nsRefPtr.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsIInputStream;
|
||||
|
||||
namespace mozilla {
|
||||
namespace image {
|
||||
|
||||
@ -207,12 +209,6 @@ private:
|
||||
* keep a list of consumers which are waiting for new data, and to resume them
|
||||
* when the producer appends more. All consumers must implement the IResumable
|
||||
* interface to make this possible.
|
||||
*
|
||||
* XXX(seth): We should add support for compacting a SourceBuffer. To do this,
|
||||
* we need to have SourceBuffer keep track of how many live
|
||||
* SourceBufferIterator's point to it. When the SourceBuffer is complete and no
|
||||
* live SourceBufferIterator's for it remain, we can compact its contents into a
|
||||
* single chunk.
|
||||
*/
|
||||
class SourceBuffer final
|
||||
{
|
||||
@ -235,6 +231,9 @@ public:
|
||||
/// Append the provided data to the buffer.
|
||||
nsresult Append(const char* aData, size_t aLength);
|
||||
|
||||
/// Append the data available on the provided nsIInputStream to the buffer.
|
||||
nsresult AppendFromInputStream(nsIInputStream* aInputStream, uint32_t aCount);
|
||||
|
||||
/**
|
||||
* Mark the buffer complete, with a status that will be available to
|
||||
* consumers. Further calls to Append() are forbidden after Complete().
|
||||
|
@ -906,6 +906,13 @@ nsGIFDecoder2::WriteInternal(const char* aBuffer, uint32_t aCount)
|
||||
break;
|
||||
|
||||
case gif_image_header: {
|
||||
if (mGIFStruct.images_decoded > 0 && IsFirstFrameDecode()) {
|
||||
// We're about to get a second frame, but we only want the first. Stop
|
||||
// decoding now.
|
||||
mGIFStruct.state = gif_done;
|
||||
break;
|
||||
}
|
||||
|
||||
// Get image offsets, with respect to the screen origin
|
||||
mGIFStruct.x_offset = GETINT16(q);
|
||||
mGIFStruct.y_offset = GETINT16(q + 2);
|
||||
|
@ -266,9 +266,10 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
|
||||
}
|
||||
|
||||
uint16_t colorDepth = 0;
|
||||
nsIntSize prefSize = mImage->GetRequestedResolution();
|
||||
if (prefSize.width == 0 && prefSize.height == 0) {
|
||||
prefSize.SizeTo(PREFICONSIZE, PREFICONSIZE);
|
||||
|
||||
// If we didn't get a #-moz-resolution, default to PREFICONSIZE.
|
||||
if (mResolution.width == 0 && mResolution.height == 0) {
|
||||
mResolution.SizeTo(PREFICONSIZE, PREFICONSIZE);
|
||||
}
|
||||
|
||||
// A measure of the difference in size between the entry we've found
|
||||
@ -306,8 +307,8 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
|
||||
// Calculate the delta between this image's size and the desired size,
|
||||
// so we can see if it is better than our current-best option.
|
||||
// In the case of several equally-good images, we use the last one.
|
||||
int32_t delta = (e.mWidth == 0 ? 256 : e.mWidth) - prefSize.width +
|
||||
(e.mHeight == 0 ? 256 : e.mHeight) - prefSize.height;
|
||||
int32_t delta = (e.mWidth == 0 ? 256 : e.mWidth) - mResolution.width +
|
||||
(e.mHeight == 0 ? 256 : e.mHeight) - mResolution.height;
|
||||
if (e.mBitCount >= colorDepth &&
|
||||
((diff < 0 && delta >= diff) || (delta >= 0 && delta <= diff))) {
|
||||
diff = delta;
|
||||
@ -360,6 +361,9 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
|
||||
mContainedDecoder = new nsPNGDecoder(mImage);
|
||||
mContainedDecoder->SetMetadataDecode(IsMetadataDecode());
|
||||
mContainedDecoder->SetSendPartialInvalidations(mSendPartialInvalidations);
|
||||
if (mFirstFrameDecode) {
|
||||
mContainedDecoder->SetIsFirstFrameDecode();
|
||||
}
|
||||
mContainedDecoder->Init();
|
||||
if (!WriteToContainedDecoder(mSignature, PNGSIGNATURESIZE)) {
|
||||
return;
|
||||
@ -437,6 +441,9 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
|
||||
bmpDecoder->SetUseAlphaData(true);
|
||||
mContainedDecoder->SetMetadataDecode(IsMetadataDecode());
|
||||
mContainedDecoder->SetSendPartialInvalidations(mSendPartialInvalidations);
|
||||
if (mFirstFrameDecode) {
|
||||
mContainedDecoder->SetIsFirstFrameDecode();
|
||||
}
|
||||
mContainedDecoder->Init();
|
||||
|
||||
// The ICO format when containing a BMP does not include the 14 byte
|
||||
|
@ -36,6 +36,11 @@ public:
|
||||
return mDirEntry.mHeight == 0 ? 256 : mDirEntry.mHeight;
|
||||
}
|
||||
|
||||
virtual void SetResolution(const gfx::IntSize& aResolution) override
|
||||
{
|
||||
mResolution = aResolution;
|
||||
}
|
||||
|
||||
virtual void WriteInternal(const char* aBuffer, uint32_t aCount) override;
|
||||
virtual void FinishInternal() override;
|
||||
virtual void FinishWithErrorInternal() override;
|
||||
@ -76,6 +81,7 @@ private:
|
||||
// Obtains the number of colors from the BPP, mBPP must be filled in
|
||||
uint16_t GetNumColors();
|
||||
|
||||
gfx::IntSize mResolution; // The requested -moz-resolution for this icon.
|
||||
uint16_t mBPP; // Stores the images BPP
|
||||
uint32_t mPos; // Keeps track of the position we have decoded up until
|
||||
uint16_t mNumIcons; // Stores the number of icons in the ICO file
|
||||
|
@ -84,6 +84,7 @@ nsJPEGDecoder::nsJPEGDecoder(RasterImage* aImage,
|
||||
Decoder::DecodeStyle aDecodeStyle)
|
||||
: Decoder(aImage)
|
||||
, mDecodeStyle(aDecodeStyle)
|
||||
, mSampleSize(0)
|
||||
{
|
||||
mState = JPEG_HEADER;
|
||||
mReading = true;
|
||||
@ -248,10 +249,10 @@ nsJPEGDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
|
||||
return; // I/O suspension
|
||||
}
|
||||
|
||||
int sampleSize = mImage->GetRequestedSampleSize();
|
||||
if (sampleSize > 0) {
|
||||
// If we have a sample size specified for -moz-sample-size, use it.
|
||||
if (mSampleSize > 0) {
|
||||
mInfo.scale_num = 1;
|
||||
mInfo.scale_denom = sampleSize;
|
||||
mInfo.scale_denom = mSampleSize;
|
||||
}
|
||||
|
||||
// Used to set up image size so arrays can be allocated
|
||||
|
@ -57,6 +57,11 @@ public:
|
||||
|
||||
virtual nsresult SetTargetSize(const nsIntSize& aSize) override;
|
||||
|
||||
virtual void SetSampleSize(int aSampleSize) override
|
||||
{
|
||||
mSampleSize = aSampleSize;
|
||||
}
|
||||
|
||||
virtual void InitInternal() override;
|
||||
virtual void WriteInternal(const char* aBuffer, uint32_t aCount) override;
|
||||
virtual void FinishInternal() override;
|
||||
@ -103,6 +108,8 @@ public:
|
||||
const Decoder::DecodeStyle mDecodeStyle;
|
||||
|
||||
uint32_t mCMSMode;
|
||||
|
||||
int mSampleSize;
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
|
@ -115,6 +115,7 @@ nsPNGDecoder::nsPNGDecoder(RasterImage* aImage)
|
||||
mHeaderBytesRead(0), mCMSMode(0),
|
||||
mChannels(0), mFrameIsHidden(false),
|
||||
mDisablePremultipliedAlpha(false),
|
||||
mSuccessfulEarlyFinish(false),
|
||||
mNumFrames(0)
|
||||
{
|
||||
}
|
||||
@ -176,9 +177,8 @@ nsPNGDecoder::CreateFrame(png_uint_32 aXOffset, png_uint_32 aYOffset,
|
||||
|
||||
MOZ_LOG(GetPNGDecoderAccountingLog(), LogLevel::Debug,
|
||||
("PNGDecoderAccounting: nsPNGDecoder::CreateFrame -- created "
|
||||
"image frame with %dx%d pixels in container %p",
|
||||
aWidth, aHeight,
|
||||
&mImage));
|
||||
"image frame with %dx%d pixels for decoder %p",
|
||||
aWidth, aHeight, this));
|
||||
|
||||
#ifdef PNG_APNG_SUPPORTED
|
||||
if (png_get_valid(mPNG, mInfo, PNG_INFO_acTL)) {
|
||||
@ -376,7 +376,7 @@ nsPNGDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
|
||||
|
||||
// We might not really know what caused the error, but it makes more
|
||||
// sense to blame the data.
|
||||
if (!HasError()) {
|
||||
if (!mSuccessfulEarlyFinish && !HasError()) {
|
||||
PostDataError();
|
||||
}
|
||||
|
||||
@ -828,6 +828,14 @@ nsPNGDecoder::frame_info_callback(png_structp png_ptr, png_uint_32 frame_num)
|
||||
// old frame is done
|
||||
decoder->EndImageFrame();
|
||||
|
||||
if (!decoder->mFrameIsHidden && decoder->IsFirstFrameDecode()) {
|
||||
// We're about to get a second non-hidden frame, but we only want the first.
|
||||
// Stop decoding now.
|
||||
decoder->PostDecodeDone();
|
||||
decoder->mSuccessfulEarlyFinish = true;
|
||||
png_longjmp(decoder->mPNG, 1);
|
||||
}
|
||||
|
||||
// Only the first frame can be hidden, so unhide unconditionally here.
|
||||
decoder->mFrameIsHidden = false;
|
||||
|
||||
|
@ -95,6 +95,7 @@ public:
|
||||
uint8_t mChannels;
|
||||
bool mFrameIsHidden;
|
||||
bool mDisablePremultipliedAlpha;
|
||||
bool mSuccessfulEarlyFinish;
|
||||
|
||||
struct AnimFrameInfo
|
||||
{
|
||||
|
@ -140,12 +140,12 @@ imgFrame::imgFrame()
|
||||
, mBlendMethod(BlendMethod::OVER)
|
||||
, mHasNoAlpha(false)
|
||||
, mAborted(false)
|
||||
, mOptimizable(false)
|
||||
, mPalettedImageData(nullptr)
|
||||
, mPaletteDepth(0)
|
||||
, mNonPremult(false)
|
||||
, mSinglePixel(false)
|
||||
, mCompositingFailed(false)
|
||||
, mOptimizable(false)
|
||||
{
|
||||
static bool hasCheckedOptimize = false;
|
||||
if (!hasCheckedOptimize) {
|
||||
@ -952,8 +952,8 @@ imgFrame::UnlockImageData()
|
||||
void
|
||||
imgFrame::SetOptimizable()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AssertImageDataLocked();
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mOptimizable = true;
|
||||
}
|
||||
|
||||
|
@ -342,6 +342,7 @@ private: // data
|
||||
|
||||
bool mHasNoAlpha;
|
||||
bool mAborted;
|
||||
bool mOptimizable;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -371,7 +372,6 @@ private: // data
|
||||
|
||||
bool mSinglePixel;
|
||||
bool mCompositingFailed;
|
||||
bool mOptimizable;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -789,7 +789,9 @@ NewImageChannel(nsIChannel** aResult,
|
||||
// we should always have a requestingNode, or we are loading something
|
||||
// outside a document, in which case the triggeringPrincipal
|
||||
// should always be the systemPrincipal.
|
||||
MOZ_ASSERT(nsContentUtils::IsSystemPrincipal(triggeringPrincipal));
|
||||
// However, there are two exceptions: one is Notifications and the
|
||||
// other one is Favicons which create a channel in the parent prcoess
|
||||
// in which case we can't get a requestingNode.
|
||||
rv = NS_NewChannel(aResult,
|
||||
aURI,
|
||||
triggeringPrincipal,
|
||||
|
@ -61,6 +61,8 @@ imgTools::DecodeImage(nsIInputStream* aInStr,
|
||||
const nsACString& aMimeType,
|
||||
imgIContainer** aContainer)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsresult rv;
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aInStr);
|
||||
|
@ -5,6 +5,8 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += ['build', 'decoders', 'encoders']
|
||||
if CONFIG['ENABLE_TESTS']:
|
||||
DIRS += ['test/gtest']
|
||||
|
||||
with Files('**'):
|
||||
BUG_COMPONENT = ('Core', 'ImageLib')
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user