зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to m-c. a=merge
This commit is contained in:
Коммит
85792b5ee7
|
@ -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/cert8.db
Двоичный файл не отображается.
Двоичные данные
build/pgo/certs/key3.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
|
||||
|
|
|
@ -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();
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче