This commit is contained in:
Ryan VanderMeulen 2014-10-31 16:09:15 -04:00
Родитель 94730ac570 05091f1634
Коммит 85792b5ee7
243 изменённых файлов: 4804 добавлений и 2141 удалений

Просмотреть файл

@ -402,10 +402,11 @@ this.EventManager.prototype = {
// If there are embedded objects in the text, ignore them.
// Assuming changes to the descendants would already be handled by the
// show/hide event.
let modifiedText = event.modifiedText.replace(/\uFFFC/g, '').trim();
if (!modifiedText) {
let modifiedText = event.modifiedText.replace(/\uFFFC/g, '');
if (modifiedText != event.modifiedText && !modifiedText.trim()) {
return;
}
if (aLiveRegion) {
if (aEvent.eventType === Events.TEXT_REMOVED) {
this._queueLiveEvent(Events.TEXT_REMOVED, aLiveRegion, aIsPolite,
@ -416,8 +417,8 @@ this.EventManager.prototype = {
modifiedText));
}
} else {
this.present(Presentation.textChanged(isInserted, event.start,
event.length, text, modifiedText));
this.present(Presentation.textChanged(aEvent.accessible, isInserted,
event.start, event.length, text, modifiedText));
}
},

Просмотреть файл

@ -11,8 +11,7 @@
const {utils: Cu, interfaces: Ci} = Components;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'Utils', // jshint ignore:line
'resource://gre/modules/accessibility/Utils.jsm');
Cu.import('resource://gre/modules/accessibility/Utils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'Logger', // jshint ignore:line
'resource://gre/modules/accessibility/Utils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'PivotContext', // jshint ignore:line
@ -60,8 +59,8 @@ Presenter.prototype = {
/**
* Text has changed, either by the user or by the system. TODO.
*/
textChanged: function textChanged(aIsInserted, aStartOffset, aLength, aText, // jshint ignore:line
aModifiedText) {}, // jshint ignore:line
textChanged: function textChanged(aAccessible, aIsInserted, aStartOffset, // jshint ignore:line
aLength, aText, aModifiedText) {}, // jshint ignore:line
/**
* Text selection has changed. TODO.
@ -344,7 +343,7 @@ AndroidPresenter.prototype.tabStateChanged =
};
AndroidPresenter.prototype.textChanged = function AndroidPresenter_textChanged(
aIsInserted, aStart, aLength, aText, aModifiedText) {
aAccessible, aIsInserted, aStart, aLength, aText, aModifiedText) {
let eventDetails = {
eventType: this.ANDROID_VIEW_TEXT_CHANGED,
text: [aText],
@ -461,6 +460,13 @@ B2GPresenter.prototype = Object.create(Presenter.prototype);
B2GPresenter.prototype.type = 'B2G';
B2GPresenter.prototype.keyboardEchoSetting =
new PrefCache('accessibility.accessfu.keyboard_echo');
B2GPresenter.prototype.NO_ECHO = 0;
B2GPresenter.prototype.CHARACTER_ECHO = 1;
B2GPresenter.prototype.WORD_ECHO = 2;
B2GPresenter.prototype.CHARACTER_AND_WORD_ECHO = 3;
/**
* A pattern used for haptic feedback.
* @type {Array}
@ -497,6 +503,12 @@ B2GPresenter.prototype.pivotChanged =
B2GPresenter.prototype.valueChanged =
function B2GPresenter_valueChanged(aAccessible) {
// the editable value changes are handled in the text changed presenter
if (Utils.getState(aAccessible).contains(States.EDITABLE)) {
return null;
}
return {
type: this.type,
details: {
@ -506,6 +518,42 @@ B2GPresenter.prototype.valueChanged =
};
};
B2GPresenter.prototype.textChanged = function B2GPresenter_textChanged(
aAccessible, aIsInserted, aStart, aLength, aText, aModifiedText) {
let echoSetting = this.keyboardEchoSetting.value;
let text = '';
if (echoSetting == this.CHARACTER_ECHO ||
echoSetting == this.CHARACTER_AND_WORD_ECHO) {
text = aModifiedText;
}
// add word if word boundary is added
if ((echoSetting == this.WORD_ECHO ||
echoSetting == this.CHARACTER_AND_WORD_ECHO) &&
aIsInserted && aLength === 1) {
let accText = aAccessible.QueryInterface(Ci.nsIAccessibleText);
let startBefore = {}, endBefore = {};
let startAfter = {}, endAfter = {};
accText.getTextBeforeOffset(aStart,
Ci.nsIAccessibleText.BOUNDARY_WORD_END, startBefore, endBefore);
let maybeWord = accText.getTextBeforeOffset(aStart + 1,
Ci.nsIAccessibleText.BOUNDARY_WORD_END, startAfter, endAfter);
if (endBefore.value !== endAfter.value) {
text += maybeWord;
}
}
return {
type: this.type,
details: {
eventType: 'text-change',
data: text
}
};
};
B2GPresenter.prototype.actionInvoked =
function B2GPresenter_actionInvoked(aObject, aActionName) {
return {
@ -614,11 +662,11 @@ this.Presentation = { // jshint ignore:line
for each (p in this.presenters)]; // jshint ignore:line
},
textChanged: function Presentation_textChanged(aIsInserted, aStartOffset,
aLength, aText,
textChanged: function Presentation_textChanged(aAccessible, aIsInserted,
aStartOffset, aLength, aText,
aModifiedText) {
return [p.textChanged(aIsInserted, aStartOffset, aLength, aText, // jshint ignore:line
aModifiedText) for each (p in this.presenters)]; // jshint ignore:line
return [p.textChanged(aAccessible, aIsInserted, aStartOffset, aLength, // jshint ignore:line
aText, aModifiedText) for each (p in this.presenters)]; // jshint ignore:line
},
textSelectionChanged: function textSelectionChanged(aText, aStart, aEnd,

Просмотреть файл

@ -626,6 +626,15 @@ function ExpectedValueChange(aValue, aOptions) {
ExpectedValueChange.prototype = Object.create(ExpectedPresent.prototype);
function ExpectedTextChanged(aValue, aOptions) {
ExpectedPresent.call(this, {
eventType: 'text-change',
data: aValue
}, null, aOptions);
}
ExpectedTextChanged.prototype = Object.create(ExpectedPresent.prototype);
function ExpectedEditState(aEditState, aOptions) {
ExpectedMessage.call(this, 'AccessFu:Input', aOptions);
this.json = aEditState;

Просмотреть файл

@ -8,6 +8,9 @@
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js">
</script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js">
</script>
<script type="application/javascript"
src="chrome://mochikit/content/chrome-harness.js">
</script>
@ -169,9 +172,98 @@
multiline: false,
atStart: true,
atEnd: false
}, { focused: 'html' })]
}, { focused: 'html' })],
[ContentMessages.focusSelector('input'),
new ExpectedAnnouncement('editing'),
new ExpectedEditState({
editing: true,
multiline: false,
atStart: true,
atEnd: true
}),
new ExpectedCursorChange([{string: 'entry'}]),
new ExpectedTextSelectionChanged(0, 0)
],
[function() {
SpecialPowers.setIntPref(KEYBOARD_ECHO_SETTING, 3);
typeKey('a')();
},
new ExpectedTextChanged('a'),
new ExpectedTextSelectionChanged(1, 1),
],
[typeKey('b'),
new ExpectedTextChanged('b'),
new ExpectedTextSelectionChanged(2, 2),
],
[typeKey('c'),
new ExpectedTextChanged('c'),
new ExpectedTextSelectionChanged(3, 3),
],
[typeKey('d'),
new ExpectedTextChanged('d'),
new ExpectedTextSelectionChanged(4, 4),
],
[typeKey(' '),
new ExpectedTextChanged(' abcd'),
new ExpectedTextSelectionChanged(5, 5),
],
[typeKey('e'),
new ExpectedTextChanged('e'),
new ExpectedTextSelectionChanged(6, 6),
],
[function() {
SpecialPowers.setIntPref(KEYBOARD_ECHO_SETTING, 2);
typeKey('a')();
},
new ExpectedTextChanged(''),
new ExpectedTextSelectionChanged(7, 7),
],
[typeKey('d'),
new ExpectedTextChanged(''),
new ExpectedTextSelectionChanged(8, 8),
],
[typeKey(' '),
new ExpectedTextChanged(' ead'),
new ExpectedTextSelectionChanged(9, 9),
],
[function() {
SpecialPowers.setIntPref(KEYBOARD_ECHO_SETTING, 1);
typeKey('f')();
},
new ExpectedTextChanged('f'),
new ExpectedTextSelectionChanged(10, 10),
],
[typeKey('g'),
new ExpectedTextChanged('g'),
new ExpectedTextSelectionChanged(11, 11),
],
[typeKey(' '),
new ExpectedTextChanged(' '),
new ExpectedTextSelectionChanged(12, 12),
],
[function() {
SpecialPowers.setIntPref(KEYBOARD_ECHO_SETTING, 0);
typeKey('f')();
},
new ExpectedTextChanged(''),
new ExpectedTextSelectionChanged(13, 13),
],
[typeKey('g'),
new ExpectedTextChanged(''),
new ExpectedTextSelectionChanged(14, 14),
],
[typeKey(' '),
new ExpectedTextChanged(''),
new ExpectedTextSelectionChanged(15, 15),
],
]);
const KEYBOARD_ECHO_SETTING = 'accessibility.accessfu.keyboard_echo';
function typeKey(key) {
return function() { synthesizeKey(key, {}, currentTabWindow()); };
}
addA11yLoadEvent(function() {
textTest.start(function () {
closeBrowserWindow();

Просмотреть файл

@ -797,6 +797,9 @@ pref("accessibility.accessfu.quicknav_index", 0);
pref("accessibility.accessfu.utterance", 1);
// Whether to skip images with empty alt text
pref("accessibility.accessfu.skip_empty_images", true);
// Setting to change the verbosity of entered text (0 - none, 1 - characters,
// 2 - words, 3 - both)
pref("accessibility.accessfu.keyboard_echo", 3);
// Enable hit-target fluffing
pref("ui.touch.radius.enabled", true);
@ -1003,12 +1006,11 @@ pref("apz.subframe.enabled", true);
// Overscroll-related settings
pref("apz.overscroll.enabled", true);
pref("apz.overscroll.fling_friction", "0.05");
pref("apz.overscroll.fling_stopped_threshold", "0.4");
pref("apz.overscroll.stretch_factor", "0.5");
pref("apz.overscroll.snap_back.spring_stiffness", "0.05");
pref("apz.overscroll.snap_back.spring_friction", "0.1");
pref("apz.overscroll.snap_back.mass", "100");
pref("apz.overscroll.spring_stiffness", "0.001");
pref("apz.overscroll.spring_friction", "0.015");
pref("apz.overscroll.stop_distance_threshold", "5.0");
pref("apz.overscroll.stop_velocity_threshold", "0.01");
// This preference allows FirefoxOS apps (and content, I think) to force
// the use of software (instead of hardware accelerated) 2D canvases by

Просмотреть файл

@ -91,6 +91,37 @@
buttonEl.disabled = true;
}
function toggleDisplay(node) {
toggle = {
'': 'block',
'none': 'block',
'block': 'none'
};
node.style.display = toggle[node.style.display];
}
function showCertificateErrorReporting() {
// Display error reporting UI
document.getElementById('certificateErrorReporting').style.display = 'block';
// Get the hostname and add it to the panel
document.getElementById('hostname').textContent = document.location.hostname;
// Register click handler for the certificateErrorReportingPanel
document.getElementById('showCertificateErrorReportingPanel')
.addEventListener('click', function togglePanelVisibility() {
var panel = document.getElementById('certificateErrorReportingPanel');
toggleDisplay(panel);
});
}
function sendErrorReport() {
var event = new CustomEvent("AboutNetErrorSendReport", {bubbles:true});
document.dispatchEvent(event);
}
function initPage()
{
var err = getErrorCode();
@ -161,6 +192,37 @@
document.getElementById("errorTryAgain").style.display = "none";
}
window.addEventListener("AboutNetErrorOptions", function(evt) {
// Pinning errors are of type nssFailure2 (don't ask me why)
if (getErrorCode() == "nssFailure2") {
// TODO: and the pref is set...
var options = JSON.parse(evt.detail);
if (options && options.enabled) {
var checkbox = document.getElementById('automaticallyReportInFuture');
showCertificateErrorReporting();
if (options.automatic) {
// set the checkbox
checkbox.checked = true;
}
checkbox.addEventListener('change', function(evt) {
var event = new CustomEvent("AboutNetErrorSetAutomatic",
{bubbles:true, detail:evt.target.checked});
document.dispatchEvent(event);
}, false);
var reportBtn = document.getElementById('reportCertificateError');
var retryBtn = document.getElementById('reportCertificateErrorRetry');
reportBtn.addEventListener('click', sendErrorReport, false);
retryBtn.addEventListener('click', sendErrorReport, false);
}
}
}.bind(this), true, true);
var event = new CustomEvent("AboutNetErrorLoad", {bubbles:true});
document.dispatchEvent(event);
if (err == "nssBadCert") {
// Remove the "Try again" button for security exceptions, since it's
// almost certainly useless.
@ -348,6 +410,7 @@
<a id="securityOverrideLink" href="javascript:showSecuritySection();" >&securityOverride.linkText;</a>
<div id="securityOverrideContent" style="display: none;">&securityOverride.warningContent;</div>
</div>
</div>
<!-- Retry Button -->
@ -368,6 +431,28 @@
}
</script>
<!-- UI for option to report certificate errors to Mozilla. Removed on
init for other error types .-->
<div id="certificateErrorReporting">
<a id="showCertificateErrorReportingPanel" href="#">&errorReporting.title;<span class="downArrow"></span></a>
</div>
<div id="certificateErrorReportingPanel">
<p>&errorReporting.longDesc;</p>
<p>
<input type="checkbox" id="automaticallyReportInFuture" />
<label for="automaticallyReportInFuture" id="automaticallyReportInFuture">&errorReporting.automatic;</label>
</p>
<!-- TODO add link to relevant page on sumo -->
<a href="https://support.mozilla.org/kb/certificate-pinning-reports" target="new">&errorReporting.learnMore;</a>
<span id="reportingState">
<button id="reportCertificateError">&errorReporting.report;</button>
<button id="reportCertificateErrorRetry">&errorReporting.tryAgain;</button>
<span id="reportSendingMessage">&errorReporting.sending;</span>
<span id="reportSentMessage">&errorReporting.sent;</span>
</span>
</div>
</div>
<!--

Просмотреть файл

@ -5,6 +5,7 @@
let Ci = Components.interfaces;
let Cu = Components.utils;
let Cc = Components.classes;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/NotificationDB.jsm");
@ -47,6 +48,9 @@ var gMultiProcessBrowser =
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsILoadContext)
.useRemoteTabs;
var gAppInfo = Cc["@mozilla.org/xre/app-info;1"]
.getService(Ci.nsIXULAppInfo)
.QueryInterface(Ci.nsIXULRuntime);
#ifndef XP_MACOSX
var gEditUIVisible = true;
@ -2417,6 +2421,8 @@ let BrowserOnClick = {
mm.addMessageListener("Browser:CertExceptionError", this);
mm.addMessageListener("Browser:SiteBlockedError", this);
mm.addMessageListener("Browser:NetworkError", this);
mm.addMessageListener("Browser:SendSSLErrorReport", this);
mm.addMessageListener("Browser:SetSSLErrorReportAuto", this);
},
uninit: function () {
@ -2424,6 +2430,8 @@ let BrowserOnClick = {
mm.removeMessageListener("Browser:CertExceptionError", this);
mm.removeMessageListener("Browser:SiteBlockedError", this);
mm.removeMessageListener("Browser:NetworkError", this);
mm.removeMessageListener("Browser:SendSSLErrorReport", this);
mm.removeMessageListener("Browser:SetSSLErrorReportAuto", this);
},
handleEvent: function (event) {
@ -2462,9 +2470,124 @@ let BrowserOnClick = {
// Reset network state, the error page will refresh on its own.
Services.io.offline = false;
break;
case "Browser:SendSSLErrorReport":
this.onSSLErrorReport(msg.target, msg.data.elementId,
msg.data.documentURI,
msg.data.location,
msg.data.securityInfo);
break;
case "Browser:SetSSLErrorReportAuto":
Services.prefs.setBoolPref("security.ssl.errorReporting.automatic", msg.json.automatic);
break;
}
},
onSSLErrorReport: function(browser, elementId, documentURI, location, securityInfo) {
function showReportStatus(reportStatus) {
gBrowser.selectedBrowser
.messageManager
.sendAsyncMessage("Browser:SSLErrorReportStatus",
{
reportStatus: reportStatus,
documentURI: documentURI
});
}
if (!Services.prefs.getBoolPref("security.ssl.errorReporting.enabled")) {
showReportStatus("error");
Cu.reportError("User requested certificate error report sending, but certificate error reporting is disabled");
return;
}
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Ci.nsISerializationHelper);
let transportSecurityInfo = serhelper.deserializeObject(securityInfo);
transportSecurityInfo.QueryInterface(Ci.nsITransportSecurityInfo)
if (transportSecurityInfo.failedCertChain == null) {
Cu.reportError("transportSecurityInfo didn't have a failedCertChain for a failedChannel");
return;
}
showReportStatus("activity");
/*
* Requested info for the report:
* - Domain of bad connection
* - Error type (e.g. Pinning, domain mismatch, etc)
* - Cert chain (at minimum, same data to distrust each cert in the
* chain)
* - Request data (e.g. User Agent, IP, Timestamp)
*
* The request data should be added to the report by the receiving server.
*/
// TODO: can we pull this in from pippki.js isntead of duplicating it
// here?
function getDERString(cert)
{
var length = {};
var derArray = cert.getRawDER(length);
var derString = '';
for (var i = 0; i < derArray.length; i++) {
derString += String.fromCharCode(derArray[i]);
}
return derString;
}
// Convert the nsIX509CertList into a format that can be parsed into
// JSON
let asciiCertChain = [];
let certs = transportSecurityInfo.failedCertChain.getEnumerator();
while (certs.hasMoreElements()) {
let cert = certs.getNext();
cert.QueryInterface(Ci.nsIX509Cert);
asciiCertChain.push(btoa(getDERString(cert)));
}
let report = {
hostname: location.hostname,
port: location.port,
timestamp: Math.round(Date.now() / 1000),
errorCode: transportSecurityInfo.errorCode,
failedCertChain: asciiCertChain,
userAgent: window.navigator.userAgent,
version: 1,
build: gAppInfo.appBuildID,
product: gAppInfo.name,
channel: Services.prefs.getCharPref("app.update.channel")
}
let reportURL = Services.prefs.getCharPref("security.ssl.errorReporting.url");
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
try {
xhr.open("POST", reportURL);
} catch (e) {
Cu.reportError("xhr.open exception", e);
showReportStatus("error");
}
xhr.onerror = function (e) {
// error making request to reportURL
Cu.reportError("xhr onerror", e);
showReportStatus("error");
};
xhr.onload = function (event) {
if (xhr.status !== 201 && xhr.status !== 0) {
// request returned non-success status
Cu.reportError("xhr returned failure code", xhr.status);
showReportStatus("error");
} else {
showReportStatus("complete");
}
};
xhr.send(JSON.stringify(report));
},
onAboutCertError: function (browser, elementId, isTopFrame, location, sslStatusAsString) {
let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");

Просмотреть файл

@ -122,6 +122,113 @@ if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
}
let AboutNetErrorListener = {
init: function(chromeGlobal) {
chromeGlobal.addEventListener('AboutNetErrorLoad', this, false, true);
chromeGlobal.addEventListener('AboutNetErrorSetAutomatic', this, false, true);
chromeGlobal.addEventListener('AboutNetErrorSendReport', this, false, true);
},
get isAboutNetError() {
return content.document.documentURI.startsWith("about:neterror");
},
handleEvent: function(aEvent) {
if (!this.isAboutNetError) {
return;
}
switch (aEvent.type) {
case "AboutNetErrorLoad":
this.onPageLoad(aEvent);
break;
case "AboutNetErrorSetAutomatic":
this.onSetAutomatic(aEvent);
break;
case "AboutNetErrorSendReport":
this.onSendReport(aEvent);
break;
}
},
onPageLoad: function(evt) {
let automatic = Services.prefs.getBoolPref("security.ssl.errorReporting.automatic");
content.dispatchEvent(new content.CustomEvent("AboutNetErrorOptions", {
detail: JSON.stringify({
enabled: Services.prefs.getBoolPref("security.ssl.errorReporting.enabled"),
automatic: automatic
})
}
));
if (automatic) {
this.onSendReport(evt);
}
},
onSetAutomatic: function(evt) {
sendAsyncMessage("Browser:SetSSLErrorReportAuto", {
automatic: evt.detail
});
},
onSendReport: function(evt) {
let contentDoc = content.document;
let reportSendingMsg = contentDoc.getElementById("reportSendingMessage");
let reportSentMsg = contentDoc.getElementById("reportSentMessage");
let reportBtn = contentDoc.getElementById("reportCertificateError");
let retryBtn = contentDoc.getElementById("reportCertificateErrorRetry");
addMessageListener("Browser:SSLErrorReportStatus", function(message) {
// show and hide bits - but only if this is a message for the right
// document - we'll compare on document URI
if (contentDoc.documentURI === message.data.documentURI) {
switch(message.data.reportStatus) {
case "activity":
// Hide the button that was just clicked
reportBtn.style.display = "none";
retryBtn.style.display = "none";
reportSentMsg.style.display = "none";
reportSendingMsg.style.display = "inline";
break;
case "error":
// show the retry button
retryBtn.style.display = "inline";
reportSendingMsg.style.display = "none";
break;
case "complete":
// Show a success indicator
reportSentMsg.style.display = "inline";
reportSendingMsg.style.display = "none";
break;
}
}
});
let failedChannel = docShell.failedChannel;
let location = contentDoc.location.href;
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Ci.nsISerializationHelper);
let serializable = docShell.failedChannel.securityInfo
.QueryInterface(Ci.nsITransportSecurityInfo)
.QueryInterface(Ci.nsISerializable);
let serializedSecurityInfo = serhelper.serializeToString(serializable);
sendAsyncMessage("Browser:SendSSLErrorReport", {
elementId: evt.target.id,
documentURI: contentDoc.documentURI,
location: contentDoc.location,
securityInfo: serializedSecurityInfo
});
}
}
AboutNetErrorListener.init(this);
let AboutHomeListener = {
init: function(chromeGlobal) {
chromeGlobal.addEventListener('AboutHomeLoad', this, false, true);

Просмотреть файл

@ -0,0 +1,46 @@
.. _healthreport_dataformat:
==============
Payload Format
==============
An example report::
{
"timestamp":1413490449,
"errorCode":-16384,
"failedCertChain":[
],
"userAgent":"Mozilla/5.0 (X11; Linux x86_64; rv:36.0) Gecko/20100101 Firefox/36.0",
"version":1,
"build":"20141022164419",
"product":"Firefox",
"channel":"default"
}
Where the data represents the following:
"timestamp"
The (local) time at which the report was generated. Seconds since 1 Jan 1970,
UTC.
"errorCode"
The error code. This is the error code from certificate verification. Here's a small list of the most commonly-encountered errors:
https://wiki.mozilla.org/SecurityEngineering/x509Certs#Error_Codes_in_Firefox
In theory many of the errors from sslerr.h, secerr.h, and pkixnss.h could be encountered. We're starting with just MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE, which means that key pinning failed (i.e. there wasn't an intersection between the keys in any computed trusted certificate chain and the expected list of keys for the domain the user is attempting to connect to).
"failedCertChain"
The certificate chain which caused the pinning violation (array of base64
encoded PEM)
"user agent"
The user agent string of the browser sending the report
"build"
The build ID
"product"
The product name
"channel"
The user's release channel

Просмотреть файл

@ -0,0 +1,15 @@
.. _sslerrorreport
===================
SSL Error Reporting
===================
With the introduction of HPKP, it becomes useful to be able to capture data
on pin violations. SSL Error Reporting is an opt-in mechanism to allow users
to send data on such violations to mozilla.
.. toctree::
:maxdepth: 1
dataformat
preferences

Просмотреть файл

@ -0,0 +1,23 @@
.. _healthreport_preferences:
===========
Preferences
===========
The following preferences are used by SSL Error reporting:
"security.ssl.errorReporting.enabled"
Should the SSL Error Reporting UI be shown on pin violations? Default
value: ``true``
"security.ssl.errorReporting.url"
Where should SSL error reports be sent? Default value:
``https://data.mozilla.com/submit/sslreports-stg``
"security.ssl.errorReporting.automatic"
Should error reports be sent without user interaction. Default value:
``false``. Note: this pref is overridden by the value of
``security.ssl.errorReporting.enabled``
This is only set when specifically requested by the user. The user can set
this value (or unset it) by checking the "Automatically report errors in the
future" checkbox when about:neterror is displayed for SSL Errors.

Просмотреть файл

@ -257,23 +257,15 @@ function securityOnLoad() {
msg1 = pkiBundle.getString("pageInfo_Privacy_Mixed1");
msg2 = pkiBundle.getString("pageInfo_Privacy_None2");
}
else if (info.encryptionStrength >= 90) {
hdr = pkiBundle.getFormattedString("pageInfo_StrongEncryptionWithBitsAndProtocol",
else if (info.encryptionStrength > 0) {
hdr = pkiBundle.getFormattedString("pageInfo_EncryptionWithBitsAndProtocol",
[info.encryptionAlgorithm,
info.encryptionStrength + "",
info.version]);
msg1 = pkiBundle.getString("pageInfo_Privacy_Strong1");
msg2 = pkiBundle.getString("pageInfo_Privacy_Strong2");
msg1 = pkiBundle.getString("pageInfo_Privacy_Encrypted1");
msg2 = pkiBundle.getString("pageInfo_Privacy_Encrypted2");
security._cert = info.cert;
}
else if (info.encryptionStrength > 0) {
hdr = pkiBundle.getFormattedString("pageInfo_WeakEncryptionWithBitsAndProtocol",
[info.encryptionAlgorithm,
info.encryptionStrength + "",
info.version]);
msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_Weak1", [info.hostName]);
msg2 = pkiBundle.getString("pageInfo_Privacy_Weak2");
}
else {
hdr = pkiBundle.getString("pageInfo_NoEncryption");
if (info.hostName != null)

Просмотреть файл

@ -10,6 +10,7 @@ support-files =
browser_bug479408_sample.html
browser_bug678392-1.html
browser_bug678392-2.html
browser_bug846489_content.js
browser_bug970746.xhtml
browser_fxa_oauth.html
browser_registerProtocolHandler_notification.html
@ -65,6 +66,7 @@ support-files =
page_style_sample.html
parsingTestHelpers.jsm
pinning_headers.sjs
pinning_reports.sjs
popup_blocker.html
print_postdata.sjs
redirect_bug623155.sjs
@ -152,6 +154,7 @@ skip-if = e10s # Bug ?????? - no about:home support yet
[browser_bug419612.js]
skip-if = e10s # Bug 691614 - no e10s zoom support yet
[browser_bug422590.js]
[browser_bug846489.js]
[browser_bug423833.js]
skip-if = true # bug 428712
[browser_bug424101.js]

Просмотреть файл

@ -0,0 +1,327 @@
var badPin = "https://include-subdomains.pinning.example.com";
var enabledPref = false;
var automaticPref = false;
var urlPref = "security.ssl.errorReporting.url";
var enforcement_level = 1;
function loadFrameScript() {
let mm = Cc["@mozilla.org/globalmessagemanager;1"]
.getService(Ci.nsIMessageListenerManager);
const ROOT = getRootDirectory(gTestPath);
mm.loadFrameScript(ROOT+"browser_bug846489_content.js", true);
}
add_task(function*(){
waitForExplicitFinish();
loadFrameScript();
SimpleTest.requestCompleteLog();
yield testSendReportDisabled();
yield testSendReportManual();
yield testSendReportAuto();
yield testSendReportError();
yield testSetAutomatic();
});
// creates a promise of the message in an error page
function createNetworkErrorMessagePromise(aBrowser) {
return new Promise(function(resolve, reject) {
// Error pages do not fire "load" events, so use a progressListener.
var originalDocumentURI = aBrowser.contentDocument.documentURI;
var progressListener = {
onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) {
// Make sure nothing other than an error page is loaded.
if (!(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE)) {
reject("location change was not to an error page");
}
},
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
let doc = aBrowser.contentDocument;
if (doc.getElementById("reportCertificateError")) {
// Wait until the documentURI changes (from about:blank) this should
// be the error page URI.
var documentURI = doc.documentURI;
if (documentURI == originalDocumentURI) {
return;
}
aWebProgress.removeProgressListener(progressListener,
Ci.nsIWebProgress.NOTIFY_LOCATION |
Ci.nsIWebProgress.NOTIFY_STATE_REQUEST);
var matchArray = /about:neterror\?.*&d=([^&]*)/.exec(documentURI);
if (!matchArray) {
reject("no network error message found in URI")
return;
}
var errorMsg = matchArray[1];
resolve(decodeURIComponent(errorMsg));
}
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference])
};
aBrowser.addProgressListener(progressListener,
Ci.nsIWebProgress.NOTIFY_LOCATION |
Ci.nsIWebProgress.NOTIFY_STATE_REQUEST);
});
}
// check we can set the 'automatically send' pref
let testSetAutomatic = Task.async(function*() {
setup();
let tab = gBrowser.addTab(badPin, {skipAnimation: true});
let browser = tab.linkedBrowser;
let mm = browser.messageManager;
gBrowser.selectedTab = tab;
// ensure we have the correct error message from about:neterror
let netError = createNetworkErrorMessagePromise(browser);
yield netError;
// ensure that setting automatic when unset works
let prefEnabled = new Promise(function(resolve, reject){
mm.addMessageListener("ssler-test:AutoPrefUpdated", function() {
if (Services.prefs.getBoolPref("security.ssl.errorReporting.automatic")) {
resolve();
} else {
reject();
}
});
});
mm.sendAsyncMessage("ssler-test:SetAutoPref",{value:true});
yield prefEnabled;
// ensure un-setting automatic, when set, works
let prefDisabled = new Promise(function(resolve, reject){
mm.addMessageListener("ssler-test:AutoPrefUpdated", function () {
if (!Services.prefs.getBoolPref("security.ssl.errorReporting.automatic")) {
resolve();
} else {
reject();
}
});
});
mm.sendAsyncMessage("ssler-test:SetAutoPref",{value:false});
yield prefDisabled;
gBrowser.removeTab(tab);
cleanup();
});
// test that manual report sending (with button clicks) works
let testSendReportManual = Task.async(function*() {
setup();
Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", true);
Services.prefs.setCharPref("security.ssl.errorReporting.url", "https://example.com/browser/browser/base/content/test/general/pinning_reports.sjs?succeed");
let tab = gBrowser.addTab(badPin, {skipAnimation: true});
let browser = tab.linkedBrowser;
let mm = browser.messageManager;
gBrowser.selectedTab = tab;
// ensure we have the correct error message from about:neterror
let netError = createNetworkErrorMessagePromise(browser);
yield netError;
netError.then(function(val){
is(val.startsWith("An error occurred during a connection to include-subdomains.pinning.example.com"), true ,"ensure the correct error message came from about:neterror");
});
// Check the report starts on click
let btn = browser.contentDocument.getElementById("reportCertificateError");
// check the content script sends the message to report
let reportWillStart = new Promise(function(resolve, reject){
mm.addMessageListener("Browser:SendSSLErrorReport", function() {
resolve();
});
});
let deferredReportActivity = Promise.defer()
let deferredReportSucceeds = Promise.defer();
// ensure we see the correct statuses in the correct order...
mm.addMessageListener("ssler-test:SSLErrorReportStatus", function(message) {
switch(message.data.reportStatus) {
case "activity":
deferredReportActivity.resolve(message.data.reportStatus);
break;
case "complete":
deferredReportSucceeds.resolve(message.data.reportStatus);
break;
case "error":
deferredReportSucceeds.reject();
deferredReportActivity.reject();
break;
}
});
// ... once the button is clicked, that is
mm.sendAsyncMessage("ssler-test:SendBtnClick",{});
yield reportWillStart;
yield deferredReportActivity.promise;
yield deferredReportSucceeds.promise;
gBrowser.removeTab(tab);
cleanup();
});
// test that automatic sending works
let testSendReportAuto = Task.async(function*() {
setup();
Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", true);
Services.prefs.setBoolPref("security.ssl.errorReporting.automatic", true);
Services.prefs.setCharPref("security.ssl.errorReporting.url", "https://example.com/browser/browser/base/content/test/general/pinning_reports.sjs?succeed");
let tab = gBrowser.addTab(badPin, {skipAnimation: true});
let browser = tab.linkedBrowser;
let mm = browser.messageManager;
gBrowser.selectedTab = tab;
let reportWillStart = Promise.defer();
mm.addMessageListener("Browser:SendSSLErrorReport", function() {
reportWillStart.resolve();
});
let deferredReportActivity = Promise.defer();
let deferredReportSucceeds = Promise.defer();
mm.addMessageListener("ssler-test:SSLErrorReportStatus", function(message) {
switch(message.data.reportStatus) {
case "activity":
deferredReportActivity.resolve(message.data.reportStatus);
break;
case "complete":
deferredReportSucceeds.resolve(message.data.reportStatus);
break;
case "error":
deferredReportSucceeds.reject();
deferredReportActivity.reject();
break;
}
});
// Ensure the error page loads
let netError = createNetworkErrorMessagePromise(browser);
yield netError;
// Ensure the reporting steps all occur with no interaction
yield reportWillStart;
yield deferredReportActivity.promise;
yield deferredReportSucceeds.promise;
gBrowser.removeTab(tab);
cleanup();
});
// test that an error is shown if there's a problem with the report server
let testSendReportError = Task.async(function*() {
setup();
Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", true);
Services.prefs.setBoolPref("security.ssl.errorReporting.automatic", true);
Services.prefs.setCharPref("security.ssl.errorReporting.url", "https://example.com/browser/browser/base/content/test/general/pinning_reports.sjs?error");
let tab = gBrowser.addTab(badPin, {skipAnimation: true});
let browser = tab.linkedBrowser;
let mm = browser.messageManager;
gBrowser.selectedTab = tab;
// check the report send starts....
let reportWillStart = new Promise(function(resolve, reject){
mm.addMessageListener("Browser:SendSSLErrorReport", function() {
resolve();
});
});
let netError = createNetworkErrorMessagePromise(browser);
yield netError;
yield reportWillStart;
// and that errors are seen
let reportErrors = new Promise(function(resolve, reject) {
mm.addMessageListener("ssler-test:SSLErrorReportStatus", function(message) {
switch(message.data.reportStatus) {
case "complete":
reject(message.data.reportStatus);
break;
case "error":
resolve(message.data.reportStatus);
break;
}
});
});
yield reportErrors;
gBrowser.removeTab(tab);
cleanup();
});
let testSendReportDisabled = Task.async(function*() {
setup();
Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", false);
Services.prefs.setCharPref("security.ssl.errorReporting.url", "https://offdomain.com");
let tab = gBrowser.addTab(badPin, {skipAnimation: true});
let browser = tab.linkedBrowser;
let mm = browser.messageManager;
gBrowser.selectedTab = tab;
// Ensure we have an error page
let netError = createNetworkErrorMessagePromise(browser);
yield netError;
let reportErrors = new Promise(function(resolve, reject) {
mm.addMessageListener("ssler-test:SSLErrorReportStatus", function(message) {
switch(message.data.reportStatus) {
case "complete":
reject(message.data.reportStatus);
break;
case "error":
resolve(message.data.reportStatus);
break;
}
});
});
// click the button
mm.sendAsyncMessage("ssler-test:SendBtnClick",{forceUI:true});
// check we get an error
yield reportErrors;
gBrowser.removeTab(tab);
cleanup();
});
function setup() {
// ensure the relevant prefs are set
enabledPref = Services.prefs.getBoolPref("security.ssl.errorReporting.enabled");
automaticPref = Services.prefs.getBoolPref("security.ssl.errorReporting.automatic");
urlPref = Services.prefs.getCharPref("security.ssl.errorReporting.url");
enforcement_level = Services.prefs.getIntPref("security.cert_pinning.enforcement_level");
Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 2);
}
function cleanup() {
// reset prefs for other tests in the run
Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", enabledPref);
Services.prefs.setBoolPref("security.ssl.errorReporting.automatic", automaticPref);
Services.prefs.setCharPref("security.ssl.errorReporting.url", urlPref);
}

