merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2015-08-03 13:56:39 +02:00
commit e016c33f6e
189 changed files with 3212 additions and 1153 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -76,6 +76,7 @@ public:
IPC::Channel* aChannel);
void InitProcessAttributes();
void InitXPCOM();
void InitGraphicsDeviceData();
static ContentChild* GetSingleton() {
return sSingleton;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 += [

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -20,8 +20,6 @@ WIN_LIBS= \
---------------------------------------------------------------------- */
#define NOMINMAX 1
#include "plstr.h"
#include <windows.h>
#include <tchar.h>

View File

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

View File

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

View File

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

View 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

View File

@ -26,6 +26,10 @@ SOURCES += [
'SharedDIB.cpp',
]
IPDL_SOURCES = [
'GraphicsMessages.ipdlh',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

@ -95,6 +95,7 @@ public:
uint8_t mChannels;
bool mFrameIsHidden;
bool mDisablePremultipliedAlpha;
bool mSuccessfulEarlyFinish;
struct AnimFrameInfo
{

View File

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

View File

@ -342,6 +342,7 @@ private: // data
bool mHasNoAlpha;
bool mAborted;
bool mOptimizable;
//////////////////////////////////////////////////////////////////////////////
@ -371,7 +372,6 @@ private: // data
bool mSinglePixel;
bool mCompositingFailed;
bool mOptimizable;
};
/**

View File

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

View File

@ -61,6 +61,8 @@ imgTools::DecodeImage(nsIInputStream* aInStr,
const nsACString& aMimeType,
imgIContainer** aContainer)
{
MOZ_ASSERT(NS_IsMainThread());
nsresult rv;
NS_ENSURE_ARG_POINTER(aInStr);

View File

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