Просмотреть файл

@ -0,0 +1,25 @@
addMessageListener("Browser:SSLErrorReportStatus", function(message) {
sendSyncMessage("ssler-test:SSLErrorReportStatus", {reportStatus:message.data.reportStatus});
});
addMessageListener("ssler-test:SetAutoPref", function(message) {
let checkbox = content.document.getElementById("automaticallyReportInFuture");
// we use "click" because otherwise the 'changed' event will not fire
if (checkbox.checked != message.data.value) {
checkbox.click();
}
sendSyncMessage("ssler-test:AutoPrefUpdated", {});
});
addMessageListener("ssler-test:SendBtnClick", function(message) {
if (message.data && message.data.forceUI) {
content.dispatchEvent(new content.CustomEvent("AboutNetErrorOptions",
{
detail: "{\"enabled\": true, \"automatic\": false}"
}));
}
let btn = content.document.getElementById("reportCertificateError");
btn.click();
});

Просмотреть файл

@ -0,0 +1,41 @@
const EXPECTED_CHAIN = [
"MIIDCjCCAfKgAwIBAgIENUiGYDANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDExtBbHRlcm5hdGUgVHJ1c3RlZCBBdXRob3JpdHkwHhcNMTQxMDAxMjExNDE5WhcNMjQxMDAxMjExNDE5WjAxMS8wLQYDVQQDEyZpbmNsdWRlLXN1YmRvbWFpbnMucGlubmluZy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALxYrge8C4eVfTb6/lJ4k/+/4J6wlnWpp5Szxy1MHhsLB+LJh/HRHqkO/tsigT204kTeU3dxuAfQHz0g+Td8dr6KICLLNVFUPw+XjhBV4AtxV8wcprs6EmdBhJgAjkFB4M76BL7/Ow0NfH012WNESn8TTbsp3isgkmrXjTZhWR33vIL1eDNimykp/Os/+JO+x9KVfdCtDCrPwO9Yusial5JiaW7qemRtVuUDL87NSJ7xokPEOSc9luv/fBamZ3rgqf3K6epqg+0o3nNCCcNFnfLW52G0t69+dIjr39WISHnqqZj3Sb7JPU6OmxTd13ByoLkoM3ZUQ2Lpas+RJvQyGXkCAwEAAaM1MDMwMQYDVR0RBCowKIImaW5jbHVkZS1zdWJkb21haW5zLnBpbm5pbmcuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQELBQADggEBAAmzXfeoOS59FkNABRonFPRyFl7BoGpVJENUteFfTa2pdAhGYdo19Y4uILTTj+vtDAa5yryb5Uvd+YuJnExosbMMkzCrmZ9+VJCJdqUTb+idwk9/sgPl2gtGeRmefB0hXSUFHc/p1CDufSpYOmj9NCUZD2JEsybgJQNulkfAsVnS3lzDcxAwcO+RC/1uJDSiUtcBpWS4FW58liuDYE7PD67kLJHZPVUV2WCMuIl4VM2tKPtvShz1JkZ5UytOLs6jPfviNAk/ftXczaE2/RJgM2MnDX9nGzOxG6ONcVNCljL8avhFBCosutE6i5LYSZR6V14YY/xOn15WDSuWdnIsJCo=",
"MIIC2jCCAcKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDExtBbHRlcm5hdGUgVHJ1c3RlZCBBdXRob3JpdHkwHhcNMTQwOTI1MjEyMTU0WhcNMjQwOTI1MjEyMTU0WjAmMSQwIgYDVQQDExtBbHRlcm5hdGUgVHJ1c3RlZCBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBT+BwAhO52IWgSIdZZifU9LHOs3IR/+8DCC0WP5d/OuyKlZ6Rqd0tsd3i7durhQyjHSbLf2lJStcnFjcVEbEnNI76RuvlN8xLLn5eV+2Ayr4cZYKztudwRmw+DV/iYAiMSy0hs7m3ssfX7qpoi1aNRjUanwU0VTCPQhF1bEKAC2du+C5Z8e92zN5t87w7bYr7lt+m8197XliXEu+0s9RgnGwGaZ296BIRz6NOoJYTa43n06LU1I1+Z4d6lPdzUFrSR0GBaMhUSurUBtOin3yWiMhg1VHX/KwqGc4als5GyCVXy8HGrA/0zQPOhetxrlhEVAdK/xBt7CZvByj1Rcc7AgMBAAGjEzARMA8GA1UdEwQIMAYBAf8CAQAwDQYJKoZIhvcNAQELBQADggEBAJq/hogSRqzPWTwX4wTn/DVSNdWwFLv53qep9YrSMJ8ZsfbfK9Es4VP4dBLRQAVMJ0Z5mW1I6d/n0KayTanuUBvemYdxPi/qQNSs8UJcllqdhqWzmzAg6a0LxrMnEeKzPBPD6q8PwQ7tYP+B4sBN9tnnsnyPgti9ZiNZn5FwXZliHXseQ7FE9/SqHlLw5LXW3YtKjuti6RmuV6fq3j+D4oeC5vb1mKgIyoTqGN6ze57v8RHi+pQ8Q+kmoUn/L3Z2YmFe4SKN/4WoyXr8TdejpThGOCGCAd3565s5gOx5QfSQX11P8NZKO8hcN0tme3VzmGpHK0Z/6MTmdpNaTwQ6odk="
];
function handleRequest(request, response)
{
if (request.queryString === "succeed") {
// read the report from the client
let inputStream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
inputStream.init(request.bodyInputStream, 0x01, 0004, 0);
let body = "";
if (inputStream) {
while (inputStream.available()) {
body = body + inputStream.read(inputStream.available());
}
}
// parse the report
let report = JSON.parse(body);
let certChain = report.failedCertChain;
// ensure the cert chain is what we expect
for (idx in certChain) {
if (certChain[idx] !== EXPECTED_CHAIN[idx]) {
// if the chain differs, send an error response to cause test
// failure
response.setStatusLine("1.1", 500, "Server error");
response.write("<html>The report contained an unexpected chain</html>");
return;
}
}
// if all is as expected, send the 201 the client expects
response.setStatusLine("1.1", 201, "Created");
response.write("<html>OK</html>");
} else if (request.queryString === "error") {
response.setStatusLine("1.1", 500, "Server error");
response.write("<html>server error</html>");
}
}

Просмотреть файл

@ -4,6 +4,8 @@
# 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/.
SPHINX_TREES['sslerrorreport'] = 'content/docs/sslerrorreport'
MOCHITEST_MANIFESTS += [
'content/test/general/mochitest.ini',
]

Просмотреть файл

@ -6,7 +6,8 @@
let tmp = {};
Cu.import("resource:///modules/translation/Translation.jsm", tmp);
let {Translation} = tmp;
Cu.import("resource://gre/modules/Promise.jsm", tmp);
let {Translation, Promise} = tmp;
const kLanguagesPref = "browser.translation.neverForLanguages";
const kShowUIPref = "browser.translation.ui.show";

Просмотреть файл

@ -6,8 +6,8 @@
"filename": "mozmake.exe"
},
{
"size": 51,
"digest": "c8e40edb314eeabfb92c77cf5ff9a7857033f15dd65a00349bcf9e3e5b75624afc71f733b2ff7e029c20a78313038409c2bd022bf7e5a7e0c487fc2c2d640986",
"size": 176,
"digest": "2809058907ac5eefdc394113d2e4fe76ba559ac61c2eca2f88e7a12a74bdf44a15d9039fa8aa229f7362a14b67d67395063f68147ae098beac5dfcc78aff98da",
"algorithm": "sha512",
"filename": "setup.sh"
},

Просмотреть файл

@ -35,9 +35,8 @@ function addTab(aURL, aCallback)
}
function promiseTab(aURL) {
let deferred = Promise.defer();
addTab(aURL, deferred.resolve);
return deferred.promise;
return new Promise(resolve =>
addTab(aURL, resolve));
}
registerCleanupFunction(function tearDown() {
@ -138,11 +137,11 @@ function* createHost(type = "bottom", src = "data:text/html;charset=utf-8,") {
let host = new Hosts[type](gBrowser.selectedTab);
let iframe = yield host.create();
let loaded = Promise.defer();
let domHelper = new DOMHelpers(iframe.contentWindow);
iframe.setAttribute("src", src);
domHelper.onceDOMReady(loaded.resolve);
yield loaded.promise;
yield new Promise(resolve => {
let domHelper = new DOMHelpers(iframe.contentWindow);
iframe.setAttribute("src", src);
domHelper.onceDOMReady(resolve);
});
return [host, iframe.contentWindow, iframe.contentDocument];
}

Просмотреть файл

@ -193,5 +193,14 @@ functionality specific to firefox. -->
<button id='exceptionDialogButton'>&securityOverride.exceptionButtonLabel;</button>
">
<!ENTITY errorReporting.title "Report this error">
<!ENTITY errorReporting.longDesc "Reporting the address and certificate information for <span id='hostname'></span> will help us identify and block malicious sites. Thanks for helping create a safer web!">
<!ENTITY errorReporting.automatic "Automatically report errors in the future">
<!ENTITY errorReporting.learnMore "Learn more…">
<!ENTITY errorReporting.sending "Sending report">
<!ENTITY errorReporting.sent "Report sent">
<!ENTITY errorReporting.report "Report">
<!ENTITY errorReporting.tryAgain "Try again">
<!ENTITY remoteXUL.title "Remote XUL">
<!ENTITY remoteXUL.longDesc "<p><ul><li>Please contact the website owners to inform them of this problem.</li></ul></p>">

Просмотреть файл

@ -67,3 +67,75 @@ ul {
button:disabled {
cursor: pointer;
}
div#certificateErrorReporting {
display: none;
float:right;
/* Align with the "Try Again" button */
margin-top:24px;
margin-right:24px;
}
div#certificateErrorReporting a,
div#certificateErrorReportingPanel a {
color: #0095DD;
}
div#certificateErrorReporting a {
text-decoration: none;
}
div#certificateErrorReporting a:hover {
text-decoration: underline;
}
span.downArrow {
font-size: 0.9em;
}
div#certificateErrorReportingPanel {
/* Hidden until the link is clicked */
display: none;
background-color: white;
border: 1px lightgray solid;
/* Don't use top padding because the default p style has top padding, and it
* makes the overall div look uneven */
padding: 0 12px 12px 12px;
box-shadow: 0 0 4px #ddd;
position: relative;
width: 75%;
left: 34%;
font-size: 0.9em;
top: 8px;
}
span#hostname {
font-weight: bold;
}
#automaticallyReportInFuture {
cursor: pointer;
}
#reportingState {
padding-left: 150px;
}
#reportSendingMessage {
position: relative;
display: none;
}
#reportSentMessage {
position: relative;
display: none;
}
button#reportCertificateError {
position: relative;
}
button#reportCertificateErrorRetry {
position: relative;
display: none;
}

Двоичные данные
build/pgo/certs/cert8.db

Двоичный файл не отображается.

Двоичные данные
build/pgo/certs/key3.db

Двоичный файл не отображается.

Просмотреть файл

@ -227,3 +227,5 @@ https://marketplace.allizom.org:443 privileged
https://include-subdomains.pinning-dynamic.example.com:443 privileged,cert=dynamicPinningGood
https://bad.include-subdomains.pinning-dynamic.example.com:443 privileged,cert=dynamicPinningBad
# Host for static pin tests
https://include-subdomains.pinning.example.com:443 privileged,cert=staticPinningBad

1
config/external/nss/nss.def поставляемый
Просмотреть файл

@ -146,7 +146,6 @@ CERT_StartCertificateRequestAttributes
CERT_SubjectPublicKeyInfoTemplate DATA
CERT_TimeChoiceTemplate DATA
CERT_VerifyCertificate
CERT_VerifyCertName
CERT_VerifySignedDataWithPublicKeyInfo
DER_AsciiToTime_Util
DER_DecodeTimeChoice_Util

Просмотреть файл

@ -51,7 +51,7 @@ _SUBDIR_CONFIG_ARGS="$ac_configure_args"
dnl Set the version number of the libs included with mozilla
dnl ========================================================
MOZJPEG=62
MOZPNG=10613
MOZPNG=10614
NSPR_VERSION=4
NSPR_MINVER=4.10.3
NSS_VERSION=3
@ -9189,9 +9189,9 @@ if test "$MOZ_TREE_FREETYPE"; then
if ! test -e modules; then
mkdir modules
fi
# Only export CC and CXX for the subconfigure, and avoid spilling that
# further down the road.
(export CC CXX;
# Only export CC, CXX and RANLIB for the subconfigure, and avoid spilling
# that further down the road.
(export CC CXX RANLIB;
AC_OUTPUT_SUBDIRS(modules/freetype2)
) || exit 1
fi

Просмотреть файл

@ -500,6 +500,13 @@ Element::WrapObject(JSContext *aCx)
return obj;
}
/* virtual */
nsINode*
Element::GetScopeChainParent() const
{
return OwnerDoc();
}
nsDOMTokenList*
Element::ClassList()
{

Просмотреть файл

@ -139,8 +139,8 @@ class DestinationInsertionPointList;
// IID for the dom::Element interface
#define NS_ELEMENT_IID \
{ 0xaa79cb98, 0xc785, 0x44c5, \
{ 0x80, 0x80, 0x2e, 0x5f, 0x0c, 0xa5, 0xbd, 0x63 } }
{ 0x31d3f3fb, 0xcdf8, 0x4e40, \
{ 0xb7, 0x09, 0x1a, 0x11, 0x43, 0x93, 0x61, 0x71 } }
class Element : public FragmentOrElement
{
@ -961,6 +961,8 @@ public:
virtual JSObject* WrapObject(JSContext *aCx) MOZ_FINAL MOZ_OVERRIDE;
nsINode* GetScopeChainParent() const MOZ_OVERRIDE;
/**
* Locate an nsIEditor rooted at this content node, if there is one.
*/

Просмотреть файл

@ -136,8 +136,8 @@ typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
} // namespace mozilla
#define NS_IDOCUMENT_IID \
{ 0xbab5b447, 0x7e23, 0x4cdd, \
{ 0xac, 0xe5, 0xaa, 0x04, 0x26, 0x87, 0x2b, 0x97 } }
{ 0x6bbf1955, 0xd9c4, 0x4d61, \
{ 0xbf, 0x75, 0x1b, 0xba, 0x55, 0xf7, 0x99, 0xc2 } }
// Enum for requesting a particular type of document when creating a doc
enum DocumentFlavor {
@ -2877,7 +2877,11 @@ nsINode::OwnerDocAsNode() const
inline mozilla::dom::ParentObject
nsINode::GetParentObject() const
{
return GetParentObjectInternal(OwnerDoc());
mozilla::dom::ParentObject p(OwnerDoc());
// Note that mUseXBLScope is a no-op for chrome, and other places where we
// don't use XBL scopes.
p.mUseXBLScope = IsInAnonymousSubtree() && !IsAnonymousContentInSVGUseSubtree();
return p;
}
#endif /* nsIDocument_h___ */

Просмотреть файл

@ -2752,3 +2752,8 @@ nsINode::HasBoxQuadsSupport(JSContext* aCx, JSObject* /* unused */)
Preferences::GetBool("layout.css.getBoxQuads.enabled");
}
nsINode*
nsINode::GetScopeChainParent() const
{
return nullptr;
}

Просмотреть файл

@ -248,8 +248,8 @@ private:
// IID for the nsINode interface
#define NS_INODE_IID \
{ 0x8deda3f4, 0x0f45, 0x497a, \
{ 0x89, 0x7c, 0xe6, 0x09, 0x12, 0x8a, 0xad, 0xd8 } }
{ 0x66972940, 0x1d1b, 0x4d15, \
{ 0x93, 0x11, 0x96, 0x72, 0x84, 0x2e, 0xc7, 0x27 } }
/**
* An internal interface that abstracts some DOMNode-related parts that both
@ -382,20 +382,16 @@ protected:
*/
virtual JSObject* WrapNode(JSContext *aCx) = 0;
// Subclasses that wish to override the parent behavior should return the
// result of GetParentObjectIntenral, which handles the XBL scope stuff.
//
mozilla::dom::ParentObject GetParentObjectInternal(nsINode* aNativeParent) const {
mozilla::dom::ParentObject p(aNativeParent);
// Note that mUseXBLScope is a no-op for chrome, and other places where we
// don't use XBL scopes.
p.mUseXBLScope = IsInAnonymousSubtree() && !IsAnonymousContentInSVGUseSubtree();
return p;
}
public:
mozilla::dom::ParentObject GetParentObject() const; // Implemented in nsIDocument.h
/**
* Return the scope chain parent for this node, for use in things
* like event handler compilation. Returning null means to use the
* global object as the scope chain parent.
*/
virtual nsINode* GetScopeChainParent() const;
/**
* Return whether the node is an Element node
*/

Просмотреть файл

@ -27,6 +27,8 @@
#include "nsContentUtils.h"
#include "nsGlobalWindow.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ScriptSettings.h"
using namespace mozilla::dom;
@ -313,6 +315,27 @@ nsJSUtils::EvaluateString(JSContext* aCx,
options, &unused, aOffThreadToken);
}
/* static */
bool
nsJSUtils::GetScopeChainForElement(JSContext* aCx,
mozilla::dom::Element* aElement,
JS::AutoObjectVector& aScopeChain)
{
for (nsINode* cur = aElement; cur; cur = cur->GetScopeChainParent()) {
JS::RootedValue val(aCx);
if (!WrapNewBindingObject(aCx, cur, &val)) {
return false;
}
if (!aScopeChain.append(&val.toObject())) {
return false;
}
}
return true;
}
//
// nsDOMJSUtils.h
//

Просмотреть файл

@ -25,6 +25,7 @@ class nsIScriptGlobalObject;
namespace mozilla {
namespace dom {
class AutoJSAPI;
class Element;
}
}
@ -119,6 +120,11 @@ public:
JS::CompileOptions &aCompileOptions,
void **aOffThreadToken = nullptr);
// Returns false if an exception got thrown on aCx. Passing a null
// aElement is allowed; that wil produce an empty aScopeChain.
static bool GetScopeChainForElement(JSContext* aCx,
mozilla::dom::Element* aElement,
JS::AutoObjectVector& aScopeChain);
};
class MOZ_STACK_CLASS AutoDontReportUncaught {

Просмотреть файл

@ -344,7 +344,7 @@ skip-if = buildapp == 'b2g' # b2g(86 total, 4 failing - testing mozAnon - got fa
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(12 total, 2 failing - .mozSystem == true - got false, expected true + ) b2g-desktop(12 total, 2 failing - .mozSystem == true - got false, expected true + )
[test_XHR_timeout.html]
skip-if = buildapp == 'b2g' # b2g(flaky on B2G, bug 960743) b2g-debug(flaky on B2G, bug 960743) b2g-desktop(flaky on B2G, bug 960743)
[test_XHR_timeout.js]
support-files = test_XHR_timeout.js
[test_base.xhtml]
[test_blobconstructor.html]
[test_bug166235.html]
@ -390,7 +390,7 @@ skip-if = e10s # Bug 1081453 - shutdown leaks with e10s and WebIDL dom::File
[test_bug353334.html]
[test_bug355026.html]
[test_bug357450.html]
[test_bug357450.js]
support-files = test_bug357450.js
[test_bug357450.xhtml]
[test_bug357450_svg.xhtml]
[test_bug357509.html]
@ -413,7 +413,7 @@ skip-if = e10s # Bug 1081453 - shutdown leaks with e10s and WebIDL dom::File
[test_bug375314.html]
[test_bug378969.html]
[test_bug380418.html]
[test_bug380418.html^headers^]
support-files = test_bug380418.html^headers^
[test_bug382113.html]
skip-if = (os == 'mac' || os == 'win') && debug # bug 453969
[test_bug382871.html]
@ -428,7 +428,7 @@ skip-if = (os == 'mac' || os == 'win') && debug # bug 453969
[test_bug398243.html]
[test_bug401662.html]
[test_bug402150.html]
[test_bug402150.html^headers^]
support-files = test_bug402150.html^headers^
[test_bug403841.html]
[test_bug403852.html]
skip-if = e10s
@ -507,7 +507,7 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 855762 # b2g(36 total -
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 855762
[test_bug484396.html]
[test_bug493881.html]
[test_bug493881.js]
support-files = test_bug493881.js
[test_bug498240.html]
[test_bug498433.html]
skip-if = buildapp == 'b2g'

Просмотреть файл

@ -1504,22 +1504,6 @@ WrapNativeParent(JSContext* cx, const T& p)
return WrapNativeParent(cx, GetParentPointer(p), GetWrapperCache(p), GetUseXBLScope(p));
}
// A way to differentiate between nodes, which use the parent object
// returned by native->GetParentObject(), and all other objects, which
// just use the parent's global.
static inline JSObject*
GetRealParentObject(void* aParent, JSObject* aParentObject)
{
return aParentObject ?
js::GetGlobalForObjectCrossCompartment(aParentObject) : nullptr;
}
static inline JSObject*
GetRealParentObject(Element* aParent, JSObject* aParentObject)
{
return aParentObject;
}
HAS_MEMBER(GetParentObject)
template<typename T, bool WrapperCached=HasGetParentObjectMember<T>::Value>
@ -1529,9 +1513,8 @@ struct GetParentObject
{
MOZ_ASSERT(js::IsObjectInContextCompartment(obj, cx));
T* native = UnwrapDOMObject<T>(obj);
return
GetRealParentObject(native,
WrapNativeParent(cx, native->GetParentObject()));
JSObject* wrappedParent = WrapNativeParent(cx, native->GetParentObject());
return wrappedParent ? js::GetGlobalForObjectCrossCompartment(wrappedParent) : nullptr;
}
};

Просмотреть файл

@ -3069,24 +3069,23 @@ class CGConstructorEnabled(CGAbstractMethod):
return body.define()
def CreateBindingJSObject(descriptor, properties, parent):
def CreateBindingJSObject(descriptor, properties):
# We don't always need to root obj, but there are a variety
# of cases where we do, so for simplicity, just always root it.
objDecl = "JS::Rooted<JSObject*> obj(aCx);\n"
if descriptor.proxy:
create = fill(
create = dedent(
"""
JS::Rooted<JS::Value> proxyPrivateVal(aCx, JS::PrivateValue(aObject));
js::ProxyOptions options;
options.setClass(&Class.mBase);
obj = NewProxyObject(aCx, DOMProxyHandler::getInstance(),
proxyPrivateVal, proto, ${parent}, options);
proxyPrivateVal, proto, global, options);
if (!obj) {
return nullptr;
}
""",
parent=parent)
""")
if descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
create += dedent("""
js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO,
@ -3094,16 +3093,15 @@ def CreateBindingJSObject(descriptor, properties, parent):
""")
else:
create = fill(
create = dedent(
"""
obj = JS_NewObject(aCx, Class.ToJSClass(), proto, ${parent});
obj = JS_NewObject(aCx, Class.ToJSClass(), proto, global);
if (!obj) {
return nullptr;
}
js::SetReservedSlot(obj, DOM_OBJECT_SLOT, PRIVATE_TO_JSVAL(aObject));
""",
parent=parent)
""")
create = objDecl + create
if descriptor.nativeOwnership == 'refcounted':
@ -3254,9 +3252,7 @@ class CGWrapWithCacheMethod(CGAbstractMethod):
MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
"nsISupports must be on our primary inheritance chain");
JS::Rooted<JSObject*> parent(aCx,
GetRealParentObject(aObject,
WrapNativeParent(aCx, aObject->GetParentObject())));
JS::Rooted<JSObject*> parent(aCx, WrapNativeParent(aCx, aObject->GetParentObject()));
if (!parent) {
return nullptr;
}
@ -3272,13 +3268,13 @@ class CGWrapWithCacheMethod(CGAbstractMethod):
}
JSAutoCompartment ac(aCx, parent);
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, parent));
JS::Rooted<JSObject*> global(aCx, js::GetGlobalForObjectCrossCompartment(parent));
JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx, global);
if (!proto) {
return nullptr;
}
$*{parent}
$*{createObject}
$*{unforgeable}
@ -3287,8 +3283,7 @@ class CGWrapWithCacheMethod(CGAbstractMethod):
return obj;
""",
assertion=AssertInheritanceChain(self.descriptor),
parent=CreateBindingJSObject(self.descriptor, self.properties,
"parent"),
createObject=CreateBindingJSObject(self.descriptor, self.properties),
unforgeable=InitUnforgeableProperties(self.descriptor, self.properties),
slots=InitMemberSlots(self.descriptor, True))
@ -3334,7 +3329,7 @@ class CGWrapNonWrapperCacheMethod(CGAbstractMethod):
return nullptr;
}
$*{global_}
$*{createObject}
$*{unforgeable}
@ -3342,8 +3337,7 @@ class CGWrapNonWrapperCacheMethod(CGAbstractMethod):
return obj;
""",
assertions=AssertInheritanceChain(self.descriptor),
global_=CreateBindingJSObject(self.descriptor, self.properties,
"global"),
createObject=CreateBindingJSObject(self.descriptor, self.properties),
unforgeable=InitUnforgeableProperties(self.descriptor, self.properties),
slots=InitMemberSlots(self.descriptor, False))

Просмотреть файл

@ -35,7 +35,6 @@ GENERATED_FILES += [
MOCHITEST_MANIFESTS += [
'test/mochitest.ini',
'test/unit/mochitest.ini',
]
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']

Просмотреть файл

@ -9,13 +9,19 @@ support-files =
file_utf16_le_bom.xhtml
file_utf16_le_nobom.xhtml
file_TLD.html
unit/test_big5.js
unit/test_euc-jp.js
unit/test_euc-kr.js
unit/test_gbk.js
unit/test_iso-2022-jp.js
unit/test_shift_jis.js
worker_helper.js
test_BOMEncoding.js
test_TextDecoder.js
test_TextEncoder.js
[test_BOMEncoding.js]
[test_TextDecoder.html]
[test_TextDecoder.js]
[test_TextEncoder.html]
[test_TextEncoder.js]
[test_stringencoding.html]
skip-if = buildapp == 'b2g' # b2g(Test timed out on b2g board) b2g-debug(Test timed out on b2g board) b2g-desktop(Test timed out on b2g board)
[test_submit_euckr.html]

Просмотреть файл

@ -1,9 +0,0 @@
[DEFAULT]
skip-if = e10s
[test_big5.js]
[test_euc-jp.js]
[test_euc-kr.js]
[test_gbk.js]
[test_iso-2022-jp.js]
[test_shift_jis.js]

Просмотреть файл

@ -1,8 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
MOCHITEST_MANIFESTS += ['mochitest.ini']

Просмотреть файл

@ -863,18 +863,6 @@ EventListenerManager::CompileEventHandlerInternal(Listener* aListener,
}
}
JS::AutoObjectVector scopeChain(cx);
{ // scope for curScope
// We append all the non-globals on our desired scope chain.
JS::Rooted<JSObject*> curScope(cx, &v.toObject());
while (curScope && !JS_IsGlobalObject(curScope)) {
if (!scopeChain.append(curScope)) {
return NS_ERROR_OUT_OF_MEMORY;
}
curScope = JS_GetParent(curScope);
}
}
if (addonId) {
JS::Rooted<JSObject*> vObj(cx, &v.toObject());
JS::Rooted<JSObject*> addonScope(cx, xpc::GetAddonScope(cx, vObj, addonId));
@ -882,14 +870,9 @@ EventListenerManager::CompileEventHandlerInternal(Listener* aListener,
return NS_ERROR_FAILURE;
}
JSAutoCompartment ac(cx, addonScope);
for (size_t i = 0; i < scopeChain.length(); ++i) {
if (!JS_WrapObject(cx, scopeChain[i])) {
return NS_ERROR_FAILURE;
}
}
// And wrap v as well, since scopeChain might be empty so we can't
// reliably use it to enter a compartment.
// Wrap our event target into the addon scope, since that's where we want to
// do all our work.
if (!JS_WrapValue(cx, &v)) {
return NS_ERROR_FAILURE;
}
@ -897,6 +880,16 @@ EventListenerManager::CompileEventHandlerInternal(Listener* aListener,
JS::Rooted<JSObject*> target(cx, &v.toObject());
JSAutoCompartment ac(cx, target);
// Now that we've entered the compartment we actually care about, create our
// scope chain. Note that we start with |element|, not aElement, because
// mTarget is different from aElement in the <body> case, where mTarget is a
// Window, and in that case we do not want the scope chain to include the body
// or the document.
JS::AutoObjectVector scopeChain(cx);
if (!nsJSUtils::GetScopeChainForElement(cx, element, scopeChain)) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsDependentAtomString str(attrName);
// Most of our names are short enough that we don't even have to malloc
// the JS string stuff, so don't worry about playing games with
@ -915,8 +908,7 @@ EventListenerManager::CompileEventHandlerInternal(Listener* aListener,
.setFileAndLine(url.get(), lineNo)
.setVersion(JSVERSION_DEFAULT)
.setElement(&v.toObject())
.setElementAttributeName(jsStr)
.setDefineOnScope(false);
.setElementAttributeName(jsStr);
JS::Rooted<JSObject*> handler(cx);
result = nsJSUtils::CompileFunction(jsapi, scopeChain, options,

Просмотреть файл

@ -27,8 +27,8 @@ skip-if = buildapp == 'b2g'
[test_bug322588.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
[test_bug328885.html]
[test_bug336682.js]
[test_bug336682_1.html]
support-files = test_bug336682.js
[test_bug367781.html]
[test_bug368835.html]
[test_bug379120.html]

Просмотреть файл

@ -22,7 +22,7 @@ HTMLLegendElement::~HTMLLegendElement()
NS_IMPL_ELEMENT_CLONE(HTMLLegendElement)
nsIContent*
HTMLLegendElement::GetFieldSet()
HTMLLegendElement::GetFieldSet() const
{
nsIContent* parent = GetParent();

Просмотреть файл

@ -54,7 +54,7 @@ public:
virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const MOZ_OVERRIDE;
Element* GetFormElement()
Element* GetFormElement() const
{
nsCOMPtr<nsIFormControl> fieldsetControl = do_QueryInterface(GetFieldSet());
@ -77,10 +77,10 @@ public:
SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
}
ParentObject GetParentObject() {
nsINode* GetScopeChainParent() const MOZ_OVERRIDE
{
Element* form = GetFormElement();
return form ? GetParentObjectInternal(form)
: nsGenericHTMLElement::GetParentObject();
return form ? form : nsGenericHTMLElement::GetScopeChainParent();
}
protected:
@ -92,7 +92,7 @@ protected:
* Get the fieldset content element that contains this legend.
* Returns null if there is no fieldset containing this legend.
*/
nsIContent* GetFieldSet();
nsIContent* GetFieldSet() const;
};
} // namespace dom

Просмотреть файл

@ -781,7 +781,7 @@ ImageDocument::UpdateTitleAndCharset()
"ImageTitleWithDimensions2AndFile",
};
MediaDocument::UpdateTitleAndCharset(typeStr, formatNames,
MediaDocument::UpdateTitleAndCharset(typeStr, mChannel, formatNames,
mImageWidth, mImageHeight, status);
}

Просмотреть файл

@ -278,10 +278,16 @@ MediaDocument::StartLayout()
}
void
MediaDocument::GetFileName(nsAString& aResult)
MediaDocument::GetFileName(nsAString& aResult, nsIChannel* aChannel)
{
aResult.Truncate();
if (aChannel) {
aChannel->GetContentDispositionFilename(aResult);
if (!aResult.IsEmpty())
return;
}
nsCOMPtr<nsIURL> url = do_QueryInterface(mDocumentURI);
if (!url)
return;
@ -339,12 +345,13 @@ MediaDocument::LinkStylesheet(const nsAString& aStylesheet)
void
MediaDocument::UpdateTitleAndCharset(const nsACString& aTypeStr,
nsIChannel* aChannel,
const char* const* aFormatNames,
int32_t aWidth, int32_t aHeight,
const nsAString& aStatus)
{
nsXPIDLString fileStr;
GetFileName(fileStr);
GetFileName(fileStr, aChannel);
NS_ConvertASCIItoUTF16 typeStr(aTypeStr);
nsXPIDLString title;

Просмотреть файл

@ -48,7 +48,7 @@ protected:
friend class MediaDocumentStreamListener;
nsresult StartLayout();
void GetFileName(nsAString& aResult);
void GetFileName(nsAString& aResult, nsIChannel* aChannel);
nsresult LinkStylesheet(const nsAString& aStylesheet);
@ -64,6 +64,7 @@ protected:
// but could be in other units for other 'media', in which case you have to
// define format names accordingly.
void UpdateTitleAndCharset(const nsACString& aTypeStr,
nsIChannel* aChannel,
const char* const* aFormatNames = sFormatNames,
int32_t aWidth = 0,
int32_t aHeight = 0,

Просмотреть файл

@ -185,7 +185,7 @@ PluginDocument::StartDocumentLoad(const char* aCommand,
return rv;
}
MediaDocument::UpdateTitleAndCharset(mMimeType);
MediaDocument::UpdateTitleAndCharset(mMimeType, aChannel);
mStreamListener = new PluginStreamListener(this);
NS_ASSERTION(aDocListener, "null aDocListener");

Просмотреть файл

@ -128,7 +128,7 @@ VideoDocument::UpdateTitle(nsIChannel* aChannel)
return;
nsAutoString fileName;
GetFileName(fileName);
GetFileName(fileName, aChannel);
SetTitle(fileName);
}

Просмотреть файл

@ -1896,14 +1896,10 @@ NS_IMPL_ISUPPORTS_INHERITED(nsGenericHTMLFormElement,
nsGenericHTMLElement,
nsIFormControl)
mozilla::dom::ParentObject
nsGenericHTMLFormElement::GetParentObject() const
nsINode*
nsGenericHTMLFormElement::GetScopeChainParent() const
{
// We use the parent chain to implement the scope for event handlers.
if (mForm) {
return GetParentObjectInternal(mForm);
}
return nsGenericHTMLElement::GetParentObject();
return mForm ? mForm : nsGenericHTMLElement::GetScopeChainParent();
}
bool

Просмотреть файл

@ -1245,7 +1245,7 @@ public:
NS_DECL_ISUPPORTS_INHERITED
mozilla::dom::ParentObject GetParentObject() const;
nsINode* GetScopeChainParent() const MOZ_OVERRIDE;
virtual bool IsNodeOfType(uint32_t aFlags) const MOZ_OVERRIDE;
virtual void SaveSubtreeState() MOZ_OVERRIDE;

Просмотреть файл

@ -1,13 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<link rel="import" href="file_cycle_5_B.html" onload="loaded()" onerror="failed()"></link>
<link rel="import" href="file_cycle_5_D.html" onload="loaded()" onerror="failed()"></link>
<link rel="import" href="file_cycle_5_C.html" onload="loaded()" onerror="failed()"></link>
</head>
<body>
<script>
order.push("A");
</script>
</body>
</html>

Просмотреть файл

@ -1,13 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<link rel="import" href="file_cycle_5_A.html" onload="loaded()" onerror="failed()"></link>
<link rel="import" href="file_cycle_5_C.html" onload="loaded()" onerror="failed()"></link>
<link rel="import" href="file_cycle_5_D.html" onload="loaded()" onerror="failed()"></link>
</head>
<body>
<script>
order.push("B");
</script>
</body>
</html>

Просмотреть файл

@ -1,13 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<link rel="import" href="file_cycle_5_A.html" onload="loaded()" onerror="failed()"></link>
<link rel="import" href="file_cycle_5_B.html" onload="loaded()" onerror="failed()"></link>
<link rel="import" href="file_cycle_5_D.html" onload="loaded()" onerror="failed()"></link>
</head>
<body>
<script>
order.push("C");
</script>
</body>
</html>

Просмотреть файл

@ -1,13 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<link rel="import" href="file_cycle_5_A.html" onload="loaded()" onerror="failed()"></link>
<link rel="import" href="file_cycle_5_B.html" onload="loaded()" onerror="failed()"></link>
<link rel="import" href="file_cycle_5_C.html" onload="loaded()" onerror="failed()"></link>
</head>
<body>
<script>
order.push("D");
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,4 @@
<!DOCTYPE html>
<head>
</head>
<body>Simple import</body>

Просмотреть файл

@ -31,11 +31,8 @@ support-files =
file_cycle_4_C.html
file_cycle_4_D.html
file_cycle_4_E.html
file_cycle_5_A.html
file_cycle_5_B.html
file_cycle_5_C.html
file_cycle_5_D.html
file_encoding.html
file_simple_import.html
[test_cycle_1.html]
skip-if = toolkit == 'gonk' # nested imports fail on b2g emulator
@ -45,6 +42,5 @@ skip-if = toolkit == 'gonk' # nested imports fail on b2g emulator
skip-if = toolkit == 'gonk' # nested imports fail on b2g emulator
[test_cycle_4.html]
skip-if = toolkit == 'gonk' # nested imports fail on b2g emulator
[test_cycle_5.html]
skip-if = toolkit == 'gonk' # nested imports fail on b2g emulator
[test_encoding.html]
[test_defaultView.html]

Просмотреть файл

@ -13,25 +13,19 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1061469
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1061469">Mozilla Bug 1061469</a>
<script type="text/javascript">
SimpleTest.waitForExplicitFinish();
var counter = 0;
var fcounter = 0;
var order = [];
var success = false;
function loaded() {
counter++;
success = true;
}
function failed() {
fcounter++;
ok(false, "Import loading failed");
}
</script>
<link rel="import" href="file_cycle_5_A.html" onload="loaded()" onerror="failed()"></link>
<link rel="import" href="file_cycle_5_C.html" onload="loaded()" onerror="failed()"></link>
<link rel="import" href="file_simple_import.html" id="import" onload="loaded()" onerror="failed()"></link>
<script type="text/javascript">
is(counter, 14, "Imports are loaded");
is(fcounter, 0, "No error in imports");
var expected = ["D","C","B","A"];
for (i in expected)
is(order[i], expected[i], "import " + i + " should be " + expected[i]);
document.defaultView;
is(document.getElementById("import").import.defaultView, null, "defaultView is always null for imports");
SimpleTest.finish();
</script>
</body>
</html>
</html>

Просмотреть файл

@ -21,7 +21,6 @@ support-files =
[test_bug1043828.html]
[test_bug1059163.html]
[test_bug1066515.html]
[test_delete_focused_element.html]
[test_sendkey_cancel.html]
[test_sync_edit.html]
[test_two_inputs.html]

Просмотреть файл

@ -1,112 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=952741
-->
<head>
<title>Test focused element deletion for InputMethod API.</title>
<script type="application/javascript;version=1.7" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=952741">Mozilla Bug 952741</a>
<input type="text" />
<p id="display"></p>
<pre id="test">
<script class="testbody" type="application/javascript;version=1.7">
inputmethod_setup(function() {
runTest();
});
// The frame script running in file_test_app.html.
function appFrameScript() {
let input = content.document.getElementById('test-input');
let textarea = content.document.createElement('textarea');
textarea.lang = 'en';
content.document.body.appendChild(textarea);
textarea.onfocus = function() {
content.setTimeout(function() {
textarea.parentNode.removeChild(textarea);
sendAsyncMessage('test:InputMethod:finished', {});
}, 10);
};
content.setTimeout(function() {
content.setTimeout(function() {
textarea.focus();
}, 10);
input.parentNode.removeChild(input);
}, 0);
}
function runTest() {
var timeoutId = null;
// Create an app frame to recieve keyboard inputs.
let app = document.createElement('iframe');
app.src = 'file_test_app.html';
app.setAttribute('mozbrowser', true);
document.body.appendChild(app);
app.addEventListener('mozbrowserloadend', function() {
let mm = SpecialPowers.getBrowserFrameMessageManager(app);
mm.loadFrameScript('data:,(' + appFrameScript.toString() + ')();', false);
mm.addMessageListener("test:InputMethod:finished", function() {
timeoutId = setTimeout(function() {
ok(false, 'No inputcontextchange event when textarea is deleted.');
inputmethod_cleanup();
}, 20000);
});
});
let im = navigator.mozInputMethod;
let count = 0;
im.oninputcontextchange = function() {
switch (count++) {
case 0:
if (!im.inputcontext) {
break;
}
is(im.inputcontext.lang, 'zh', 'input was focused.');
return;
case 1:
if (im.inputcontext) {
break;
}
ok(true, 'input was blurred.');
return;
case 2:
if (!im.inputcontext) {
break;
}
is(im.inputcontext.lang, 'en', 'textarea was focused.');
return;
case 3:
if (im.inputcontext) {
break;
}
ok(true, 'textarea was removed.');
clearTimeout(timeoutId);
inputmethod_cleanup();
return;
default:
return;
}
count = 100;
ok(false, 'Should not arrive here.');
inputmethod_cleanup();
};
// Set current page as an input method.
SpecialPowers.wrap(im).setActive(true);
}
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -2,6 +2,7 @@
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1057898
https://bugzilla.mozilla.org/show_bug.cgi?id=952741
-->
<head>
<title>Test switching between two inputs</title>
@ -11,6 +12,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1057898
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1057898">Mozilla Bug 1057898</a>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=952741">Mozilla Bug 952741</a>
<p id="display"></p>
<pre id="test">
<script class="testbody" type="application/javascript;version=1.7">
@ -55,7 +57,17 @@ let appFrameScript = function appFrameScript() {
break;
case 6:
input1.blur();
content.document.body.removeChild(input1);
break;
case 7:
input2.focus();
break;
case 8:
content.document.body.removeChild(input2);
break;
}
@ -114,10 +126,25 @@ function runTest() {
mm.sendAsyncMessage('test:next');
break;
// blur on the first input results null input context
// remove on the first focused input results null input context
case 6:
is(inputcontext, null, 'Receving null inputcontext');
mm.sendAsyncMessage('test:next');
break;
// input context for the second input.
case 7:
ok(!!inputcontext, 'Receving the second input context');
is(inputcontext.textAfterCursor, 'Second');
mm.sendAsyncMessage('test:next');
break;
// remove on the second focused input results null input context
case 8:
is(inputcontext, null, 'Receving null inputcontext');
inputmethod_cleanup();
break;

Просмотреть файл

@ -342,7 +342,6 @@ skip-if = buildapp == 'b2g' || (toolkit == 'android' && processor == 'x86') # bu
[test_can_play_type_no_ogg.html]
[test_can_play_type_ogg.html]
[test_chaining.html]
skip-if = toolkit == 'gonk' && debug
[test_clone_media_element.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_closing_connections.html]

Просмотреть файл

@ -35,27 +35,25 @@ add_task(function asyncCleanup() {
});
function waitForPageLoad(aTab) {
let deferred = Promise.defer();
return new Promise(resolve => {
function onTabLoad(event) {
aTab.linkedBrowser.removeEventListener("load", onTabLoad, true);
info("Load tab event received");
resolve();
};
function onTabLoad(event) {
aTab.linkedBrowser.removeEventListener("load", onTabLoad, true);
info("Load tab event received");
deferred.resolve();
}
aTab.linkedBrowser.addEventListener("load", onTabLoad, true, true);
return deferred.promise;
aTab.linkedBrowser.addEventListener("load", onTabLoad, true, true);
});
}
function waitForPanelShow(aPanel) {
let deferred = Promise.defer();
return new Promise(resolve => {
function onPopupShown(event) {
PopupNotifications.panel.removeEventListener("popupshown", onPopupShown, true);
info("Popup shown event received");
resolve();
}
function onPopupShown(event) {
PopupNotifications.panel.removeEventListener("popupshown", onPopupShown, true);
info("Popup shown event received");
deferred.resolve();
}
PopupNotifications.panel.addEventListener("popupshown", onPopupShown, true, true);
return deferred.promise;
PopupNotifications.panel.addEventListener("popupshown", onPopupShown, true, true);
});
}

Просмотреть файл

@ -23,13 +23,12 @@ support-files =
SimpleTest/SimpleTest.js
SimpleTest/TestRunner.js
SimpleTest/test.css
[test_Base.js]
[test_Color.js]
[test_DateTime.js]
[test_DragAndDrop.js]
[test_Format.js]
[test_Iter.js]
[test_Logging.js]
[test_MochiKit-Async.json]
[test_Signal.js]
test_Base.js
test_Color.js
test_DateTime.js
test_DragAndDrop.js
test_Format.js
test_Iter.js
test_Logging.js
test_MochiKit-Async.json
test_Signal.js

Просмотреть файл

@ -70,7 +70,7 @@ skip-if = ((buildapp == 'mulet' || buildapp == 'b2g') && toolkit != 'gonk') #Bug
# [test_network_events.html]
# Disable this test until bug 795711 is fixed.
[test_offsets.html]
[test_offsets.js]
support-files = test_offsets.js
[test_outerHTML.html]
[test_outerHTML.xhtml]
skip-if = buildapp == 'mulet'

Просмотреть файл

@ -15,7 +15,7 @@
namespace mozilla {
namespace dom {
class TVSourceListener : public nsITVSourceListener
class TVSourceListener MOZ_FINAL : public nsITVSourceListener
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS

Просмотреть файл

@ -71,7 +71,6 @@ private:
uint64_t mDuration;
nsString mDescription;
nsString mRating;
bool mIsInterrupting;
nsTArray<nsString> mAudioLanguages;
nsTArray<nsString> mSubtitleLanguages;
};

Просмотреть файл

@ -57,6 +57,10 @@ support-files =
terminateSyncXHR_frame.html
terminateSyncXHR_worker.js
testXHR.txt
test_csp.html^headers^
test_csp.js
test_xhr_parameters.js
test_xhr_system.js
threadErrors_worker1.js
threadErrors_worker2.js
threadErrors_worker3.js
@ -110,8 +114,6 @@ support-files =
[test_contentWorker.html]
[test_csp.html]
skip-if = (toolkit == 'gonk' && debug) #debug-only failure
[test_csp.html^headers^]
[test_csp.js]
[test_dataURLWorker.html]
[test_errorPropagation.html]
skip-if = buildapp == 'b2g' # b2g(times out) b2g-debug(times out) b2g-desktop(times out)
@ -169,11 +171,9 @@ skip-if = buildapp == 'b2g' || e10s # b2g(test timed out, might need more time)
[test_xhr_implicit_cancel.html]
[test_xhr_parameters.html]
skip-if = buildapp == 'b2g' || e10s
[test_xhr_parameters.js]
[test_xhr_responseURL.html]
[test_xhr_system.html]
skip-if = buildapp == 'b2g' || e10s
[test_xhr_system.js]
[test_xhr_timeout.html]
skip-if = (os == "win") || (os == "mac") || toolkit == 'android' || e10s #bug 798220
[test_url_exceptions.html]

Просмотреть файл

@ -18,6 +18,7 @@
#include "nsIXPConnect.h"
#include "xpcpublic.h"
#include "nsXBLPrototypeBinding.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ScriptSettings.h"
using namespace mozilla;
@ -103,16 +104,21 @@ nsXBLProtoImplMethod::InstallMember(JSContext* aCx,
"Should not be installing an uncompiled method");
MOZ_ASSERT(js::IsObjectInContextCompartment(aTargetClassObject, aCx));
JS::Rooted<JSObject*> globalObject(aCx, JS_GetGlobalForObject(aCx, aTargetClassObject));
MOZ_ASSERT(xpc::IsInContentXBLScope(globalObject) ||
xpc::IsInAddonScope(globalObject) ||
globalObject == xpc::GetXBLScope(aCx, globalObject));
#ifdef DEBUG
{
JS::Rooted<JSObject*> globalObject(aCx, JS_GetGlobalForObject(aCx, aTargetClassObject));
MOZ_ASSERT(xpc::IsInContentXBLScope(globalObject) ||
xpc::IsInAddonScope(globalObject) ||
globalObject == xpc::GetXBLScope(aCx, globalObject));
MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx) == globalObject);
}
#endif
JS::Rooted<JSObject*> jsMethodObject(aCx, GetCompiledMethod());
if (jsMethodObject) {
nsDependentString name(mName);
JS::Rooted<JSObject*> method(aCx, JS_CloneFunctionObject(aCx, jsMethodObject, globalObject));
JS::Rooted<JSObject*> method(aCx, JS::CloneFunctionObject(aCx, jsMethodObject));
NS_ENSURE_TRUE(method, NS_ERROR_OUT_OF_MEMORY);
if (!::JS_DefineUCProperty(aCx, aTargetClassObject,
@ -194,8 +200,7 @@ nsXBLProtoImplMethod::CompileMember(AutoJSAPI& jsapi, const nsCString& aClassStr
JS::CompileOptions options(cx);
options.setFileAndLine(functionUri.get(),
uncompiledMethod->mBodyText.GetLineNumber())
.setVersion(JSVERSION_LATEST)
.setDefineOnScope(false);
.setVersion(JSVERSION_LATEST);
JS::Rooted<JSObject*> methodObject(cx);
JS::AutoObjectVector emptyVector(cx);
nsresult rv = nsJSUtils::CompileFunction(jsapi, emptyVector, options, cname,
@ -269,6 +274,7 @@ nsXBLProtoImplMethod::Write(nsIObjectOutputStream* aStream)
nsresult
nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement, JSAddonId* aAddonId)
{
MOZ_ASSERT(aBoundElement->IsElement());
NS_PRECONDITION(IsCompiled(), "Can't execute uncompiled method");
if (!GetCompiledMethod()) {
@ -295,23 +301,22 @@ nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement, JSAddonId* aAd
JS::Rooted<JSObject*> globalObject(cx, global->GetGlobalJSObject());
JS::Rooted<JS::Value> v(cx);
nsresult rv = nsContentUtils::WrapNative(cx, aBoundElement, &v);
NS_ENSURE_SUCCESS(rv, rv);
JS::Rooted<JSObject*> thisObject(cx, &v.toObject());
JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, globalObject, aAddonId));
NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
JSAutoCompartment ac(cx, scopeObject);
if (!JS_WrapObject(cx, &thisObject))
return NS_ERROR_OUT_OF_MEMORY;
JS::AutoObjectVector scopeChain(cx);
if (!nsJSUtils::GetScopeChainForElement(cx, aBoundElement->AsElement(),
scopeChain)) {
return NS_ERROR_OUT_OF_MEMORY;
}
MOZ_ASSERT(scopeChain.length() != 0);
// Clone the function object, using thisObject as the parent so "this" is in
// the scope chain of the resulting function (for backwards compat to the
// days when this was an event handler).
// Clone the function object, using our scope chain (for backwards
// compat to the days when this was an event handler).
JS::Rooted<JSObject*> jsMethodObject(cx, GetCompiledMethod());
JS::Rooted<JSObject*> method(cx, ::JS_CloneFunctionObject(cx, jsMethodObject, thisObject));
JS::Rooted<JSObject*> method(cx, JS::CloneFunctionObject(cx, jsMethodObject,
scopeChain));
if (!method)
return NS_ERROR_OUT_OF_MEMORY;
@ -325,7 +330,7 @@ nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement, JSAddonId* aAd
if (scriptAllowed) {
JS::Rooted<JS::Value> retval(cx);
JS::Rooted<JS::Value> methodVal(cx, JS::ObjectValue(*method));
ok = ::JS::Call(cx, thisObject, methodVal, JS::HandleValueArray::empty(), &retval);
ok = ::JS::Call(cx, scopeChain[0], methodVal, JS::HandleValueArray::empty(), &retval);
}
if (!ok) {

Просмотреть файл

@ -128,21 +128,27 @@ nsXBLProtoImplProperty::InstallMember(JSContext *aCx,
"Should not be installing an uncompiled property");
MOZ_ASSERT(mGetter.IsCompiled() && mSetter.IsCompiled());
MOZ_ASSERT(js::IsObjectInContextCompartment(aTargetClassObject, aCx));
JS::Rooted<JSObject*> globalObject(aCx, JS_GetGlobalForObject(aCx, aTargetClassObject));
MOZ_ASSERT(xpc::IsInContentXBLScope(globalObject) ||
xpc::IsInAddonScope(globalObject) ||
globalObject == xpc::GetXBLScope(aCx, globalObject));
#ifdef DEBUG
{
JS::Rooted<JSObject*> globalObject(aCx, JS_GetGlobalForObject(aCx, aTargetClassObject));
MOZ_ASSERT(xpc::IsInContentXBLScope(globalObject) ||
xpc::IsInAddonScope(globalObject) ||
globalObject == xpc::GetXBLScope(aCx, globalObject));
MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx) == globalObject);
}
#endif
JS::Rooted<JSObject*> getter(aCx, mGetter.GetJSFunction());
JS::Rooted<JSObject*> setter(aCx, mSetter.GetJSFunction());
if (getter || setter) {
if (getter) {
if (!(getter = ::JS_CloneFunctionObject(aCx, getter, globalObject)))
if (!(getter = JS::CloneFunctionObject(aCx, getter)))
return NS_ERROR_OUT_OF_MEMORY;
}
if (setter) {
if (!(setter = ::JS_CloneFunctionObject(aCx, setter, globalObject)))
if (!(setter = JS::CloneFunctionObject(aCx, setter)))
return NS_ERROR_OUT_OF_MEMORY;
}
@ -192,8 +198,7 @@ nsXBLProtoImplProperty::CompileMember(AutoJSAPI& jsapi, const nsCString& aClassS
JSAutoCompartment ac(cx, aClassObject);
JS::CompileOptions options(cx);
options.setFileAndLine(functionUri.get(), getterText->GetLineNumber())
.setVersion(JSVERSION_LATEST)
.setDefineOnScope(false);
.setVersion(JSVERSION_LATEST);
nsCString name = NS_LITERAL_CSTRING("get_") + NS_ConvertUTF16toUTF8(mName);
JS::Rooted<JSObject*> getterObject(cx);
JS::AutoObjectVector emptyVector(cx);
@ -239,8 +244,7 @@ nsXBLProtoImplProperty::CompileMember(AutoJSAPI& jsapi, const nsCString& aClassS
JSAutoCompartment ac(cx, aClassObject);
JS::CompileOptions options(cx);
options.setFileAndLine(functionUri.get(), setterText->GetLineNumber())
.setVersion(JSVERSION_LATEST)
.setDefineOnScope(false);
.setVersion(JSVERSION_LATEST);
nsCString name = NS_LITERAL_CSTRING("set_") + NS_ConvertUTF16toUTF8(mName);
JS::Rooted<JSObject*> setterObject(cx);
JS::AutoObjectVector emptyVector(cx);

Просмотреть файл

@ -44,6 +44,7 @@
#include "mozilla/BasicEvents.h"
#include "mozilla/JSEventHandler.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/EventHandlerBinding.h"
#include "mozilla/dom/ScriptSettings.h"
#include "xpcpublic.h"
@ -300,16 +301,15 @@ nsXBLPrototypeHandler::ExecuteHandler(EventTarget* aTarget,
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
MOZ_ASSERT(!js::IsCrossCompartmentWrapper(genericHandler));
// Wrap the native into the XBL scope. This creates a reflector in the document
// scope if one doesn't already exist, and potentially wraps it cross-
// compartment into our scope (via aAllowWrapping=true).
JS::Rooted<JS::Value> targetV(cx, JS::UndefinedValue());
rv = nsContentUtils::WrapNative(cx, scriptTarget, &targetV);
NS_ENSURE_SUCCESS(rv, rv);
// Build a scope chain in the XBL scope.
nsRefPtr<Element> targetElement = do_QueryObject(scriptTarget);
JS::AutoObjectVector scopeChain(cx);
ok = nsJSUtils::GetScopeChainForElement(cx, targetElement, scopeChain);
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
// Next, clone the generic handler to be parented to the target.
JS::Rooted<JSObject*> target(cx, &targetV.toObject());
JS::Rooted<JSObject*> bound(cx, JS_CloneFunctionObject(cx, genericHandler, target));
// Next, clone the generic handler with our desired scope chain.
JS::Rooted<JSObject*> bound(cx, JS::CloneFunctionObject(cx, genericHandler,
scopeChain));
NS_ENSURE_TRUE(bound, NS_ERROR_FAILURE);
nsRefPtr<EventHandlerNonNull> handlerCallback =
@ -370,8 +370,7 @@ nsXBLPrototypeHandler::EnsureEventHandler(AutoJSAPI& jsapi, nsIAtom* aName,
JSAutoCompartment ac(cx, scopeObject);
JS::CompileOptions options(cx);
options.setFileAndLine(bindingURI.get(), mLineNumber)
.setVersion(JSVERSION_LATEST)
.setDefineOnScope(false);
.setVersion(JSVERSION_LATEST);
JS::Rooted<JSObject*> handlerFun(cx);
JS::AutoObjectVector emptyVector(cx);

Просмотреть файл

@ -606,14 +606,11 @@ public:
already_AddRefed<nsFrameLoader> GetFrameLoader();
void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& rv);
// For XUL, the parent is the parent element, if any
mozilla::dom::ParentObject GetParentObject() const
nsINode* GetScopeChainParent() const MOZ_OVERRIDE
{
// For XUL, the parent is the parent element, if any
Element* parent = GetParentElement();
if (parent) {
return GetParentObjectInternal(parent);
}
return nsStyledElement::GetParentObject();
return parent ? parent : nsStyledElement::GetScopeChainParent();
}
protected:

Просмотреть файл

@ -43,6 +43,19 @@ MOZ_BEGIN_ENUM_CLASS(SurfaceFormat, int8_t)
UNKNOWN
MOZ_END_ENUM_CLASS(SurfaceFormat)
inline bool IsOpaque(SurfaceFormat aFormat)
{
switch (aFormat) {
case SurfaceFormat::B8G8R8X8:
case SurfaceFormat::R8G8B8X8:
case SurfaceFormat::R5G6B5:
case SurfaceFormat::YUV:
return true;
default:
return false;
}
}
MOZ_BEGIN_ENUM_CLASS(FilterType, int8_t)
BLEND = 0,
TRANSFORM,

Просмотреть файл

@ -5187,6 +5187,7 @@
#define LOCAL_EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133
#define LOCAL_EGL_COVERAGE_SAMPLE_RESOLVE_NV 0x3131
#define LOCAL_EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
#define LOCAL_EGL_DXGI_KEYED_MUTEX_ANGLE 0x3209
#define LOCAL_EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0)
#define LOCAL_EGL_DEPTH_ENCODING_NONE_NV 0
#define LOCAL_EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3

Просмотреть файл

@ -4,10 +4,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SharedSurfaceANGLE.h"
#include "GLContextEGL.h"
#include "GLLibraryEGL.h"
#include <d3d11.h>
#include "gfxWindowsPlatform.h"
namespace mozilla {
namespace gl {
@ -65,6 +67,12 @@ SharedSurface_ANGLEShareHandle::Create(GLContext* gl,
egl->fDestroySurface(egl->Display(), pbuffer);
return nullptr;
}
void* opaqueKeyedMutex = nullptr;
egl->fQuerySurfacePointerANGLE(display,
pbuffer,
LOCAL_EGL_DXGI_KEYED_MUTEX_ANGLE,
&opaqueKeyedMutex);
RefPtr<IDXGIKeyedMutex> keyedMutex = static_cast<IDXGIKeyedMutex*>(opaqueKeyedMutex);
GLuint fence = 0;
if (gl->IsExtensionSupported(GLContext::NV_fence)) {
@ -74,7 +82,7 @@ SharedSurface_ANGLEShareHandle::Create(GLContext* gl,
typedef SharedSurface_ANGLEShareHandle ptrT;
UniquePtr<ptrT> ret( new ptrT(gl, egl, size, hasAlpha, context,
pbuffer, shareHandle, fence) );
pbuffer, shareHandle, keyedMutex, fence) );
return Move(ret);
}
@ -91,6 +99,7 @@ SharedSurface_ANGLEShareHandle::SharedSurface_ANGLEShareHandle(GLContext* gl,
EGLContext context,
EGLSurface pbuffer,
HANDLE shareHandle,
const RefPtr<IDXGIKeyedMutex>& keyedMutex,
GLuint fence)
: SharedSurface(SharedSurfaceType::EGLSurfaceANGLE,
AttachmentType::Screen,
@ -101,6 +110,7 @@ SharedSurface_ANGLEShareHandle::SharedSurface_ANGLEShareHandle(GLContext* gl,
, mContext(context)
, mPBuffer(pbuffer)
, mShareHandle(shareHandle)
, mKeyedMutex(keyedMutex)
, mFence(fence)
{
}
@ -145,6 +155,58 @@ SharedSurface_ANGLEShareHandle::PollSync()
return true;
}
void
SharedSurface_ANGLEShareHandle::ProducerAcquireImpl()
{
if (mKeyedMutex)
mKeyedMutex->AcquireSync(0, INFINITE);
}
void
SharedSurface_ANGLEShareHandle::ProducerReleaseImpl()
{
if (mKeyedMutex) {
// XXX: ReleaseSync() has an implicit flush of the D3D commands
// whether we need Flush() or not depends on the ANGLE semantics.
// For now, we'll just do it
mGL->fFlush();
mKeyedMutex->ReleaseSync(0);
return;
}
Fence();
}
void
SharedSurface_ANGLEShareHandle::ConsumerAcquireImpl()
{
if (!mConsumerTexture) {
RefPtr<ID3D11Texture2D> tex;
HRESULT hr = gfxWindowsPlatform::GetPlatform()->GetD3D11Device()->OpenSharedResource(mShareHandle,
__uuidof(ID3D11Texture2D),
(void**)(ID3D11Texture2D**)byRef(tex));
if (SUCCEEDED(hr)) {
mConsumerTexture = tex;
RefPtr<IDXGIKeyedMutex> mutex;
hr = tex->QueryInterface((IDXGIKeyedMutex**)byRef(mutex));
if (SUCCEEDED(hr)) {
mConsumerKeyedMutex = mutex;
}
}
}
if (mConsumerKeyedMutex)
mConsumerKeyedMutex->AcquireSync(0, INFINITE);
}
void
SharedSurface_ANGLEShareHandle::ConsumerReleaseImpl()
{
if (mConsumerKeyedMutex) {
mConsumerKeyedMutex->ReleaseSync(0);
}
}
void
SharedSurface_ANGLEShareHandle::Fence_ContentThread_Impl()
{

Просмотреть файл

@ -7,9 +7,11 @@
#define SHARED_SURFACE_ANGLE_H_
#include <windows.h>
#include "SharedSurface.h"
struct IDXGIKeyedMutex;
struct ID3D11Texture2D;
namespace mozilla {
namespace gl {
@ -37,6 +39,10 @@ protected:
const EGLContext mContext;
const EGLSurface mPBuffer;
const HANDLE mShareHandle;
RefPtr<IDXGIKeyedMutex> mKeyedMutex;
RefPtr<IDXGIKeyedMutex> mConsumerKeyedMutex;
RefPtr<ID3D11Texture2D> mConsumerTexture;
const GLuint mFence;
SharedSurface_ANGLEShareHandle(GLContext* gl,
@ -46,6 +52,7 @@ protected:
EGLContext context,
EGLSurface pbuffer,
HANDLE shareHandle,
const RefPtr<IDXGIKeyedMutex>& keyedMutex,
GLuint fence);
EGLDisplay Display();
@ -57,6 +64,10 @@ public:
virtual void UnlockProdImpl() MOZ_OVERRIDE;
virtual void Fence() MOZ_OVERRIDE;
virtual void ProducerAcquireImpl() MOZ_OVERRIDE;
virtual void ProducerReleaseImpl() MOZ_OVERRIDE;
virtual void ConsumerAcquireImpl() MOZ_OVERRIDE;
virtual void ConsumerReleaseImpl() MOZ_OVERRIDE;
virtual bool WaitSync() MOZ_OVERRIDE;
virtual bool PollSync() MOZ_OVERRIDE;
@ -68,6 +79,10 @@ public:
HANDLE GetShareHandle() {
return mShareHandle;
}
const RefPtr<ID3D11Texture2D>& GetConsumerTexture() const {
return mConsumerTexture;
}
};

Просмотреть файл

@ -76,6 +76,8 @@ GrallocImage::SetData(const Data& aData)
new GrallocTextureClientOGL(ImageBridgeChild::GetSingleton(),
gfx::SurfaceFormat::UNKNOWN,
gfx::BackendType::NONE);
// GrallocImages are all YUV and don't support alpha.
textureClient->SetIsOpaque(true);
bool result =
textureClient->AllocateGralloc(mData.mYSize,
HAL_PIXEL_FORMAT_YV12,

Просмотреть файл

@ -82,7 +82,11 @@ MOZ_BEGIN_ENUM_CLASS(LayerRenderStateFlags, int8_t)
Y_FLIPPED = 1 << 0,
BUFFER_ROTATION = 1 << 1,
// Notify Composer2D to swap the RB pixels of gralloc buffer
FORMAT_RB_SWAP = 1 << 2
FORMAT_RB_SWAP = 1 << 2,
// We record opaqueness here alongside the actual surface we're going to
// render. This avoids confusion when a layer might return different kinds
// of surfaces over time (e.g. video frames).
OPAQUE = 1 << 3
MOZ_END_ENUM_CLASS(LayerRenderStateFlags)
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(LayerRenderStateFlags)

Просмотреть файл

@ -286,14 +286,6 @@ typedef mozilla::gfx::Matrix4x4 Matrix4x4;
* Pref that enables overscrolling. If this is disabled, excess scroll that
* cannot be handed off is discarded.
*
* "apz.overscroll.fling_friction"
* Amount of friction applied during flings when in overscroll.
*
* "apz.overscroll.fling_stopped_threshold"
* When flinging in an overscrolled state, if the velocity goes below this
* number, we stop the fling.
* Units: screen pixels per millisecond
*
* "apz.overscroll.min_pan_distance_ratio"
* The minimum ratio of the pan distance along one axis to the pan distance
* along the other axis needed to initiate overscroll along the first axis
@ -305,18 +297,21 @@ typedef mozilla::gfx::Matrix4x4 Matrix4x4;
* (So if kStretchFactor is 0, you can't stretch at all; if kStretchFactor
* is 1, you can stretch at most by a factor of 2).
*
* "apz.overscroll.snap_back.spring_stiffness"
* "apz.overscroll.spring_stiffness"
* The stiffness of the spring used in the physics model for the overscroll
* snap-back animation.
*
* "apz.overscroll.snap_back.spring_damping"
* The friction of the spring used in the physics model for the overscroll
* snap-back animation.
*
* "apz.overscroll.snap_back.mass"
* The mass of the page in the physics model for the overscroll snap-back
* animation.
*
* "apz.overscroll.spring_friction"
* The friction of the spring used in the physics model for the overscroll
* animation.
*
* "apz.overscroll.stop_distance_threshold"
* "apz.overscroll.stop_velocity_threshold"
* Thresholds for stopping the overscroll animation. When both the distance
* and the velocity fall below their thresholds, we stop oscillating.
* Units: screen pixels (for distance)
* screen pixels per millisecond (for velocity)
*
* "apz.pan_repaint_interval"
* Maximum amount of time while panning before sending a viewport change. This
* will asynchronously repaint the page. It is also forced when panning stops.
@ -472,15 +467,27 @@ class FlingAnimation: public AsyncPanZoomAnimation {
public:
FlingAnimation(AsyncPanZoomController& aApzc,
const nsRefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
bool aApplyAcceleration,
bool aAllowOverscroll)
bool aApplyAcceleration)
: AsyncPanZoomAnimation(TimeDuration::FromMilliseconds(gfxPrefs::APZFlingRepaintInterval()))
, mApzc(aApzc)
, mOverscrollHandoffChain(aOverscrollHandoffChain)
, mAllowOverscroll(aAllowOverscroll)
{
MOZ_ASSERT(mOverscrollHandoffChain);
TimeStamp now = GetFrameTime();
// Drop any velocity on axes where we don't have room to scroll anyways.
// This ensures that we don't take the 'overscroll' path in Sample()
// on account of one axis which can't scroll having a velocity.
{
ReentrantMonitorAutoEnter lock(mApzc.mMonitor);
if (!mApzc.mX.CanScroll()) {
mApzc.mX.SetVelocity(0);
}
if (!mApzc.mY.CanScroll()) {
mApzc.mY.SetVelocity(0);
}
}
ScreenPoint velocity(mApzc.mX.GetVelocity(), mApzc.mY.GetVelocity());
// If the last fling was very recent and in the same direction as this one,
@ -531,11 +538,8 @@ public:
return true;
}
bool overscrolled = mApzc.IsOverscrolled();
float friction = overscrolled ? gfxPrefs::APZOverscrollFlingFriction()
: gfxPrefs::APZFlingFriction();
float threshold = overscrolled ? gfxPrefs::APZOverscrollFlingStoppedThreshold()
: gfxPrefs::APZFlingStoppedThreshold();
float friction = gfxPrefs::APZFlingFriction();
float threshold = gfxPrefs::APZFlingStoppedThreshold();
bool shouldContinueFlingX = mApzc.mX.FlingApplyFrictionOrCancel(aDelta, friction, threshold),
shouldContinueFlingY = mApzc.mY.FlingApplyFrictionOrCancel(aDelta, friction, threshold);
@ -576,48 +580,37 @@ public:
// The fling may have caused us to reach the end of our scroll range.
if (!IsZero(overscroll)) {
if (mAllowOverscroll) {
// If this is a fling that allows overscroll, then go into overscroll.
// Hand off the fling to the next APZC in the overscroll handoff chain.
mApzc.OverscrollBy(overscroll);
// Restore the velocity of the fling, which was zeroed out by
// AdjustDisplacement().
mApzc.mX.SetVelocity(velocity.x);
mApzc.mY.SetVelocity(velocity.y);
} else {
// Otherwise, hand off the fling to the next APZC in the overscroll
// handoff chain.
// We may have reached the end of the scroll range along one axis but
// not the other. In such a case we only want to hand off the relevant
// component of the fling.
if (FuzzyEqualsAdditive(overscroll.x, 0.0f, COORDINATE_EPSILON)) {
velocity.x = 0;
} else if (FuzzyEqualsAdditive(overscroll.y, 0.0f, COORDINATE_EPSILON)) {
velocity.y = 0;
}
// To hand off the fling, we attempt to find a target APZC and start a new
// fling with the same velocity on that APZC. For simplicity, the actual
// overscroll of the current sample is discarded rather than being handed
// off. The compositor should sample animations sufficiently frequently
// that this is not noticeable. The target APZC is chosen by seeing if
// there is an APZC further in the handoff chain which is pannable; if
// there isn't, we take the new fling ourselves, entering an overscrolled
// state.
// Note: APZC is holding mMonitor, so directly calling
// HandleFlingOverscroll() (which acquires the tree lock) would violate
// the lock ordering. Instead we schedule HandleFlingOverscroll() to be
// called after mMonitor is released.
mDeferredTasks.append(NewRunnableMethod(&mApzc,
&AsyncPanZoomController::HandleFlingOverscroll,
velocity,
mOverscrollHandoffChain));
return false;
// We may have reached the end of the scroll range along one axis but
// not the other. In such a case we only want to hand off the relevant
// component of the fling.
// TODO(botond): If our intention is to continue the other component
// in this APZC, we should not be returning 'false'.
if (FuzzyEqualsAdditive(overscroll.x, 0.0f, COORDINATE_EPSILON)) {
velocity.x = 0;
} else if (FuzzyEqualsAdditive(overscroll.y, 0.0f, COORDINATE_EPSILON)) {
velocity.y = 0;
}
// To hand off the fling, we attempt to find a target APZC and start a new
// fling with the same velocity on that APZC. For simplicity, the actual
// overscroll of the current sample is discarded rather than being handed
// off. The compositor should sample animations sufficiently frequently
// that this is not noticeable. The target APZC is chosen by seeing if
// there is an APZC further in the handoff chain which is pannable; if
// there isn't, we take the new fling ourselves, entering an overscrolled
// state.
// Note: APZC is holding mMonitor, so directly calling
// HandleFlingOverscroll() (which acquires the tree lock) would violate
// the lock ordering. Instead we schedule HandleFlingOverscroll() to be
// called after mMonitor is released.
mDeferredTasks.append(NewRunnableMethod(&mApzc,
&AsyncPanZoomController::HandleFlingOverscroll,
velocity,
mOverscrollHandoffChain));
return false;
}
return true;
@ -639,7 +632,6 @@ private:
AsyncPanZoomController& mApzc;
nsRefPtr<const OverscrollHandoffChain> mOverscrollHandoffChain;
bool mAllowOverscroll;
};
class ZoomAnimation: public AsyncPanZoomAnimation {
@ -701,24 +693,21 @@ private:
CSSToScreenScale mEndZoom;
};
class OverscrollSnapBackAnimation: public AsyncPanZoomAnimation {
class OverscrollAnimation: public AsyncPanZoomAnimation {
public:
explicit OverscrollSnapBackAnimation(AsyncPanZoomController& aApzc)
explicit OverscrollAnimation(AsyncPanZoomController& aApzc, const ScreenPoint& aVelocity)
: mApzc(aApzc)
{
// Make sure the initial velocity is zero. This is normally the case
// since we've just stopped a fling, but in some corner cases involving
// handoff it could not be.
mApzc.mX.SetVelocity(0);
mApzc.mY.SetVelocity(0);
mApzc.mX.SetVelocity(aVelocity.x);
mApzc.mY.SetVelocity(aVelocity.y);
}
virtual bool Sample(FrameMetrics& aFrameMetrics,
const TimeDuration& aDelta) MOZ_OVERRIDE
{
// Can't inline these variables due to short-circuit evaluation.
bool continueX = mApzc.mX.SampleSnapBack(aDelta);
bool continueY = mApzc.mY.SampleSnapBack(aDelta);
bool continueX = mApzc.mX.SampleOverscrollAnimation(aDelta);
bool continueY = mApzc.mY.SampleOverscrollAnimation(aDelta);
return continueX || continueY;
}
private:
@ -1217,9 +1206,10 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent)
NS_WARNING("Gesture listener should have handled pinching in OnTouchMove.");
return nsEventStatus_eIgnore;
case SNAP_BACK: // Should not receive a touch-move in the SNAP_BACK state
// as touch blocks that begin in an overscrolled state
// are ignored.
case OVERSCROLL_ANIMATION:
// Should not receive a touch-move in the OVERSCROLL_ANIMATION state
// as touch blocks that begin in an overscrolled state
// are ignored.
NS_WARNING("Received impossible touch in OnTouchMove");
break;
}
@ -1301,9 +1291,10 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
NS_WARNING("Gesture listener should have handled pinching in OnTouchEnd.");
return nsEventStatus_eIgnore;
case SNAP_BACK: // Should not receive a touch-move in the SNAP_BACK state
// as touch blocks that begin in an overscrolled state
// are ignored.
case OVERSCROLL_ANIMATION:
// Should not receive a touch-move in the OVERSCROLL_ANIMATION state
// as touch blocks that begin in an overscrolled state
// are ignored.
NS_WARNING("Received impossible touch in OnTouchEnd");
break;
}
@ -1988,8 +1979,7 @@ nsRefPtr<const OverscrollHandoffChain> AsyncPanZoomController::BuildOverscrollHa
void AsyncPanZoomController::AcceptFling(const ScreenPoint& aVelocity,
const nsRefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
bool aHandoff,
bool aAllowOverscroll) {
bool aHandoff) {
// We may have a pre-existing velocity for whatever reason (for example,
// a previously handed off fling). We don't want to clobber that.
mX.SetVelocity(mX.GetVelocity() + aVelocity.x);
@ -1997,8 +1987,7 @@ void AsyncPanZoomController::AcceptFling(const ScreenPoint& aVelocity,
SetState(FLING);
StartAnimation(new FlingAnimation(*this,
aOverscrollHandoffChain,
!aHandoff, // only apply acceleration if this is an initial fling
aAllowOverscroll));
!aHandoff)); // only apply acceleration if this is an initial fling
}
bool AsyncPanZoomController::AttemptFling(ScreenPoint aVelocity,
@ -2008,8 +1997,7 @@ bool AsyncPanZoomController::AttemptFling(ScreenPoint aVelocity,
if (IsPannable()) {
AcceptFling(aVelocity,
aOverscrollHandoffChain,
aHandoff,
false /* do not allow overscroll */);
aHandoff);
return true;
}
@ -2023,12 +2011,10 @@ void AsyncPanZoomController::HandleFlingOverscroll(const ScreenPoint& aVelocity,
aVelocity,
aOverscrollHandoffChain,
true /* handoff */))) {
// No one wanted the fling, so we enter into an overscroll fling ourselves.
// No one wanted the fling, so we "take it" ourselves by entering an
// overscroll animation starting with the fling's velocity.
if (IsPannable()) {
AcceptFling(aVelocity,
aOverscrollHandoffChain,
true /* handoff */,
true /* allow overscroll */);
StartOverscrollAnimation(aVelocity);
}
}
}
@ -2055,9 +2041,9 @@ void AsyncPanZoomController::StartSmoothScroll() {
gfxPrefs::ScrollBehaviorDampingRatio()));
}
void AsyncPanZoomController::StartSnapBack() {
SetState(SNAP_BACK);
StartAnimation(new OverscrollSnapBackAnimation(*this));
void AsyncPanZoomController::StartOverscrollAnimation(const ScreenPoint& aVelocity) {
SetState(OVERSCROLL_ANIMATION);
StartAnimation(new OverscrollAnimation(*this, aVelocity));
}
bool AsyncPanZoomController::CallDispatchScroll(const ScreenPoint& aStartPoint,
@ -2291,7 +2277,7 @@ bool AsyncPanZoomController::SnapBackIfOverscrolled() {
ReentrantMonitorAutoEnter lock(mMonitor);
if (IsOverscrolled()) {
APZC_LOG("%p is overscrolled, starting snap-back\n", this);
StartSnapBack();
StartOverscrollAnimation(ScreenPoint(0, 0));
return true;
}
return false;
@ -2450,20 +2436,31 @@ Matrix4x4 AsyncPanZoomController::GetOverscrollTransform() const {
float scaleX = 1 + kStretchFactor * fabsf(mX.GetOverscroll()) / mX.GetCompositionLength();
float scaleY = 1 + kStretchFactor * fabsf(mY.GetOverscroll()) / mY.GetCompositionLength();
// If an axis is in underscroll, the interpretation of its overscroll
// amount changes: instead of stretching along that axis, we compress.
if (mX.IsInUnderscroll()) {
scaleX = 1 / scaleX;
}
if (mY.IsInUnderscroll()) {
scaleY = 1 / scaleY;
}
// The scale is applied relative to the origin of the composition bounds, i.e.
// it keeps the top-left corner of the content in place. This is fine if we
// are overscrolling at the top or on the left, but if we are overscrolling
// at the bottom or on the right, we want the bottom or right edge of the
// content to stay in place instead, so we add a translation to compensate.
ScreenPoint translation;
if (mX.IsOverscrolled() && mX.GetOverscroll() > 0) {
// Overscrolled on the right.
bool overscrolledOnRight = (mX.GetOverscroll() > 0 && !mX.IsInUnderscroll())
|| (mX.GetOverscroll() < 0 && mX.IsInUnderscroll());
if (overscrolledOnRight) {
ScreenCoord overscrolledCompositionWidth = scaleX * compositionSize.width;
ScreenCoord extraCompositionWidth = overscrolledCompositionWidth - compositionSize.width;
translation.x = -extraCompositionWidth;
}
if (mY.IsOverscrolled() && mY.GetOverscroll() > 0) {
// Overscrolled at the bottomn.
bool overscrolledAtBottom = (mY.GetOverscroll() > 0 && !mY.IsInUnderscroll())
|| (mY.GetOverscroll() < 0 && mY.IsInUnderscroll());
if (overscrolledAtBottom) {
ScreenCoord overscrolledCompositionHeight = scaleY * compositionSize.height;
ScreenCoord extraCompositionHeight = overscrolledCompositionHeight - compositionSize.height;
translation.y = -extraCompositionHeight;

Просмотреть файл

@ -725,7 +725,8 @@ protected:
PINCHING, /* nth touch-start, where n > 1. this mode allows pan and zoom */
ANIMATING_ZOOM, /* animated zoom to a new rect */
SNAP_BACK, /* snap-back animation to relieve overscroll */
OVERSCROLL_ANIMATION, /* Spring-based animation used to relieve overscroll once
the finger is lifted. */
SMOOTH_SCROLL, /* Smooth scrolling to destination. Used by
CSSOM-View smooth scroll-behavior */
};
@ -829,7 +830,7 @@ public:
private:
friend class FlingAnimation;
friend class OverscrollSnapBackAnimation;
friend class OverscrollAnimation;
friend class SmoothScrollAnimation;
// The initial velocity of the most recent fling.
ScreenPoint mLastFlingVelocity;
@ -849,11 +850,10 @@ private:
// Helper function used by TakeOverFling() and HandleFlingOverscroll().
void AcceptFling(const ScreenPoint& aVelocity,
const nsRefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
bool aHandoff,
bool aAllowOverscroll);
bool aHandoff);
// Start a snap-back animation to relieve overscroll.
void StartSnapBack();
// Start an overscroll animation with the given initial velocity.
void StartOverscrollAnimation(const ScreenPoint& aVelocity);
void StartSmoothScroll();

Просмотреть файл

@ -37,7 +37,8 @@ Axis::Axis(AsyncPanZoomController* aAsyncPanZoomController)
mVelocity(0.0f),
mAxisLocked(false),
mAsyncPanZoomController(aAsyncPanZoomController),
mOverscroll(0)
mOverscroll(0),
mInUnderscroll(false)
{
}
@ -181,8 +182,12 @@ ScreenCoord Axis::GetOverscroll() const {
return mOverscroll;
}
bool Axis::SampleSnapBack(const TimeDuration& aDelta) {
// Apply spring physics to the snap-back as time goes on.
bool Axis::IsInUnderscroll() const {
return mInUnderscroll;
}
bool Axis::SampleOverscrollAnimation(const TimeDuration& aDelta) {
// Apply spring physics to the overscroll as time goes on.
// Note: this method of sampling isn't perfectly smooth, as it assumes
// a constant velocity over 'aDelta', instead of an accelerating velocity.
// (The way we applying friction to flings has the same issue.)
@ -196,40 +201,45 @@ bool Axis::SampleSnapBack(const TimeDuration& aDelta) {
// b is a constant that provides damping (friction)
// v is the velocity of the point at the end of the spring
// See http://gafferongames.com/game-physics/spring-physics/
const float kSpringStiffness = gfxPrefs::APZOverscrollSnapBackSpringStiffness();
const float kSpringFriction = gfxPrefs::APZOverscrollSnapBackSpringFriction();
const float kMass = gfxPrefs::APZOverscrollSnapBackMass();
float force = -1 * kSpringStiffness * mOverscroll - kSpringFriction * mVelocity;
float acceleration = force / kMass;
mVelocity += acceleration * aDelta.ToMilliseconds();
float displacement = mVelocity * aDelta.ToMilliseconds();
if (mOverscroll > 0) {
if (displacement > 0) {
NS_WARNING("Overscroll snap-back animation is moving in the wrong direction!");
return false;
}
mOverscroll = std::max(mOverscroll + displacement, 0.0f);
// Overscroll relieved, do not continue animation.
if (mOverscroll == 0.f) {
mVelocity = 0;
return false;
}
return true;
} else if (mOverscroll < 0) {
if (displacement < 0) {
NS_WARNING("Overscroll snap-back animation is moving in the wrong direction!");
return false;
}
mOverscroll = std::min(mOverscroll + displacement, 0.0f);
// Overscroll relieved, do not continue animation.
if (mOverscroll == 0.f) {
mVelocity = 0;
return false;
}
return true;
const float kSpringStiffness = gfxPrefs::APZOverscrollSpringStiffness();
const float kSpringFriction = gfxPrefs::APZOverscrollSpringFriction();
// Apply spring force.
float springForce = -1 * kSpringStiffness * mOverscroll;
// Assume unit mass, so force = acceleration.
mVelocity += springForce * aDelta.ToMilliseconds();
// Apply dampening.
mVelocity *= pow(double(1 - kSpringFriction), aDelta.ToMilliseconds());
// Adjust the amount of overscroll based on the velocity.
// Note that we allow for oscillations. mInUnderscroll tracks whether
// we are currently in a state where we have overshot and the spring is
// displaced in the other direction.
float oldOverscroll = mOverscroll;
mOverscroll += (mVelocity * aDelta.ToMilliseconds());
bool signChange = (oldOverscroll * mOverscroll) < 0;
if (signChange) {
// If the sign of mOverscroll changed, we have either entered underscroll
// or exited it.
mInUnderscroll = !mInUnderscroll;
}
// No overscroll on this axis, do not continue animation.
return false;
// If both the velocity and the displacement fall below a threshold, stop
// the animation so we don't continue doing tiny oscillations that aren't
// noticeable.
if (fabs(mOverscroll) < gfxPrefs::APZOverscrollStopDistanceThreshold() &&
fabs(mVelocity) < gfxPrefs::APZOverscrollStopVelocityThreshold()) {
// "Jump" to the at-rest state. The jump shouldn't be noticeable as the
// velocity and overscroll are already low.
mOverscroll = 0;
mVelocity = 0;
mInUnderscroll = false;
return false;
}
// Otherwise, continue the animation.
return true;
}
bool Axis::IsOverscrolled() const {

Просмотреть файл

@ -88,11 +88,17 @@ public:
*/
ScreenCoord GetOverscroll() const;
/**
* Return whether the axis is in underscroll. See |mInUnderscroll|
* for a detailed description.
*/
bool IsInUnderscroll() const;
/**
* Sample the snap-back animation to relieve overscroll.
* |aDelta| is the time since the last sample.
*/
bool SampleSnapBack(const TimeDuration& aDelta);
bool SampleOverscrollAnimation(const TimeDuration& aDelta);
/**
* Return whether this axis is overscrolled in either direction.
@ -218,9 +224,44 @@ protected:
// If this amount is nonzero, the relevant component of
// mAsyncPanZoomController->mFrameMetrics.mScrollOffset must be at its
// extreme allowed value in the relevant direction (that is, it must be at
// its maximum value if mOverscroll is positive, and at its minimum value
// if mOverscroll is negative).
// its maximum value if we are overscrolled at our composition length, and
// at its minimum value if we are overscrolled at the origin).
// Note that if |mInUnderscroll| is true, the interpretation of this field
// changes slightly (see below).
ScreenCoord mOverscroll;
// This flag is set when an overscroll animation is in a state where the
// spring physics caused a snap-back movement to "overshoot" its target and
// as a result the spring is stretched in a direction opposite to the one
// when we were in overscroll. We call this situation "underscroll". When in
// underscroll, mOverscroll can be nonzero, but rather than being
// interpreted as overscroll (stretch) at the other end of the composition
// bounds, it's interpeted as an "underscroll" (compression) at the same end.
// This table summarizes what the possible combinations of mOverscroll and
// mInUnderscroll mean:
//
// mOverscroll | mInUnderscroll | Description
//---------------------------------------------------------------------------
// negative | false | The axis is overscrolled at
// | | its origin. A stretch is applied
// | | with the content fixed in place
// | | at the origin.
//---------------------------------------------------------------------------
// positive | false | The axis is overscrolled at its
// | | composition end. A stretch is
// | | applied with the content fixed in
// | | place at the composition end.
//---------------------------------------------------------------------------
// positive | true | The axis is underscrolled at its
// | | origin. A compression is applied
// | | with the content fixed in place
// | | at the origin.
//---------------------------------------------------------------------------
// negative | true | The axis is underscrolled at its
// | | composition end. A compression is
// | | applied with the content fixed in
// | | place at the composition end.
//---------------------------------------------------------------------------
bool mInUnderscroll;
// A queue of (timestamp, velocity) pairs; these are the historical
// velocities at the given timestamps. Timestamps are in milliseconds,
// velocities are in screen pixels per ms. This member can only be

Просмотреть файл

@ -41,7 +41,7 @@ MacIOSurfaceTextureHostBasic::MacIOSurfaceTextureHostBasic(
{
mSurface = MacIOSurface::LookupSurface(aDescriptor.surface(),
aDescriptor.scaleFactor(),
aDescriptor.hasAlpha());
!aDescriptor.isOpaque());
}
gfx::SourceSurface*

Просмотреть файл

@ -814,17 +814,12 @@ SharedSurfaceToTexSource(gl::SharedSurface* abstractSurf, Compositor* compositor
#ifdef XP_WIN
case gl::SharedSurfaceType::EGLSurfaceANGLE: {
auto surf = gl::SharedSurface_ANGLEShareHandle::Cast(abstractSurf);
HANDLE shareHandle = surf->GetShareHandle();
MOZ_ASSERT(compositor->GetBackendType() == LayersBackend::LAYERS_D3D11);
CompositorD3D11* compositorD3D11 = static_cast<CompositorD3D11*>(compositor);
ID3D11Device* d3d = compositorD3D11->GetDevice();
RefPtr<ID3D11Texture2D> tex = surf->GetConsumerTexture();
nsRefPtr<ID3D11Texture2D> tex;
HRESULT hr = d3d->OpenSharedResource(shareHandle,
__uuidof(ID3D11Texture2D),
getter_AddRefs(tex));
if (FAILED(hr)) {
if (!tex) {
NS_WARNING("Failed to open shared resource.");
break;
}

Просмотреть файл

@ -188,7 +188,7 @@ DeviceManagerD3D9::Init()
wc.lpfnWndProc = ::DefWindowProc;
wc.lpszClassName = kClassName;
if (!RegisterClassW(&wc)) {
NS_WARNING("Failed to register window class for DeviceManager.");
gfxCriticalError() << "[D3D9] Failed to register class for DeviceManager";
return false;
}
}
@ -198,7 +198,7 @@ DeviceManagerD3D9::Init()
nullptr, GetModuleHandle(nullptr), nullptr);
if (!mFocusWnd) {
NS_WARNING("Failed to create DeviceManagerD3D9 Window.");
gfxCriticalError() << "[D3D9] Failed to create a window";
return false;
}
@ -234,12 +234,14 @@ DeviceManagerD3D9::Init()
if (!mD3D9) {
if (!d3d9Create) {
gfxCriticalError() << "[D3D9] Failed to load symbols";
return false;
}
mD3D9 = dont_AddRef(d3d9Create(D3D_SDK_VERSION));
if (!mD3D9) {
gfxCriticalError() << "[D3D9] Failed to create the device";
return false;
}
}
@ -248,6 +250,7 @@ DeviceManagerD3D9::Init()
hr = mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &ident);
if (FAILED(hr)) {
gfxCriticalError() << "[D3D9] Failed to create the environment";
return false;
}
@ -300,12 +303,13 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mDevice));
if (FAILED(hr)) {
NS_WARNING("Failed to create Device for DeviceManagerD3D9.");
gfxCriticalError() << "[D3D9] Failed to create the device";
return false;
}
}
if (!VerifyCaps()) {
gfxCriticalError() << "[D3D9] insufficient capabilities";
return false;
}
@ -328,10 +332,13 @@ DeviceManagerD3D9::Init()
mNv3DVUtils->SetDeviceInfo(devUnknown);
}
auto failCreateShaderMsg = "[D3D9] failed to create a critical resource (shader)";
hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVS,
getter_AddRefs(mLayerVS));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
return false;
}
@ -339,6 +346,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mRGBPS));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
return false;
}
@ -346,6 +354,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mRGBAPS));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
return false;
}
@ -353,6 +362,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mComponentPass1PS));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
return false;
}
@ -360,6 +370,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mComponentPass2PS));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
return false;
}
@ -367,6 +378,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mYCbCrPS));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
return false;
}
@ -374,6 +386,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mSolidColorPS));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
return false;
}
@ -381,12 +394,14 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mLayerVSMask));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
return false;
}
hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVSMask3D,
getter_AddRefs(mLayerVSMask3D));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
return false;
}
@ -394,6 +409,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mRGBPSMask));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
return false;
}
@ -401,6 +417,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mRGBAPSMask));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
return false;
}
@ -408,6 +425,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mRGBAPSMask3D));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
return false;
}
@ -415,6 +433,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mComponentPass1PSMask));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
return false;
}
@ -422,6 +441,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mComponentPass2PSMask));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
return false;
}
@ -429,6 +449,7 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mYCbCrPSMask));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
return false;
}
@ -436,15 +457,18 @@ DeviceManagerD3D9::Init()
getter_AddRefs(mSolidColorPSMask));
if (FAILED(hr)) {
gfxCriticalError() << failCreateShaderMsg;
return false;
}
if (!CreateVertexBuffer()) {
gfxCriticalError() << "[D3D9] Failed to create a critical resource (vbo)";
return false;
}
hr = mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
if (FAILED(hr)) {
gfxCriticalError() << "[D3D9] Failed to set the stream source";
return false;
}

Просмотреть файл

@ -53,7 +53,7 @@ struct SurfaceDescriptorD3D10 {
struct SurfaceDescriptorMacIOSurface {
uint32_t surface;
double scaleFactor;
bool hasAlpha;
bool isOpaque;
};
struct SurfaceTextureDescriptor {
@ -74,6 +74,7 @@ struct NewSurfaceDescriptorGralloc {
* Extra size member is necessary. See Bug 850566.
*/
IntSize size;
bool isOpaque;
};
struct SharedSurfaceDescriptor {

Просмотреть файл

@ -20,19 +20,6 @@ namespace layers {
using namespace mozilla::gfx;
using namespace android;
GrallocTextureClientOGL::GrallocTextureClientOGL(MaybeMagicGrallocBufferHandle buffer,
gfx::IntSize aSize,
gfx::BackendType aMoz2dBackend,
TextureFlags aFlags)
: BufferTextureClient(nullptr, gfx::SurfaceFormat::UNKNOWN, aMoz2dBackend, aFlags)
, mGrallocHandle(buffer)
, mMappedBuffer(nullptr)
, mMediaBuffer(nullptr)
{
InitWith(buffer, aSize);
MOZ_COUNT_CTOR(GrallocTextureClientOGL);
}
GrallocTextureClientOGL::GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
gfx::SurfaceFormat aFormat,
gfx::BackendType aMoz2dBackend,
@ -41,6 +28,7 @@ GrallocTextureClientOGL::GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
, mGrallocHandle(null_t())
, mMappedBuffer(nullptr)
, mMediaBuffer(nullptr)
, mIsOpaque(gfx::IsOpaque(aFormat))
{
MOZ_COUNT_CTOR(GrallocTextureClientOGL);
}
@ -89,7 +77,7 @@ GrallocTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
return false;
}
aOutDescriptor = NewSurfaceDescriptorGralloc(mGrallocHandle, mSize);
aOutDescriptor = NewSurfaceDescriptorGralloc(mGrallocHandle, mSize, mIsOpaque);
return true;
}

Просмотреть файл

@ -37,10 +37,6 @@ namespace layers {
class GrallocTextureClientOGL : public BufferTextureClient
{
public:
GrallocTextureClientOGL(MaybeMagicGrallocBufferHandle buffer,
gfx::IntSize aSize,
gfx::BackendType aMoz2dBackend,
TextureFlags aFlags = TextureFlags::DEFAULT);
GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
gfx::SurfaceFormat aFormat,
gfx::BackendType aMoz2dBackend,
@ -95,6 +91,8 @@ public:
bool AllocateGralloc(gfx::IntSize aYSize, uint32_t aAndroidFormat, uint32_t aUsage);
void SetIsOpaque(bool aIsOpaque) { mIsOpaque = aIsOpaque; }
virtual bool Allocate(uint32_t aSize) MOZ_OVERRIDE;
virtual size_t GetBufferSize() const MOZ_OVERRIDE;
@ -147,6 +145,8 @@ protected:
gfx::IntSize mSize;
android::MediaBuffer* mMediaBuffer;
bool mIsOpaque;
};
} // namespace layers

Просмотреть файл

@ -246,6 +246,7 @@ GrallocTextureHostOGL::GrallocTextureHostOGL(TextureFlags aFlags,
, mDescriptorSize(aDescriptor.size())
, mFormat(gfx::SurfaceFormat::UNKNOWN)
, mEGLImage(EGL_NO_IMAGE)
, mIsOpaque(aDescriptor.isOpaque())
{
android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
MOZ_ASSERT(graphicBuffer);
@ -362,6 +363,9 @@ GrallocTextureHostOGL::GetRenderState()
if (graphicBuffer) {
LayerRenderStateFlags flags = LayerRenderStateFlags::LAYER_RENDER_STATE_DEFAULT;
if (mIsOpaque) {
flags |= LayerRenderStateFlags::OPAQUE;
}
if (mFlags & TextureFlags::NEEDS_Y_FLIP) {
flags |= LayerRenderStateFlags::Y_FLIPPED;
}

Просмотреть файл

@ -153,6 +153,7 @@ private:
gfx::IntSize mDescriptorSize;
gfx::SurfaceFormat mFormat;
EGLImage mEGLImage;
bool mIsOpaque;
};
} // namespace layers

Просмотреть файл

@ -55,7 +55,7 @@ MacIOSurfaceTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescrip
}
aOutDescriptor = SurfaceDescriptorMacIOSurface(mSurface->GetIOSurfaceID(),
mSurface->GetContentsScaleFactor(),
mSurface->HasAlpha());
!mSurface->HasAlpha());
return true;
}

Просмотреть файл

@ -16,7 +16,7 @@ MacIOSurfaceTextureHostOGL::MacIOSurfaceTextureHostOGL(TextureFlags aFlags,
{
mSurface = MacIOSurface::LookupSurface(aDescriptor.surface(),
aDescriptor.scaleFactor(),
aDescriptor.hasAlpha());
!aDescriptor.isOpaque());
}
bool

Просмотреть файл

@ -1019,33 +1019,22 @@ TEST_F(APZCBasicTester, OverScrollPanning) {
ApzcPan(apzc, time, touchStart, touchEnd);
EXPECT_TRUE(apzc->IsOverscrolled());
// Note that in the calls to SampleContentTransformForFrame below, the time
// increment used is sufficiently large for the animation to have completed. However,
// any single call to SampleContentTransformForFrame will not finish an animation
// *and* also proceed through the following animation, if there is one.
// Therefore the minimum number of calls to go from an overscroll-inducing pan
// to a reset state is 3; these are documented further below.
// Check that we recover from overscroll via an animation.
const TimeDuration increment = TimeDuration::FromMilliseconds(1);
bool recoveredFromOverscroll = false;
ScreenPoint pointOut;
ViewTransform viewTransformOut;
while (apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut)) {
// The reported scroll offset should be the same throughout.
EXPECT_EQ(ScreenPoint(0, 90), pointOut);
// This sample will run to the end of the non-overscrolling fling animation
// and will schedule the overscrolling fling animation.
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(10000), &viewTransformOut, pointOut);
EXPECT_EQ(ScreenPoint(0, 90), pointOut);
EXPECT_TRUE(apzc->IsOverscrolled());
// This sample will run to the end of the overscrolling fling animation and
// will schedule the snapback animation.
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(20000), &viewTransformOut, pointOut);
EXPECT_EQ(ScreenPoint(0, 90), pointOut);
EXPECT_TRUE(apzc->IsOverscrolled());
// This sample will run to the end of the snapback animation and reset the state.
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(30000), &viewTransformOut, pointOut);
EXPECT_EQ(ScreenPoint(0, 90), pointOut);
EXPECT_FALSE(apzc->IsOverscrolled());
if (!apzc->IsOverscrolled()) {
recoveredFromOverscroll = true;
}
testStartTime += increment;
}
EXPECT_TRUE(recoveredFromOverscroll);
apzc->AssertStateIsReset();
}
@ -1062,13 +1051,12 @@ TEST_F(APZCBasicTester, OverScrollAbort) {
ScreenPoint pointOut;
ViewTransform viewTransformOut;
// This sample call will run to the end of the non-overscrolling fling animation
// and will schedule the overscrolling fling animation (see comment in OverScrollPanning
// above for more explanation).
// This sample call will run to the end of the fling animation
// and will schedule the overscroll animation.
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(10000), &viewTransformOut, pointOut);
EXPECT_TRUE(apzc->IsOverscrolled());
// At this point, we have an active overscrolling fling animation.
// At this point, we have an active overscroll animation.
// Check that cancelling the animation clears the overscroll.
apzc->CancelAnimation();
EXPECT_FALSE(apzc->IsOverscrolled());

Просмотреть файл

@ -676,6 +676,14 @@ gfxContext::Clip(const gfxRect& rect)
Clip(ToRect(rect));
}
void
gfxContext::Clip(Path* aPath)
{
mDT->PushClip(aPath);
AzureState::PushedClip clip = { aPath, Rect(), mTransform };
CurrentState().pushedClips.AppendElement(clip);
}
void
gfxContext::Clip()
{

Просмотреть файл

@ -505,6 +505,7 @@ public:
*/
void Clip(const Rect& rect);
void Clip(const gfxRect& rect); // will clip to a rect
void Clip(Path* aPath);
/**
* This will ensure that the surface actually has its clip set.

Просмотреть файл

@ -160,13 +160,12 @@ private:
DECL_GFX_PREF(Live, "apz.min_skate_speed", APZMinSkateSpeed, float, 1.0f);
DECL_GFX_PREF(Live, "apz.num_paint_duration_samples", APZNumPaintDurationSamples, int32_t, 3);
DECL_GFX_PREF(Live, "apz.overscroll.enabled", APZOverscrollEnabled, bool, false);
DECL_GFX_PREF(Live, "apz.overscroll.fling_friction", APZOverscrollFlingFriction, float, 0.02f);
DECL_GFX_PREF(Live, "apz.overscroll.fling_stopped_threshold", APZOverscrollFlingStoppedThreshold, float, 0.4f);
DECL_GFX_PREF(Live, "apz.overscroll.min_pan_distance_ratio", APZMinPanDistanceRatio, float, 1.0f);
DECL_GFX_PREF(Live, "apz.overscroll.stretch_factor", APZOverscrollStretchFactor, float, 0.5f);
DECL_GFX_PREF(Live, "apz.overscroll.snap_back.spring_stiffness", APZOverscrollSnapBackSpringStiffness, float, 0.6f);
DECL_GFX_PREF(Live, "apz.overscroll.snap_back.spring_friction", APZOverscrollSnapBackSpringFriction, float, 0.1f);
DECL_GFX_PREF(Live, "apz.overscroll.snap_back.mass", APZOverscrollSnapBackMass, float, 1000.0f);
DECL_GFX_PREF(Live, "apz.overscroll.spring_stiffness", APZOverscrollSpringStiffness, float, 0.001f);
DECL_GFX_PREF(Live, "apz.overscroll.spring_friction", APZOverscrollSpringFriction, float, 0.015f);
DECL_GFX_PREF(Live, "apz.overscroll.stop_distance_threshold", APZOverscrollStopDistanceThreshold, float, 5.0f);
DECL_GFX_PREF(Live, "apz.overscroll.stop_velocity_threshold", APZOverscrollStopVelocityThreshold, float, 0.01f);
DECL_GFX_PREF(Live, "apz.pan_repaint_interval", APZPanRepaintInterval, int32_t, 250);
DECL_GFX_PREF(Live, "apz.printtree", APZPrintTree, bool, false);
DECL_GFX_PREF(Live, "apz.smooth_scroll_repaint_interval", APZSmoothScrollRepaintInterval, int32_t, 75);

Просмотреть файл

@ -1184,6 +1184,8 @@ gfxUtils::EncodeSourceSurface(SourceSurface* aSurface,
}
}
}
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(!imgData.empty(), NS_ERROR_FAILURE);
if (aBinaryOrData == eBinaryEncode) {
if (aFile) {

Просмотреть файл

@ -500,7 +500,7 @@ AsmJSHandleExecutionInterrupt()
{
AsmJSActivation *act = PerThreadData::innermostAsmJSActivation();
act->module().setInterrupted(true);
bool ret = HandleExecutionInterrupt(act->cx());
bool ret = CheckForInterrupt(act->cx());
act->module().setInterrupted(false);
return ret;
}
@ -672,8 +672,8 @@ AddressOf(AsmJSImmKind kind, ExclusiveContext *cx)
switch (kind) {
case AsmJSImm_Runtime:
return cx->runtimeAddressForJit();
case AsmJSImm_RuntimeInterrupt:
return cx->runtimeAddressOfInterrupt();
case AsmJSImm_RuntimeInterruptUint32:
return cx->runtimeAddressOfInterruptUint32();
case AsmJSImm_StackLimit:
return cx->stackLimitAddressForJitCode(StackForUntrustedScript);
case AsmJSImm_ReportOverRecursed:

Просмотреть файл

@ -705,13 +705,10 @@ Parser<ParseHandler>::parse(JSObject *chain)
Node pn = statements();
if (pn) {
bool matched;
if (!tokenStream.matchToken(&matched, TOK_EOF))
TokenKind tt;
if (!tokenStream.getToken(&tt))
return null();
if (!matched) {
TokenKind tt;
if (!tokenStream.peekToken(&tt))
return null();
if (tt != TOK_EOF) {
report(ParseError, false, null(), JSMSG_GARBAGE_AFTER_INPUT,
"script", TokenKindToDesc(tt));
return null();
@ -830,13 +827,10 @@ Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun, const AutoN
if (!pn)
return null();
bool matched;
if (!tokenStream.matchToken(&matched, TOK_EOF))
TokenKind tt;
if (!tokenStream.getToken(&tt))
return null();
if (!matched) {
TokenKind tt;
if (!tokenStream.peekToken(&tt))
return null();
if (tt != TOK_EOF) {
report(ParseError, false, null(), JSMSG_GARBAGE_AFTER_INPUT,
"function body", TokenKindToDesc(tt));
return null();

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше