merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2017-06-20 11:26:40 +02:00
commit 013fb0680e
97 changed files with 1552 additions and 847 deletions

View File

@ -132,6 +132,8 @@ AboutRedirector::NewChannel(nsIURI* aURI,
nsIChannel** result)
{
NS_ENSURE_ARG_POINTER(aURI);
NS_ENSURE_ARG_POINTER(aLoadInfo);
NS_ASSERTION(result, "must not be null");
nsAutoCString path = GetAboutModuleName(aURI);
@ -172,26 +174,22 @@ AboutRedirector::NewChannel(nsIURI* aURI,
NS_ENSURE_SUCCESS(rv, rv);
// If tempURI links to an external URI (i.e. something other than
// chrome:// or resource://) then set the LOAD_REPLACE flag on the
// channel which forces the channel owner to reflect the displayed
// chrome:// or resource://) then set the result principal URI on the
// load info which forces the channel prncipal to reflect the displayed
// URL rather then being the systemPrincipal.
bool isUIResource = false;
rv = NS_URIChainHasFlags(tempURI, nsIProtocolHandler::URI_IS_UI_RESOURCE,
&isUIResource);
NS_ENSURE_SUCCESS(rv, rv);
nsLoadFlags loadFlags = isUIResource
? static_cast<nsLoadFlags>(nsIChannel::LOAD_NORMAL)
: static_cast<nsLoadFlags>(nsIChannel::LOAD_REPLACE);
rv = NS_NewChannelInternal(getter_AddRefs(tempChannel),
tempURI,
aLoadInfo,
nullptr, // aLoadGroup
nullptr, // aCallbacks
loadFlags);
aLoadInfo);
NS_ENSURE_SUCCESS(rv, rv);
if (!isUIResource) {
aLoadInfo->SetResultPrincipalURI(tempURI);
}
tempChannel->SetOriginalURI(aURI);
NS_ADDREF(*result = tempChannel);

View File

@ -4,6 +4,6 @@ support-files =
dummy_page.html
[browser_PreviewProvider.js]
skip-if = os == 'linux' # bug 1343150
skip-if = os == 'linux' || os == 'win' # bug 1343150
[browser_remotenewtab_pageloads.js]
[browser_newtab_overrides.js]

View File

@ -1,5 +1,5 @@
This is the PDF.js project output, https://github.com/mozilla/pdf.js
Current extension version is: 1.8.450
Current extension version is: 1.8.467
Taken from upstream commit: 20975134
Taken from upstream commit: 679ffc84

View File

@ -3656,8 +3656,8 @@ var _UnsupportedManager = function UnsupportedManagerClosure() {
}();
var version, build;
{
exports.version = version = '1.8.450';
exports.build = build = '20975134';
exports.version = version = '1.8.467';
exports.build = build = '679ffc84';
}
exports.getDocument = getDocument;
exports.LoopbackPort = LoopbackPort;
@ -4659,8 +4659,8 @@ if (!_util.globalScope.PDFJS) {
}
var PDFJS = _util.globalScope.PDFJS;
{
PDFJS.version = '1.8.450';
PDFJS.build = '20975134';
PDFJS.version = '1.8.467';
PDFJS.build = '679ffc84';
}
PDFJS.pdfBug = false;
if (PDFJS.verbosity !== undefined) {
@ -10007,8 +10007,8 @@ exports.TilingPattern = TilingPattern;
"use strict";
var pdfjsVersion = '1.8.450';
var pdfjsBuild = '20975134';
var pdfjsVersion = '1.8.467';
var pdfjsBuild = '679ffc84';
var pdfjsSharedUtil = __w_pdfjs_require__(0);
var pdfjsDisplayGlobal = __w_pdfjs_require__(8);
var pdfjsDisplayAPI = __w_pdfjs_require__(3);

View File

@ -1454,7 +1454,7 @@ var Dict = function DictClosure() {
return nonSerializable;
};
function Dict(xref) {
this.map = Object.create(null);
this._map = Object.create(null);
this.xref = xref;
this.objId = null;
this.suppressEncryption = false;
@ -1468,32 +1468,32 @@ var Dict = function DictClosure() {
var value;
var xref = this.xref,
suppressEncryption = this.suppressEncryption;
if (typeof (value = this.map[key1]) !== 'undefined' || key1 in this.map || typeof key2 === 'undefined') {
if (typeof (value = this._map[key1]) !== 'undefined' || key1 in this._map || typeof key2 === 'undefined') {
return xref ? xref.fetchIfRef(value, suppressEncryption) : value;
}
if (typeof (value = this.map[key2]) !== 'undefined' || key2 in this.map || typeof key3 === 'undefined') {
if (typeof (value = this._map[key2]) !== 'undefined' || key2 in this._map || typeof key3 === 'undefined') {
return xref ? xref.fetchIfRef(value, suppressEncryption) : value;
}
value = this.map[key3] || null;
value = this._map[key3] || null;
return xref ? xref.fetchIfRef(value, suppressEncryption) : value;
},
getAsync: function Dict_getAsync(key1, key2, key3) {
var value;
var xref = this.xref,
suppressEncryption = this.suppressEncryption;
if (typeof (value = this.map[key1]) !== 'undefined' || key1 in this.map || typeof key2 === 'undefined') {
if (typeof (value = this._map[key1]) !== 'undefined' || key1 in this._map || typeof key2 === 'undefined') {
if (xref) {
return xref.fetchIfRefAsync(value, suppressEncryption);
}
return Promise.resolve(value);
}
if (typeof (value = this.map[key2]) !== 'undefined' || key2 in this.map || typeof key3 === 'undefined') {
if (typeof (value = this._map[key2]) !== 'undefined' || key2 in this._map || typeof key3 === 'undefined') {
if (xref) {
return xref.fetchIfRefAsync(value, suppressEncryption);
}
return Promise.resolve(value);
}
value = this.map[key3] || null;
value = this._map[key3] || null;
if (xref) {
return xref.fetchIfRefAsync(value, suppressEncryption);
}
@ -1516,36 +1516,36 @@ var Dict = function DictClosure() {
return value;
},
getRaw: function Dict_getRaw(key) {
return this.map[key];
return this._map[key];
},
getKeys: function Dict_getKeys() {
return Object.keys(this.map);
return Object.keys(this._map);
},
set: function Dict_set(key, value) {
this.map[key] = value;
this._map[key] = value;
},
has: function Dict_has(key) {
return key in this.map;
return key in this._map;
},
forEach: function Dict_forEach(callback) {
for (var key in this.map) {
for (var key in this._map) {
callback(key, this.get(key));
}
}
};
Dict.empty = new Dict(null);
Dict.merge = function Dict_merge(xref, dictArray) {
var mergedDict = new Dict(xref);
for (var i = 0, ii = dictArray.length; i < ii; i++) {
var dict = dictArray[i];
Dict.merge = function (xref, dictArray) {
let mergedDict = new Dict(xref);
for (let i = 0, ii = dictArray.length; i < ii; i++) {
let dict = dictArray[i];
if (!isDict(dict)) {
continue;
}
for (var keyName in dict.map) {
if (mergedDict.map[keyName]) {
for (let keyName in dict._map) {
if (mergedDict._map[keyName] !== undefined) {
continue;
}
mergedDict.map[keyName] = dict.map[keyName];
mergedDict._map[keyName] = dict._map[keyName];
}
}
return mergedDict;
@ -22751,86 +22751,83 @@ var FileSpec = function FileSpecClosure() {
};
return FileSpec;
}();
var ObjectLoader = function () {
let ObjectLoader = function () {
function mayHaveChildren(value) {
return (0, _primitives.isRef)(value) || (0, _primitives.isDict)(value) || (0, _util.isArray)(value) || (0, _primitives.isStream)(value);
}
function addChildren(node, nodesToVisit) {
var value;
if ((0, _primitives.isDict)(node) || (0, _primitives.isStream)(node)) {
var map;
if ((0, _primitives.isDict)(node)) {
map = node.map;
} else {
map = node.dict.map;
}
for (var key in map) {
value = map[key];
if (mayHaveChildren(value)) {
nodesToVisit.push(value);
let dict = (0, _primitives.isDict)(node) ? node : node.dict;
let dictKeys = dict.getKeys();
for (let i = 0, ii = dictKeys.length; i < ii; i++) {
let rawValue = dict.getRaw(dictKeys[i]);
if (mayHaveChildren(rawValue)) {
nodesToVisit.push(rawValue);
}
}
} else if ((0, _util.isArray)(node)) {
for (var i = 0, ii = node.length; i < ii; i++) {
value = node[i];
for (let i = 0, ii = node.length; i < ii; i++) {
let value = node[i];
if (mayHaveChildren(value)) {
nodesToVisit.push(value);
}
}
}
}
function ObjectLoader(obj, keys, xref) {
this.obj = obj;
function ObjectLoader(dict, keys, xref) {
this.dict = dict;
this.keys = keys;
this.xref = xref;
this.refSet = null;
this.capability = null;
}
ObjectLoader.prototype = {
load: function ObjectLoader_load() {
var keys = this.keys;
load() {
this.capability = (0, _util.createPromiseCapability)();
if (!(this.xref.stream instanceof _chunked_stream.ChunkedStream) || this.xref.stream.getMissingChunks().length === 0) {
this.capability.resolve();
return this.capability.promise;
}
let { keys, dict } = this;
this.refSet = new _primitives.RefSet();
var nodesToVisit = [];
for (var i = 0; i < keys.length; i++) {
nodesToVisit.push(this.obj[keys[i]]);
let nodesToVisit = [];
for (let i = 0, ii = keys.length; i < ii; i++) {
let rawValue = dict.getRaw(keys[i]);
if (rawValue !== undefined) {
nodesToVisit.push(rawValue);
}
}
this._walk(nodesToVisit);
return this.capability.promise;
},
_walk: function ObjectLoader_walk(nodesToVisit) {
var nodesToRevisit = [];
var pendingRequests = [];
_walk(nodesToVisit) {
let nodesToRevisit = [];
let pendingRequests = [];
while (nodesToVisit.length) {
var currentNode = nodesToVisit.pop();
let currentNode = nodesToVisit.pop();
if ((0, _primitives.isRef)(currentNode)) {
if (this.refSet.has(currentNode)) {
continue;
}
try {
var ref = currentNode;
this.refSet.put(ref);
this.refSet.put(currentNode);
currentNode = this.xref.fetch(currentNode);
} catch (e) {
if (!(e instanceof _util.MissingDataException)) {
throw e;
} catch (ex) {
if (!(ex instanceof _util.MissingDataException)) {
throw ex;
}
nodesToRevisit.push(currentNode);
pendingRequests.push({
begin: e.begin,
end: e.end
begin: ex.begin,
end: ex.end
});
}
}
if (currentNode && currentNode.getBaseStreams) {
var baseStreams = currentNode.getBaseStreams();
var foundMissingData = false;
for (var i = 0; i < baseStreams.length; i++) {
var stream = baseStreams[i];
let baseStreams = currentNode.getBaseStreams();
let foundMissingData = false;
for (let i = 0, ii = baseStreams.length; i < ii; i++) {
let stream = baseStreams[i];
if (stream.getMissingChunks && stream.getMissingChunks().length) {
foundMissingData = true;
pendingRequests.push({
@ -22847,14 +22844,13 @@ var ObjectLoader = function () {
}
if (pendingRequests.length) {
this.xref.stream.manager.requestRanges(pendingRequests).then(() => {
nodesToVisit = nodesToRevisit;
for (var i = 0; i < nodesToRevisit.length; i++) {
var node = nodesToRevisit[i];
for (let i = 0, ii = nodesToRevisit.length; i < ii; i++) {
let node = nodesToRevisit[i];
if ((0, _primitives.isRef)(node)) {
this.refSet.remove(node);
}
}
this._walk(nodesToVisit);
this._walk(nodesToRevisit);
}, this.capability.reject);
return;
}
@ -27469,7 +27465,7 @@ var Annotation = function AnnotationClosure() {
if (!resources) {
return;
}
var objectLoader = new _obj.ObjectLoader(resources.map, keys, resources.xref);
let objectLoader = new _obj.ObjectLoader(resources, keys, resources.xref);
return objectLoader.load().then(function () {
return resources;
});
@ -29006,7 +29002,7 @@ var Page = function PageClosure() {
this.resourcesPromise = this.pdfManager.ensure(this, 'resources');
}
return this.resourcesPromise.then(() => {
var objectLoader = new _obj.ObjectLoader(this.resources.map, keys, this.xref);
let objectLoader = new _obj.ObjectLoader(this.resources, keys, this.xref);
return objectLoader.load();
});
},
@ -39780,8 +39776,8 @@ exports.Type1Parser = Type1Parser;
"use strict";
var pdfjsVersion = '1.8.450';
var pdfjsBuild = '20975134';
var pdfjsVersion = '1.8.467';
var pdfjsBuild = '679ffc84';
var pdfjsCoreWorker = __w_pdfjs_require__(17);
;
exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;

View File

@ -876,6 +876,7 @@ var PDFViewerApplication = {
l10n: null,
pageRotation: 0,
isInitialViewSet: false,
downloadComplete: false,
viewerPrefs: {
sidebarViewOnLoad: _pdf_sidebar.SidebarView.NONE,
pdfBugEnabled: false,
@ -891,6 +892,7 @@ var PDFViewerApplication = {
url: '',
baseUrl: '',
externalServices: DefaultExternalServices,
_boundEvents: {},
initialize: function pdfViewInitialize(appConfig) {
this.preferences = this.externalServices.createPreferences();
configure(_pdfjsLib.PDFJS);
@ -1204,7 +1206,9 @@ var PDFViewerApplication = {
this.pdfDocumentProperties.setDocument(null, null);
}
this.store = null;
this.pageRotation = 0;
this.isInitialViewSet = false;
this.downloadComplete = false;
this.pdfSidebar.reset();
this.pdfOutlineViewer.reset();
this.pdfAttachmentViewer.reset();
@ -1247,7 +1251,6 @@ var PDFViewerApplication = {
this.pdfDocumentProperties.setFileSize(args.length);
}
}
this.downloadComplete = false;
let loadingTask = (0, _pdfjsLib.getDocument)(parameters);
this.pdfLoadingTask = loadingTask;
loadingTask.onPassword = (updateCallback, reason) => {
@ -1373,12 +1376,10 @@ var PDFViewerApplication = {
this.pdfLinkService.setDocument(pdfDocument, baseDocumentUrl);
this.pdfDocumentProperties.setDocument(pdfDocument, this.url);
let pdfViewer = this.pdfViewer;
pdfViewer.currentScale = scale;
pdfViewer.setDocument(pdfDocument);
let firstPagePromise = pdfViewer.firstPagePromise;
let pagesPromise = pdfViewer.pagesPromise;
let onePageRendered = pdfViewer.onePageRendered;
this.pageRotation = 0;
let pdfThumbnailViewer = this.pdfThumbnailViewer;
pdfThumbnailViewer.setDocument(pdfDocument);
firstPagePromise.then(pdfPage => {
@ -1618,8 +1619,11 @@ var PDFViewerApplication = {
}
this.forceRendering();
},
rotatePages: function pdfViewRotatePages(delta) {
var pageNumber = this.page;
rotatePages(delta) {
if (!this.pdfDocument) {
return;
}
let pageNumber = this.page;
this.pageRotation = (this.pageRotation + 360 + delta) % 360;
this.pdfViewer.pagesRotation = this.pageRotation;
this.pdfThumbnailViewer.pagesRotation = this.pageRotation;
@ -1632,12 +1636,14 @@ var PDFViewerApplication = {
}
this.pdfPresentationMode.request();
},
bindEvents: function pdfViewBindEvents() {
var eventBus = this.eventBus;
bindEvents() {
let eventBus = this.eventBus;
this._boundEvents.beforePrint = this.beforePrint.bind(this);
this._boundEvents.afterPrint = this.afterPrint.bind(this);
eventBus.on('resize', webViewerResize);
eventBus.on('hashchange', webViewerHashchange);
eventBus.on('beforeprint', this.beforePrint.bind(this));
eventBus.on('afterprint', this.afterPrint.bind(this));
eventBus.on('beforeprint', this._boundEvents.beforePrint);
eventBus.on('afterprint', this._boundEvents.afterPrint);
eventBus.on('pagerendered', webViewerPageRendered);
eventBus.on('textlayerrendered', webViewerTextLayerRendered);
eventBus.on('updateviewarea', webViewerUpdateViewarea);
@ -1665,23 +1671,75 @@ var PDFViewerApplication = {
eventBus.on('find', webViewerFind);
eventBus.on('findfromurlhash', webViewerFindFromUrlHash);
},
bindWindowEvents: function pdfViewBindWindowEvents() {
var eventBus = this.eventBus;
bindWindowEvents() {
let eventBus = this.eventBus;
this._boundEvents.windowResize = () => {
eventBus.dispatch('resize');
};
this._boundEvents.windowHashChange = () => {
eventBus.dispatch('hashchange', { hash: document.location.hash.substring(1) });
};
this._boundEvents.windowBeforePrint = () => {
eventBus.dispatch('beforeprint');
};
this._boundEvents.windowAfterPrint = () => {
eventBus.dispatch('afterprint');
};
window.addEventListener('wheel', webViewerWheel);
window.addEventListener('click', webViewerClick);
window.addEventListener('keydown', webViewerKeyDown);
window.addEventListener('resize', function windowResize() {
eventBus.dispatch('resize');
});
window.addEventListener('hashchange', function windowHashChange() {
eventBus.dispatch('hashchange', { hash: document.location.hash.substring(1) });
});
window.addEventListener('beforeprint', function windowBeforePrint() {
eventBus.dispatch('beforeprint');
});
window.addEventListener('afterprint', function windowAfterPrint() {
eventBus.dispatch('afterprint');
});
window.addEventListener('resize', this._boundEvents.windowResize);
window.addEventListener('hashchange', this._boundEvents.windowHashChange);
window.addEventListener('beforeprint', this._boundEvents.windowBeforePrint);
window.addEventListener('afterprint', this._boundEvents.windowAfterPrint);
},
unbindEvents() {
let eventBus = this.eventBus;
eventBus.off('resize', webViewerResize);
eventBus.off('hashchange', webViewerHashchange);
eventBus.off('beforeprint', this._boundEvents.beforePrint);
eventBus.off('afterprint', this._boundEvents.afterPrint);
eventBus.off('pagerendered', webViewerPageRendered);
eventBus.off('textlayerrendered', webViewerTextLayerRendered);
eventBus.off('updateviewarea', webViewerUpdateViewarea);
eventBus.off('pagechanging', webViewerPageChanging);
eventBus.off('scalechanging', webViewerScaleChanging);
eventBus.off('sidebarviewchanged', webViewerSidebarViewChanged);
eventBus.off('pagemode', webViewerPageMode);
eventBus.off('namedaction', webViewerNamedAction);
eventBus.off('presentationmodechanged', webViewerPresentationModeChanged);
eventBus.off('presentationmode', webViewerPresentationMode);
eventBus.off('openfile', webViewerOpenFile);
eventBus.off('print', webViewerPrint);
eventBus.off('download', webViewerDownload);
eventBus.off('firstpage', webViewerFirstPage);
eventBus.off('lastpage', webViewerLastPage);
eventBus.off('nextpage', webViewerNextPage);
eventBus.off('previouspage', webViewerPreviousPage);
eventBus.off('zoomin', webViewerZoomIn);
eventBus.off('zoomout', webViewerZoomOut);
eventBus.off('pagenumberchanged', webViewerPageNumberChanged);
eventBus.off('scalechanged', webViewerScaleChanged);
eventBus.off('rotatecw', webViewerRotateCw);
eventBus.off('rotateccw', webViewerRotateCcw);
eventBus.off('documentproperties', webViewerDocumentProperties);
eventBus.off('find', webViewerFind);
eventBus.off('findfromurlhash', webViewerFindFromUrlHash);
this._boundEvents.beforePrint = null;
this._boundEvents.afterPrint = null;
},
unbindWindowEvents() {
window.removeEventListener('wheel', webViewerWheel);
window.removeEventListener('click', webViewerClick);
window.removeEventListener('keydown', webViewerKeyDown);
window.removeEventListener('resize', this._boundEvents.windowResize);
window.removeEventListener('hashchange', this._boundEvents.windowHashChange);
window.removeEventListener('beforeprint', this._boundEvents.windowBeforePrint);
window.removeEventListener('afterprint', this._boundEvents.windowAfterPrint);
this._boundEvents.windowResize = null;
this._boundEvents.windowHashChange = null;
this._boundEvents.windowBeforePrint = null;
this._boundEvents.windowAfterPrint = null;
}
};
var validateFileURL;

View File

@ -53,7 +53,7 @@ if test "$GCC_USE_GNU_LD"; then
EXPAND_LIBS_ORDER_STYLE=)
LDFLAGS="$_SAVE_LDFLAGS"
if test -z "$EXPAND_LIBS_ORDER_STYLE"; then
if AC_TRY_COMMAND(${CC-cc} ${DSO_LDOPTS} ${LDFLAGS} -o ${DLL_PREFIX}conftest${DLL_SUFFIX} -Wl,--verbose 2> /dev/null | sed -n '/^===/,/^===/p' | grep '\.text'); then
if AC_TRY_COMMAND(${CC-cc} ${DSO_LDOPTS} ${LDFLAGS} -o conftest -Wl,--verbose 2> /dev/null | sed -n '/^===/,/^===/p' | grep '\.text'); then
EXPAND_LIBS_ORDER_STYLE=linkerscript
else
EXPAND_LIBS_ORDER_STYLE=none

View File

@ -0,0 +1 @@
<body>Follow-on navigation content</body>

View File

@ -0,0 +1,5 @@
function handleRequest(aRequest, aResponse) {
aResponse.setStatusLine(aRequest.httpVersion, 302, "Moved");
aResponse.setHeader("Location", "http://mochi.test:8888/tests/caps/tests/mochitest/file_bug1367586-target.html");
aResponse.write("To be redirected to target");
}

View File

@ -0,0 +1,6 @@
<head><script>
window.addEventListener("pageshow", function(event) {
parent.ok(!event.persisted, "Should not load from bfcache");
});
</script></head>
<body>Redirect target content</body>

View File

@ -1,5 +1,8 @@
[DEFAULT]
support-files =
file_bug1367586-followon.html
file_bug1367586-redirect.sjs
file_bug1367586-target.html
file_data.txt
file_disableScript.html
!/js/xpconnect/tests/mochitest/file_empty.html
@ -8,5 +11,6 @@ support-files =
[test_bug292789.html]
[test_bug423375.html]
[test_bug470804.html]
[test_bug1367586.html]
[test_disallowInheritPrincipal.html]
[test_extensionURL.html]

View File

@ -0,0 +1,50 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1367586
-->
<head>
<title>Test for Bug 1367586</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<iframe id="load-frame"></iframe>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
var frm = document.getElementById("load-frame");
var step = 0;
window.addEventListener("load", () => {
frm.contentWindow.location = "http://mochi.test:8888/tests/caps/tests/mochitest/file_bug1367586-redirect.sjs";
frm.addEventListener("load", function() {
++step;
SimpleTest.executeSoon((function(_step, _frm) {
switch (_step) {
case 1:
is(_frm.contentWindow.location.href, "http://mochi.test:8888/tests/caps/tests/mochitest/file_bug1367586-target.html",
"Redirected to the expected target in step 1");
_frm.contentWindow.location = "http://mochi.test:8888/tests/caps/tests/mochitest/file_bug1367586-followon.html";
break;
case 2:
is(_frm.contentWindow.location.href, "http://mochi.test:8888/tests/caps/tests/mochitest/file_bug1367586-followon.html",
"Navigated to the expected URL in step 2");
_frm.contentWindow.history.back();
break;
case 3:
is(_frm.contentWindow.location.href, "http://mochi.test:8888/tests/caps/tests/mochitest/file_bug1367586-target.html",
"Seeing the correct URL when navigating back in step 3");
SimpleTest.finish();
break;
}
}).bind(window, step, frm));
});
});
</script>
</pre>
</body>
</html>

View File

@ -105,6 +105,8 @@ nsChromeProtocolHandler::NewChannel2(nsIURI* aURI,
nsresult rv;
NS_ENSURE_ARG_POINTER(aURI);
NS_ENSURE_ARG_POINTER(aLoadInfo);
NS_PRECONDITION(aResult, "Null out param");
#ifdef DEBUG
@ -145,6 +147,12 @@ nsChromeProtocolHandler::NewChannel2(nsIURI* aURI,
return rv;
}
// We don't want to allow the inner protocol handler modify the result principal URI
// since we want either |aURI| or anything pre-set by upper layers to prevail.
nsCOMPtr<nsIURI> savedResultPrincipalURI;
rv = aLoadInfo->GetResultPrincipalURI(getter_AddRefs(savedResultPrincipalURI));
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_NewChannelInternal(getter_AddRefs(result),
resolvedURI,
aLoadInfo);
@ -168,9 +176,8 @@ nsChromeProtocolHandler::NewChannel2(nsIURI* aURI,
// Make sure that the channel remembers where it was
// originally loaded from.
nsLoadFlags loadFlags = 0;
result->GetLoadFlags(&loadFlags);
result->SetLoadFlags(loadFlags & ~nsIChannel::LOAD_REPLACE);
rv = aLoadInfo->SetResultPrincipalURI(savedResultPrincipalURI);
NS_ENSURE_SUCCESS(rv, rv);
rv = result->SetOriginalURI(aURI);
if (NS_FAILED(rv)) return rv;

View File

@ -26,6 +26,7 @@ AboutURL.prototype = {
newChannel: function (aURI, aLoadInfo) {
let chan = Services.io.newChannelFromURIWithLoadInfo(this.uri, aLoadInfo);
chan.owner = Services.scriptSecurityManager.getSystemPrincipal();
chan.originalURI = aURI;
return chan;
},

View File

@ -152,6 +152,7 @@ nsAboutRedirector::NewChannel(nsIURI* aURI,
nsIChannel** aResult)
{
NS_ENSURE_ARG_POINTER(aURI);
NS_ENSURE_ARG_POINTER(aLoadInfo);
NS_ASSERTION(aResult, "must not be null");
nsAutoCString path;
@ -168,9 +169,14 @@ nsAboutRedirector::NewChannel(nsIURI* aURI,
rv = NS_NewURI(getter_AddRefs(tempURI), kRedirMap[i].url);
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_NewChannelInternal(getter_AddRefs(tempChannel),
tempURI,
aLoadInfo);
NS_ENSURE_SUCCESS(rv, rv);
// If tempURI links to an external URI (i.e. something other than
// chrome:// or resource://) then set the LOAD_REPLACE flag on the
// channel which forces the channel owner to reflect the displayed
// chrome:// or resource://) then set result principal URI on the
// load info which forces the channel principal to reflect the displayed
// URL rather then being the systemPrincipal.
bool isUIResource = false;
rv = NS_URIChainHasFlags(tempURI, nsIProtocolHandler::URI_IS_UI_RESOURCE,
@ -179,17 +185,9 @@ nsAboutRedirector::NewChannel(nsIURI* aURI,
bool isAboutBlank = NS_IsAboutBlank(tempURI);
nsLoadFlags loadFlags = isUIResource || isAboutBlank
? static_cast<nsLoadFlags>(nsIChannel::LOAD_NORMAL)
: static_cast<nsLoadFlags>(nsIChannel::LOAD_REPLACE);
rv = NS_NewChannelInternal(getter_AddRefs(tempChannel),
tempURI,
aLoadInfo,
nullptr, // aLoadGroup
nullptr, // aCallbacks
loadFlags);
NS_ENSURE_SUCCESS(rv, rv);
if (!isUIResource && !isAboutBlank) {
aLoadInfo->SetResultPrincipalURI(tempURI);
}
tempChannel->SetOriginalURI(aURI);

View File

@ -1272,6 +1272,7 @@ nsDocShell::LoadURI(nsIURI* aURI,
nsCOMPtr<nsIURI> referrer;
nsCOMPtr<nsIURI> originalURI;
Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI;
bool loadReplace = false;
nsCOMPtr<nsIInputStream> postStream;
nsCOMPtr<nsIInputStream> headersStream;
@ -1300,6 +1301,7 @@ nsDocShell::LoadURI(nsIURI* aURI,
if (aLoadInfo) {
aLoadInfo->GetReferrer(getter_AddRefs(referrer));
aLoadInfo->GetOriginalURI(getter_AddRefs(originalURI));
GetMaybeResultPrincipalURI(aLoadInfo, resultPrincipalURI);
aLoadInfo->GetLoadReplace(&loadReplace);
nsDocShellInfoLoadType lt = nsIDocShellLoadInfo::loadNormal;
aLoadInfo->GetLoadType(&lt);
@ -1570,6 +1572,7 @@ nsDocShell::LoadURI(nsIURI* aURI,
return InternalLoad(aURI,
originalURI,
resultPrincipalURI,
loadReplace,
referrer,
referrerPolicy,
@ -5419,7 +5422,7 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
NS_ENSURE_SUCCESS(rv, rv);
return InternalLoad(errorPageURI, nullptr, false, nullptr,
return InternalLoad(errorPageURI, nullptr, Nothing(), false, nullptr,
mozilla::net::RP_Unset,
nsContentUtils::GetSystemPrincipal(), nullptr,
INTERNAL_LOAD_FLAGS_NONE, EmptyString(),
@ -5474,6 +5477,7 @@ nsDocShell::Reload(uint32_t aReloadFlags)
nsAutoString srcdoc;
nsCOMPtr<nsIURI> baseURI;
nsCOMPtr<nsIURI> originalURI;
nsCOMPtr<nsIURI> resultPrincipalURI;
bool loadReplace = false;
nsIPrincipal* triggeringPrincipal = doc->NodePrincipal();
@ -5494,6 +5498,11 @@ nsDocShell::Reload(uint32_t aReloadFlags)
if (httpChan) {
httpChan->GetOriginalURI(getter_AddRefs(originalURI));
}
nsCOMPtr<nsILoadInfo> loadInfo = chan->GetLoadInfo();
if (loadInfo) {
loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
}
}
MOZ_ASSERT(triggeringPrincipal, "Need a valid triggeringPrincipal");
@ -5503,8 +5512,13 @@ nsDocShell::Reload(uint32_t aReloadFlags)
nsCOMPtr<nsIURI> currentURI = mCurrentURI;
nsCOMPtr<nsIURI> referrerURI = mReferrerURI;
uint32_t referrerPolicy = mReferrerPolicy;
// Reload always rewrites result principal URI.
Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI;
emplacedResultPrincipalURI.emplace(Move(resultPrincipalURI));
rv = InternalLoad(currentURI,
originalURI,
emplacedResultPrincipalURI,
loadReplace,
referrerURI,
referrerPolicy,
@ -9623,8 +9637,11 @@ nsDocShell::CopyFavicon(nsIURI* aOldURI,
class InternalLoadEvent : public Runnable
{
public:
InternalLoadEvent(nsDocShell* aDocShell, nsIURI* aURI,
nsIURI* aOriginalURI, bool aLoadReplace,
InternalLoadEvent(nsDocShell* aDocShell,
nsIURI* aURI,
nsIURI* aOriginalURI,
Maybe<nsCOMPtr<nsIURI>> const& aResultPrincipalURI,
bool aLoadReplace,
nsIURI* aReferrer, uint32_t aReferrerPolicy,
nsIPrincipal* aTriggeringPrincipal,
nsIPrincipal* aPrincipalToInherit, uint32_t aFlags,
@ -9637,6 +9654,7 @@ public:
, mDocShell(aDocShell)
, mURI(aURI)
, mOriginalURI(aOriginalURI)
, mResultPrincipalURI(aResultPrincipalURI)
, mLoadReplace(aLoadReplace)
, mReferrer(aReferrer)
, mReferrerPolicy(aReferrerPolicy)
@ -9661,7 +9679,7 @@ public:
NS_IMETHOD
Run() override
{
return mDocShell->InternalLoad(mURI, mOriginalURI,
return mDocShell->InternalLoad(mURI, mOriginalURI, mResultPrincipalURI,
mLoadReplace,
mReferrer,
mReferrerPolicy,
@ -9682,6 +9700,7 @@ private:
RefPtr<nsDocShell> mDocShell;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIURI> mOriginalURI;
Maybe<nsCOMPtr<nsIURI>> mResultPrincipalURI;
bool mLoadReplace;
nsCOMPtr<nsIURI> mReferrer;
uint32_t mReferrerPolicy;
@ -9728,6 +9747,7 @@ nsDocShell::CreatePrincipalFromReferrer(nsIURI* aReferrer,
NS_IMETHODIMP
nsDocShell::InternalLoad(nsIURI* aURI,
nsIURI* aOriginalURI,
Maybe<nsCOMPtr<nsIURI>> const& aResultPrincipalURI,
bool aLoadReplace,
nsIURI* aReferrer,
uint32_t aReferrerPolicy,
@ -10063,6 +10083,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
loadInfo->SetSendReferrer(!(aFlags &
INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER));
loadInfo->SetOriginalURI(aOriginalURI);
SetMaybeResultPrincipalURI(loadInfo, aResultPrincipalURI);
loadInfo->SetLoadReplace(aLoadReplace);
loadInfo->SetTriggeringPrincipal(aTriggeringPrincipal);
loadInfo->SetInheritPrincipal(
@ -10110,6 +10131,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
if (NS_SUCCEEDED(rv) && targetDocShell) {
rv = targetDocShell->InternalLoad(aURI,
aOriginalURI,
aResultPrincipalURI,
aLoadReplace,
aReferrer,
aReferrerPolicy,
@ -10206,8 +10228,8 @@ nsDocShell::InternalLoad(nsIURI* aURI,
// Do this asynchronously
nsCOMPtr<nsIRunnable> ev =
new InternalLoadEvent(this, aURI, aOriginalURI, aLoadReplace,
aReferrer, aReferrerPolicy,
new InternalLoadEvent(this, aURI, aOriginalURI, aResultPrincipalURI,
aLoadReplace, aReferrer, aReferrerPolicy,
aTriggeringPrincipal, principalToInherit,
aFlags, aTypeHint, aPostData, aHeadersData,
aLoadType, aSHEntry, aFirstParty, aSrcdoc,
@ -10590,8 +10612,8 @@ nsDocShell::InternalLoad(nsIURI* aURI,
if (browserChrome3 && aCheckForPrerender) {
nsCOMPtr<nsIRunnable> ev =
new InternalLoadEvent(this, aURI, aOriginalURI, aLoadReplace,
aReferrer, aReferrerPolicy,
new InternalLoadEvent(this, aURI, aOriginalURI, aResultPrincipalURI,
aLoadReplace, aReferrer, aReferrerPolicy,
aTriggeringPrincipal, principalToInherit,
aFlags, aTypeHint, aPostData, aHeadersData,
aLoadType, aSHEntry, aFirstParty, aSrcdoc,
@ -10740,7 +10762,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr);
nsCOMPtr<nsIRequest> req;
rv = DoURILoad(aURI, aOriginalURI, aLoadReplace, aReferrer,
rv = DoURILoad(aURI, aOriginalURI, aResultPrincipalURI, aLoadReplace, aReferrer,
!(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER),
aReferrerPolicy,
aTriggeringPrincipal, principalToInherit, aTypeHint,
@ -10819,6 +10841,7 @@ nsDocShell::GetInheritedPrincipal(bool aConsiderCurrentDocument)
nsresult
nsDocShell::DoURILoad(nsIURI* aURI,
nsIURI* aOriginalURI,
Maybe<nsCOMPtr<nsIURI>> const& aResultPrincipalURI,
bool aLoadReplace,
nsIURI* aReferrerURI,
bool aSendReferrer,
@ -11134,6 +11157,12 @@ nsDocShell::DoURILoad(nsIURI* aURI,
if (aOriginalURI) {
channel->SetOriginalURI(aOriginalURI);
// The LOAD_REPLACE flag and its handling here will be removed as part
// of bug 1319110. For now preserve its restoration here to not break
// any code expecting it being set specially on redirected channels.
// If the flag has originally been set to change result of
// NS_GetFinalChannelURI it won't have any effect and also won't cause
// any harm.
if (aLoadReplace) {
uint32_t loadFlags;
channel->GetLoadFlags(&loadFlags);
@ -11144,6 +11173,12 @@ nsDocShell::DoURILoad(nsIURI* aURI,
channel->SetOriginalURI(aURI);
}
if (aResultPrincipalURI) {
// Unconditionally override, we want the replay to be equal to what has
// been captured.
loadInfo->SetResultPrincipalURI(aResultPrincipalURI.ref());
}
if (aTypeHint && *aTypeHint) {
channel->SetContentType(nsDependentCString(aTypeHint));
mContentTypeHint = aTypeHint;
@ -12364,6 +12399,7 @@ nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
// Get the post data & referrer
nsCOMPtr<nsIInputStream> inputStream;
nsCOMPtr<nsIURI> originalURI;
nsCOMPtr<nsIURI> resultPrincipalURI;
bool loadReplace = false;
nsCOMPtr<nsIURI> referrerURI;
uint32_t referrerPolicy = mozilla::net::RP_Unset;
@ -12411,6 +12447,8 @@ nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
triggeringPrincipal = loadInfo->TriggeringPrincipal();
}
loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
// For now keep storing just the principal in the SHEntry.
if (!principalToInherit) {
if (loadInfo->GetLoadingSandboxed()) {
@ -12443,6 +12481,7 @@ nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
mDynamicallyCreated);
entry->SetOriginalURI(originalURI);
entry->SetResultPrincipalURI(resultPrincipalURI);
entry->SetLoadReplace(loadReplace);
entry->SetReferrerURI(referrerURI);
entry->SetReferrerPolicy(referrerPolicy);
@ -12556,6 +12595,7 @@ nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
nsCOMPtr<nsIURI> uri;
nsCOMPtr<nsIURI> originalURI;
nsCOMPtr<nsIURI> resultPrincipalURI;
bool loadReplace = false;
nsCOMPtr<nsIInputStream> postData;
nsCOMPtr<nsIURI> referrerURI;
@ -12569,6 +12609,8 @@ nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
NS_ENSURE_SUCCESS(aEntry->GetURI(getter_AddRefs(uri)), NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(aEntry->GetOriginalURI(getter_AddRefs(originalURI)),
NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(aEntry->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI)),
NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(aEntry->GetLoadReplace(&loadReplace),
NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(aEntry->GetReferrerURI(getter_AddRefs(referrerURI)),
@ -12656,8 +12698,11 @@ nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
// aSourceDocShell was introduced. According to spec we should be passing
// the source browsing context that was used when the history entry was
// first created. bug 947716 has been created to address this issue.
Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI;
emplacedResultPrincipalURI.emplace(Move(resultPrincipalURI));
rv = InternalLoad(uri,
originalURI,
emplacedResultPrincipalURI,
loadReplace,
referrerURI,
referrerPolicy,
@ -14210,6 +14255,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
nsresult rv = InternalLoad(clonedURI, // New URI
nullptr, // Original URI
Nothing(), // Let the protocol handler assign it
false, // LoadReplace
referer, // Referer URI
refererPolicy, // Referer policy

View File

@ -371,6 +371,7 @@ protected:
// If aLoadReplace is true, LOAD_REPLACE flag will be set to the nsIChannel.
nsresult DoURILoad(nsIURI* aURI,
nsIURI* aOriginalURI,
mozilla::Maybe<nsCOMPtr<nsIURI>> const& aResultPrincipalURI,
bool aLoadReplace,
nsIURI* aReferrer,
bool aSendReferrer,

View File

@ -10,9 +10,61 @@
#include "nsIURI.h"
#include "nsIDocShell.h"
#include "mozilla/net/ReferrerPolicy.h"
#include "mozilla/Unused.h"
namespace mozilla {
void
GetMaybeResultPrincipalURI(nsIDocShellLoadInfo* aLoadInfo, Maybe<nsCOMPtr<nsIURI>>& aRPURI)
{
if (!aLoadInfo) {
return;
}
nsresult rv;
bool isSome;
rv = aLoadInfo->GetResultPrincipalURIIsSome(&isSome);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
aRPURI.reset();
if (!isSome) {
return;
}
nsCOMPtr<nsIURI> uri;
rv = aLoadInfo->GetResultPrincipalURI(getter_AddRefs(uri));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
aRPURI.emplace(Move(uri));
}
void
SetMaybeResultPrincipalURI(nsIDocShellLoadInfo* aLoadInfo, Maybe<nsCOMPtr<nsIURI>> const& aRPURI)
{
if (!aLoadInfo) {
return;
}
nsresult rv;
rv = aLoadInfo->SetResultPrincipalURI(aRPURI.refOr(nullptr));
Unused << NS_WARN_IF(NS_FAILED(rv));
rv = aLoadInfo->SetResultPrincipalURIIsSome(aRPURI.isSome());
Unused << NS_WARN_IF(NS_FAILED(rv));
}
} // mozilla
nsDocShellLoadInfo::nsDocShellLoadInfo()
: mLoadReplace(false)
: mResultPrincipalURIIsSome(false)
, mLoadReplace(false)
, mInheritPrincipal(false)
, mPrincipalIsExplicit(false)
, mSendReferrer(true)
@ -68,6 +120,37 @@ nsDocShellLoadInfo::SetOriginalURI(nsIURI* aOriginalURI)
return NS_OK;
}
NS_IMETHODIMP
nsDocShellLoadInfo::GetResultPrincipalURI(nsIURI** aResultPrincipalURI)
{
NS_ENSURE_ARG_POINTER(aResultPrincipalURI);
*aResultPrincipalURI = mResultPrincipalURI;
NS_IF_ADDREF(*aResultPrincipalURI);
return NS_OK;
}
NS_IMETHODIMP
nsDocShellLoadInfo::SetResultPrincipalURI(nsIURI* aResultPrincipalURI)
{
mResultPrincipalURI = aResultPrincipalURI;
return NS_OK;
}
NS_IMETHODIMP
nsDocShellLoadInfo::GetResultPrincipalURIIsSome(bool* aIsSome)
{
*aIsSome = mResultPrincipalURIIsSome;
return NS_OK;
}
NS_IMETHODIMP
nsDocShellLoadInfo::SetResultPrincipalURIIsSome(bool aIsSome)
{
mResultPrincipalURIIsSome = aIsSome;
return NS_OK;
}
NS_IMETHODIMP
nsDocShellLoadInfo::GetLoadReplace(bool* aLoadReplace)
{

View File

@ -33,7 +33,9 @@ protected:
protected:
nsCOMPtr<nsIURI> mReferrer;
nsCOMPtr<nsIURI> mOriginalURI;
nsCOMPtr<nsIURI> mResultPrincipalURI;
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
bool mResultPrincipalURIIsSome;
bool mLoadReplace;
bool mInheritPrincipal;
bool mPrincipalIsExplicit;

View File

@ -10,6 +10,7 @@
%{ C++
#include "js/TypeDecls.h"
#include "mozilla/Maybe.h"
class nsPresContext;
class nsIPresShell;
%}
@ -20,6 +21,7 @@ class nsIPresShell;
[ptr] native nsPresContext(nsPresContext);
[ptr] native nsIPresShell(nsIPresShell);
[ref] native MaybeURI(mozilla::Maybe<nsCOMPtr<nsIURI>>);
interface nsIURI;
interface nsIChannel;
@ -127,6 +129,10 @@ interface nsIDocShell : nsIDocShellTreeItem
* @param aOriginalURI - The URI to set as the originalURI on the channel
* that does the load. If null, aURI will be set as
* the originalURI.
* @param aResultPrincipalURI - The URI to be set to loadInfo.resultPrincipalURI
* When Nothing, there will be no change
* When Some, the principal URI will overwrite even
* with a null value.
* @param aLoadReplace - If set LOAD_REPLACE flag will be set on the
* channel. aOriginalURI is null, this argument is
* ignored.
@ -174,6 +180,7 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
[noscript]void internalLoad(in nsIURI aURI,
in nsIURI aOriginalURI,
[const] in MaybeURI aResultPrincipalURI,
in boolean aLoadReplace,
in nsIURI aReferrer,
in unsigned long aReferrerPolicy,

View File

@ -31,6 +31,16 @@ interface nsIDocShellLoadInfo : nsISupports
*/
attribute nsIURI originalURI;
/**
* Result principal URL from nsILoadInfo, may be null. Valid only if
* the "IsSome" part is true (has the same meaning as isSome()
* on mozilla::Maybe.)
*
* In C++ please use Get/SetMaybeResultPrincipalURI helper functions.
*/
attribute nsIURI resultPrincipalURI;
attribute boolean resultPrincipalURIIsSome;
/**
* loadReplace flag to be passed to nsIDocShell.internalLoad.
*/
@ -123,3 +133,22 @@ interface nsIDocShellLoadInfo : nsISupports
*/
attribute nsIURI baseURI;
};
%{C++
#include "mozilla/Maybe.h"
namespace mozilla {
/**
* Helper function allowing convenient work with mozilla::Maybe in C++, hiding
* resultPrincipalURI and resultPrincipalURIIsSome attributes from the consumer.
*/
void
GetMaybeResultPrincipalURI(nsIDocShellLoadInfo* aLoadInfo, Maybe<nsCOMPtr<nsIURI>>& aRPURI);
void
SetMaybeResultPrincipalURI(nsIDocShellLoadInfo* aLoadInfo, Maybe<nsCOMPtr<nsIURI>> const& aRPURI);
} // mozilla
%}

View File

@ -49,6 +49,12 @@ interface nsISHEntry : nsISupports
*/
attribute nsIURI originalURI;
/**
* URL as stored from nsILoadInfo.resultPrincipalURI. See nsILoadInfo
* for more details.
*/
attribute nsIURI resultPrincipalURI;
/**
* This flag remembers whether channel has LOAD_REPLACE set.
*/

View File

@ -137,6 +137,21 @@ nsSHEntry::SetOriginalURI(nsIURI* aOriginalURI)
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetResultPrincipalURI(nsIURI** aResultPrincipalURI)
{
*aResultPrincipalURI = mResultPrincipalURI;
NS_IF_ADDREF(*aResultPrincipalURI);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetResultPrincipalURI(nsIURI* aResultPrincipalURI)
{
mResultPrincipalURI = aResultPrincipalURI;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetLoadReplace(bool* aLoadReplace)
{

View File

@ -47,6 +47,7 @@ private:
// See nsSHEntry.idl for comments on these members.
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIURI> mOriginalURI;
nsCOMPtr<nsIURI> mResultPrincipalURI;
nsCOMPtr<nsIURI> mReferrerURI;
uint32_t mReferrerPolicy;
nsString mTitle;

View File

@ -6,7 +6,7 @@ pref(dom.animations-api.core.enabled,true) load 1216842-3.html
pref(dom.animations-api.core.enabled,true) load 1216842-4.html
pref(dom.animations-api.core.enabled,true) load 1216842-5.html
pref(dom.animations-api.core.enabled,true) load 1216842-6.html
skip-if(webrender) pref(dom.animations-api.core.enabled,true) load 1272475-1.html # see bug 1367994
pref(dom.animations-api.core.enabled,true) load 1272475-1.html
pref(dom.animations-api.core.enabled,true) load 1272475-2.html
pref(dom.animations-api.core.enabled,true) load 1278485-1.html
pref(dom.animations-api.core.enabled,true) load 1277272-1.html

View File

@ -352,7 +352,7 @@ DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time
nsLayoutUtils::GetContainingBlockForClientRect(targetFrame),
nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS
);
intersectionRect = Some(targetFrame->GetVisualOverflowRect());
intersectionRect = Some(targetFrame->GetRectRelativeToSelf());
nsIFrame* containerFrame = nsLayoutUtils::GetCrossDocParentFrame(targetFrame);
while (containerFrame && containerFrame != rootFrame) {

View File

@ -569,8 +569,14 @@ nsAttrAndChildArray::IndexOfAttr(nsIAtom* aLocalName, int32_t aNamespaceID) cons
uint32_t slotCount = AttrSlotCount();
if (aNamespaceID == kNameSpaceID_None) {
// This should be the common case so lets make an optimized loop
for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) {
// Note that here we don't check for AttrSlotIsTaken() in the loop
// condition for the sake of performance because comparing aLocalName
// against null would fail in the loop body (since Equals() just compares
// the raw pointer value of aLocalName to what AttrSlotIsTaken() would be
// checking.
for (i = 0; i < slotCount; ++i) {
if (ATTRS(mImpl)[i].mName.Equals(aLocalName)) {
MOZ_ASSERT(AttrSlotIsTaken(i), "sanity check");
return i;
}
}

View File

@ -101,6 +101,10 @@ public:
}
// Faster comparison in the case we know the namespace is null
// Note that some callers such as nsAttrAndChildArray::IndexOfAttr() will
// call this function on nsAttrName structs with 0 mBits, so no attempt
// must be made to do anything with mBits besides comparing it with the
// incoming aAtom argument.
bool Equals(nsIAtom* aAtom) const
{
return reinterpret_cast<uintptr_t>(aAtom) == mBits;

View File

@ -6049,6 +6049,10 @@ nsDocument::CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value*
bool
nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
{
if (!nsContentUtils::IsWebComponentsEnabled()) {
return false;
}
JS::Rooted<JSObject*> obj(aCx, aObject);
JSAutoCompartment ac(aCx, obj);
@ -6056,15 +6060,6 @@ nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
nsCOMPtr<nsPIDOMWindowInner> window =
do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(global));
bool enabled =
nsContentUtils::IsWebComponentsEnabled() ||
// Check for the webcomponents permission. See Bug 1181555.
IsWebComponentsEnabled(window);
if (!enabled) {
return false;
}
nsIDocument* doc = window ? window->GetExtantDoc() : nullptr;
if (doc && doc->IsStyledByServo()) {
NS_WARNING("stylo: Web Components not supported yet");
@ -6077,21 +6072,11 @@ nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
bool
nsDocument::IsWebComponentsEnabled(dom::NodeInfo* aNodeInfo)
{
nsIDocument* doc = aNodeInfo->GetDocument();
bool enabled = nsContentUtils::IsWebComponentsEnabled();
if (!enabled) {
// Use GetScopeObject() here so that data documents work the same way as the
// main document they're associated with.
nsCOMPtr<nsPIDOMWindowInner> window =
do_QueryInterface(doc->GetScopeObject());
enabled = IsWebComponentsEnabled(window);
}
if (!enabled) {
if (!nsContentUtils::IsWebComponentsEnabled()) {
return false;
}
nsIDocument* doc = aNodeInfo->GetDocument();
if (doc->IsStyledByServo()) {
NS_WARNING("stylo: Web Components not supported yet");
return false;
@ -6100,26 +6085,6 @@ nsDocument::IsWebComponentsEnabled(dom::NodeInfo* aNodeInfo)
return true;
}
bool
nsDocument::IsWebComponentsEnabled(nsPIDOMWindowInner* aWindow)
{
if (aWindow) {
nsresult rv;
nsCOMPtr<nsIPermissionManager> permMgr =
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, false);
uint32_t perm;
rv = permMgr->TestPermissionFromWindow(
aWindow, "moz-extremely-unstable-and-will-change-webcomponents", &perm);
NS_ENSURE_SUCCESS(rv, false);
return perm == nsIPermissionManager::ALLOW_ACTION;
}
return false;
}
void
nsDocument::ScheduleSVGForPresAttrEvaluation(nsSVGElement* aSVG)
{

View File

@ -1395,9 +1395,6 @@ private:
void UpdatePossiblyStaleDocumentState();
static bool CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value* aVp);
// Check whether web components are enabled for the given window.
static bool IsWebComponentsEnabled(nsPIDOMWindowInner* aWindow);
public:
virtual already_AddRefed<mozilla::dom::CustomElementRegistry>
GetCustomElementRegistry() override;

View File

@ -3446,12 +3446,27 @@ def getConditionList(idlobj, cxName, objName):
objName is the name of the object that we're working with, because some of
our test functions want that.
The return value is a pair. The first element is a possibly-empty CGList
of conditions. The second element, if not None, is a CGThing for som code
that needs to run before the list of conditions can be evaluated.
"""
conditions = []
conditionSetup = None
pref = idlobj.getExtendedAttribute("Pref")
if pref:
assert isinstance(pref, list) and len(pref) == 1
conditions.append('Preferences::GetBool("%s")' % pref[0])
conditionSetup = CGGeneric(fill(
"""
static bool sPrefValue;
static bool sPrefCacheSetUp = false;
if (!sPrefCacheSetUp) {
sPrefCacheSetUp = true;
Preferences::AddBoolVarCache(&sPrefValue, "${prefName}");
}
""",
prefName=pref[0]))
conditions.append("sPrefValue")
if idlobj.getExtendedAttribute("ChromeOnly"):
conditions.append("nsContentUtils::ThreadsafeIsSystemCaller(%s)" % cxName)
func = idlobj.getExtendedAttribute("Func")
@ -3461,7 +3476,8 @@ def getConditionList(idlobj, cxName, objName):
if idlobj.getExtendedAttribute("SecureContext"):
conditions.append("mozilla::dom::IsSecureContextOrObjectIsFromSecureContext(%s, %s)" % (cxName, objName))
return CGList((CGGeneric(cond) for cond in conditions), " &&\n")
return (CGList((CGGeneric(cond) for cond in conditions), " &&\n"),
conditionSetup)
class CGConstructorEnabled(CGAbstractMethod):
@ -3505,13 +3521,14 @@ class CGConstructorEnabled(CGAbstractMethod):
"!NS_IsMainThread()")
body.append(exposedInWorkerCheck)
conditions = getConditionList(iface, "aCx", "aObj")
(conditions, conditionsSetup) = getConditionList(iface, "aCx", "aObj")
# We should really have some conditions
assert len(body) or len(conditions)
conditionsWrapper = ""
if len(conditions):
body.append(conditionsSetup);
conditionsWrapper = CGWrapper(conditions,
pre="return ",
post=";\n",
@ -13328,7 +13345,12 @@ class CGDictionary(CGThing):
return false;
}
"""))
conditions = getConditionList(member, "cx", "*object")
(conditions, conditionsSetup) = getConditionList(member, "cx", "*object")
if conditionsSetup is not None:
raise TypeError("We don't support Pref annotations on dictionary "
"members. If we start to, we need to make sure all "
"the variable names conditionsSetup uses for a "
"given dictionary are unique.")
if len(conditions) != 0:
setTempValue = CGIfElseWrapper(conditions.define(),
setTempValue,
@ -13444,7 +13466,12 @@ class CGDictionary(CGThing):
if member.canHaveMissingValue():
# Only do the conversion if we have a value
conversion = CGIfWrapper(conversion, "%s.WasPassed()" % memberLoc)
conditions = getConditionList(member, "cx", "obj")
(conditions, conditionsSetup) = getConditionList(member, "cx", "obj")
if conditionsSetup is not None:
raise TypeError("We don't support Pref annotations on dictionary "
"members. If we start to, we need to make sure all "
"the variable names conditionsSetup uses for a "
"given dictionary are unique.")
if len(conditions) != 0:
conversion = CGIfWrapper(conversion, conditions.define())
return conversion

View File

@ -2872,8 +2872,15 @@ nsTextEditorState::UpdateOverlayTextVisibility(bool aNotify)
mPreviewVisibility = valueIsEmpty && !previewValue.IsEmpty();
mPlaceholderVisibility = valueIsEmpty && previewValue.IsEmpty();
if (mPlaceholderVisibility &&
!Preferences::GetBool("dom.placeholder.show_on_focus", true)) {
static bool sPrefCached = false;
static bool sPrefShowOnFocus = true;
if (!sPrefCached) {
sPrefCached = true;
Preferences::AddBoolVarCache(&sPrefShowOnFocus,
"dom.placeholder.show_on_focus", true);
}
if (mPlaceholderVisibility && !sPrefShowOnFocus) {
nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
mPlaceholderVisibility = !nsContentUtils::IsFocusedContent(content);
}

View File

@ -19,6 +19,7 @@ support-files =
[test_multiple_register_different_scope.html]
[test_subscription_change.html]
[test_data.html]
skip-if = os == "win" && !debug # Bug 1373346
[test_try_registering_offline_disabled.html]
[test_serviceworker_lifetime.html]
[test_error_reporting.html]

View File

@ -9,10 +9,13 @@
#include "GeckoProfiler.h" // for PROFILER_LABEL
#include "client/ClientLayerManager.h" // for ClientLayerManager, etc
#include "gfxContext.h" // for gfxContext
#include "gfx2DGlue.h"
#include "gfxRect.h" // for gfxRect
#include "gfxPrefs.h" // for gfxPrefs
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/gfx/2D.h" // for DrawTarget
#include "mozilla/gfx/DrawEventRecorder.h"
#include "mozilla/gfx/InlineTranslator.h"
#include "mozilla/gfx/Matrix.h" // for Matrix
#include "mozilla/gfx/Rect.h" // for Rect, IntRect
#include "mozilla/gfx/Types.h" // for Float, etc
@ -21,7 +24,7 @@
#include "nsCOMPtr.h" // for already_AddRefed
#include "nsISupportsImpl.h" // for Layer::AddRef, etc
#include "nsRect.h" // for mozilla::gfx::IntRect
#include "gfx2DGlue.h"
#include "PaintThread.h"
#include "ReadbackProcessor.h"
namespace mozilla {
@ -29,45 +32,102 @@ namespace layers {
using namespace mozilla::gfx;
void
ClientPaintedLayer::PaintThebes(nsTArray<ReadbackProcessor::Update>* aReadbackUpdates)
bool
ClientPaintedLayer::EnsureContentClient()
{
PROFILER_LABEL("ClientPaintedLayer", "PaintThebes",
js::ProfileEntry::Category::GRAPHICS);
if (!mContentClient) {
mContentClient = ContentClient::CreateContentClient(
ClientManager()->AsShadowForwarder());
NS_ASSERTION(ClientManager()->InDrawing(),
"Can only draw in drawing phase");
mContentClient->BeginPaint();
uint32_t flags = RotatedContentBuffer::PAINT_CAN_DRAW_ROTATED;
#ifndef MOZ_IGNORE_PAINT_WILL_RESAMPLE
if (ClientManager()->CompositorMightResample()) {
flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE;
}
if (!(flags & RotatedContentBuffer::PAINT_WILL_RESAMPLE)) {
if (MayResample()) {
flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE;
if (!mContentClient) {
return false;
}
}
#endif
PaintState state =
mContentClient->BeginPaintBuffer(this, flags);
SubtractFromValidRegion(state.mRegionToInvalidate);
if (!state.mRegionToDraw.IsEmpty() && !ClientManager()->GetPaintedLayerCallback()) {
mContentClient->Connect();
ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
MOZ_ASSERT(mContentClient->GetForwarder());
}
return true;
}
bool
ClientPaintedLayer::CanRecordLayer(ReadbackProcessor* aReadback)
{
// If we don't have a paint thread, this is either not the content
// process or the pref is disabled.
if (!PaintThread::Get()) {
return false;
}
// Not supported yet
if (aReadback && UsedForReadback()) {
return false;
}
// If we have mask layers, we have to render those first
// In this case, don't record for now.
if (GetMaskLayer()) {
return false;
}
return GetAncestorMaskLayerCount() == 0;
}
void
ClientPaintedLayer::UpdateContentClient(PaintState& aState)
{
Mutated();
AddToValidRegion(aState.mRegionToDraw);
ContentClientRemote *contentClientRemote =
static_cast<ContentClientRemote *>(mContentClient.get());
MOZ_ASSERT(contentClientRemote->GetIPCHandle());
// Hold(this) ensures this layer is kept alive through the current transaction
// The ContentClient assumes this layer is kept alive (e.g., in CreateBuffer),
// so deleting this Hold for whatever reason will break things.
ClientManager()->Hold(this);
contentClientRemote->Updated(aState.mRegionToDraw,
mVisibleRegion.ToUnknownRegion(),
aState.mDidSelfCopy);
}
bool
ClientPaintedLayer::UpdatePaintRegion(PaintState& aState)
{
SubtractFromValidRegion(aState.mRegionToInvalidate);
if (!aState.mRegionToDraw.IsEmpty() && !ClientManager()->GetPaintedLayerCallback()) {
ClientManager()->SetTransactionIncomplete();
mContentClient->EndPaint(nullptr);
return false;
}
// The area that became invalid and is visible needs to be repainted
// (this could be the whole visible area if our buffer switched
// from RGB to RGBA, because we might need to repaint with
// subpixel AA)
aState.mRegionToInvalidate.And(aState.mRegionToInvalidate,
GetLocalVisibleRegion().ToUnknownRegion());
return true;
}
void
ClientPaintedLayer::ReplayPaintedLayer(DrawEventRecorderMemory* aRecorder)
{
LayerIntRegion visibleRegion = GetVisibleRegion();
mContentClient->BeginPaint();
uint32_t flags = GetPaintFlags();
PaintState state =
mContentClient->BeginPaintBuffer(this, flags);
if (!UpdatePaintRegion(state)) {
return;
}
// The area that became invalid and is visible needs to be repainted
// (this could be the whole visible area if our buffer switched
// from RGB to RGBA, because we might need to repaint with
// subpixel AA)
state.mRegionToInvalidate.And(state.mRegionToInvalidate,
GetLocalVisibleRegion().ToUnknownRegion());
bool didUpdate = false;
RotatedContentBuffer::DrawIterator iter;
while (DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(state, &iter)) {
@ -77,7 +137,77 @@ ClientPaintedLayer::PaintThebes(nsTArray<ReadbackProcessor::Update>* aReadbackUp
}
continue;
}
SetAntialiasingFlags(this, target);
// Draw all the things into the actual content client
// This shouldn't exist in the future. For now, its just testing
// to make sure we properly record and can replay all the draw
// commands
std::istream& stream = aRecorder->GetInputStream();
InlineTranslator translator(target, nullptr);
translator.TranslateRecording(stream);
mContentClient->ReturnDrawTargetToBuffer(target);
didUpdate = true;
}
// ending paint w/o any readback updates
// TODO: Fix me
mContentClient->EndPaint(nullptr);
if (didUpdate) {
UpdateContentClient(state);
}
}
uint32_t
ClientPaintedLayer::GetPaintFlags()
{
uint32_t flags = RotatedContentBuffer::PAINT_CAN_DRAW_ROTATED;
#ifndef MOZ_IGNORE_PAINT_WILL_RESAMPLE
if (ClientManager()->CompositorMightResample()) {
flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE;
}
if (!(flags & RotatedContentBuffer::PAINT_WILL_RESAMPLE)) {
if (MayResample()) {
flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE;
}
}
#endif
return flags;
}
void
ClientPaintedLayer::PaintThebes(nsTArray<ReadbackProcessor::Update>* aReadbackUpdates)
{
PROFILER_LABEL("ClientPaintedLayer", "PaintThebes",
js::ProfileEntry::Category::GRAPHICS);
NS_ASSERTION(ClientManager()->InDrawing(),
"Can only draw in drawing phase");
mContentClient->BeginPaint();
uint32_t flags = GetPaintFlags();
PaintState state =
mContentClient->BeginPaintBuffer(this, flags);
if (!UpdatePaintRegion(state)) {
return;
}
bool didUpdate = false;
RotatedContentBuffer::DrawIterator iter;
while (DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(state, &iter)) {
if (!target || !target->IsValid()) {
if (target) {
mContentClient->ReturnDrawTargetToBuffer(target);
}
continue;
}
SetAntialiasingFlags(this, target);
RefPtr<gfxContext> ctx = gfxContext::CreatePreservingTransformOrNull(target);
@ -99,36 +229,89 @@ ClientPaintedLayer::PaintThebes(nsTArray<ReadbackProcessor::Update>* aReadbackUp
mContentClient->EndPaint(aReadbackUpdates);
if (didUpdate) {
Mutated();
AddToValidRegion(state.mRegionToDraw);
ContentClientRemote* contentClientRemote = static_cast<ContentClientRemote*>(mContentClient.get());
MOZ_ASSERT(contentClientRemote->GetIPCHandle());
// Hold(this) ensures this layer is kept alive through the current transaction
// The ContentClient assumes this layer is kept alive (e.g., in CreateBuffer),
// so deleting this Hold for whatever reason will break things.
ClientManager()->Hold(this);
contentClientRemote->Updated(state.mRegionToDraw,
mVisibleRegion.ToUnknownRegion(),
state.mDidSelfCopy);
UpdateContentClient(state);
}
}
already_AddRefed<DrawEventRecorderMemory>
ClientPaintedLayer::RecordPaintedLayer()
{
LayerIntRegion visibleRegion = GetVisibleRegion();
LayerIntRect bounds = visibleRegion.GetBounds();
LayerIntSize size = bounds.Size();
if (visibleRegion.IsEmpty()) {
if (gfxPrefs::LayersDump()) {
printf_stderr("PaintedLayer %p skipping\n", this);
}
return nullptr;
}
nsIntRegion regionToPaint;
regionToPaint.Sub(mVisibleRegion.ToUnknownRegion(), GetValidRegion());
if (regionToPaint.IsEmpty()) {
// Do we ever have to do anything if the region to paint is empty
// but we have a painted layer callback?
return nullptr;
}
if (!ClientManager()->GetPaintedLayerCallback()) {
ClientManager()->SetTransactionIncomplete();
return nullptr;
}
// I know this is slow and we should probably use DrawTargetCapture
// But for now, the recording draw target / replay should actually work
// Replay for WR happens in Moz2DIMageRenderer
IntSize imageSize(size.ToUnknownSize());
// DrawTargetRecording also plays back the commands while
// recording, hence the dummy DT. DummyDT will actually have
// the drawn painted layer.
RefPtr<DrawEventRecorderMemory> recorder =
MakeAndAddRef<DrawEventRecorderMemory>();
RefPtr<DrawTarget> dummyDt =
Factory::CreateDrawTarget(gfx::BackendType::SKIA, imageSize, gfx::SurfaceFormat::B8G8R8A8);
RefPtr<DrawTarget> dt =
Factory::CreateRecordingDrawTarget(recorder, dummyDt, imageSize);
dt->ClearRect(Rect(0, 0, imageSize.width, imageSize.height));
dt->SetTransform(Matrix().PreTranslate(-bounds.x, -bounds.y));
RefPtr<gfxContext> ctx = gfxContext::CreatePreservingTransformOrNull(dt);
MOZ_ASSERT(ctx); // already checked the target above
ClientManager()->GetPaintedLayerCallback()(this,
ctx,
visibleRegion.ToUnknownRegion(),
visibleRegion.ToUnknownRegion(),
DrawRegionClip::DRAW,
nsIntRegion(),
ClientManager()->GetPaintedLayerCallbackData());
return recorder.forget();
}
void
ClientPaintedLayer::RenderLayerWithReadback(ReadbackProcessor *aReadback)
{
RenderMaskLayers(this);
if (!mContentClient) {
mContentClient = ContentClient::CreateContentClient(ClientManager()->AsShadowForwarder());
if (!mContentClient) {
if (CanRecordLayer(aReadback)) {
RefPtr<DrawEventRecorderMemory> recorder = RecordPaintedLayer();
if (recorder) {
if (!EnsureContentClient()) {
return;
}
ReplayPaintedLayer(recorder);
return;
}
mContentClient->Connect();
ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
MOZ_ASSERT(mContentClient->GetForwarder());
}
if (!EnsureContentClient()) {
return;
}
nsTArray<ReadbackProcessor::Update> readbackUpdates;

View File

@ -19,8 +19,11 @@
#include "mozilla/layers/PLayerTransaction.h" // for PaintedLayerAttributes
namespace mozilla {
namespace layers {
namespace gfx {
class DrawEventRecorderMemory;
};
namespace layers {
class CompositableClient;
class ShadowableLayer;
class SpecificLayerAttributes;
@ -109,6 +112,15 @@ public:
protected:
void PaintThebes(nsTArray<ReadbackProcessor::Update>* aReadbackUpdates);
void RecordThebes();
bool CanRecordLayer(ReadbackProcessor* aReadback);
bool HasMaskLayers();
already_AddRefed<gfx::DrawEventRecorderMemory> RecordPaintedLayer();
void ReplayPaintedLayer(DrawEventRecorderMemory* aRecorder);
bool EnsureContentClient();
uint32_t GetPaintFlags();
void UpdateContentClient(PaintState& aState);
bool UpdatePaintRegion(PaintState& aState);
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;

View File

@ -36,7 +36,7 @@
#include <vector>
#include "GeckoProfiler.h" // for GeckoProfiler
#ifdef MOZ_GECKO_PROFILER
#include "ProfilerMarkerPayload.h" // for LayerTranslationPayload
#include "ProfilerMarkerPayload.h" // for LayerTranslationMarkerPayload
#endif
#define CULLING_LOG(...)
@ -102,7 +102,7 @@ PrintUniformityInfo(Layer* aLayer)
Point translation = transform.As2D().GetTranslation();
PROFILER_MARKER_PAYLOAD(
"LayerTranslation",
MakeUnique<LayerTranslationPayload>(aLayer, translation));
MakeUnique<LayerTranslationMarkerPayload>(aLayer, translation));
#endif
}

View File

@ -1765,7 +1765,7 @@ InsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp)
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
PROFILER_MARKER_PAYLOAD(
"VsyncTimestamp",
MakeUnique<VsyncPayload>(aVsyncTimestamp));
MakeUnique<VsyncMarkerPayload>(aVsyncTimestamp));
#endif
}

View File

@ -39,7 +39,7 @@ AnimationState::UpdateState(bool aAnimationFinished,
DefaultSurfaceFlags(),
PlaybackType::eAnimated));
return UpdateStateInternal(result, aAnimationFinished, aSize);
return UpdateStateInternal(result, aAnimationFinished, aSize, aAllowInvalidation);
}
const gfx::IntRect

View File

@ -182,11 +182,13 @@ MessageLoop::MessageLoop(Type type, nsIThread* aThread)
#endif // OS_WIN
transient_hang_timeout_(0),
permanent_hang_timeout_(0),
next_sequence_num_(0),
mEventTarget(new EventTarget(this)) {
next_sequence_num_(0) {
DCHECK(!current()) << "should only have one message loop per thread";
get_tls_ptr().Set(this);
// Must initialize after current() is initialized.
mEventTarget = new EventTarget(this);
switch (type_) {
case TYPE_MOZILLA_PARENT:
MOZ_RELEASE_ASSERT(!aThread);

View File

@ -23,6 +23,7 @@
#include "nsString.h"
#include "nsTArray.h"
#include "mozilla/nsRedirectHistoryEntry.h"
#include "URIUtils.h"
namespace mozilla {
namespace net {
@ -346,6 +347,13 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
sandboxedLoadingPrincipalInfo = sandboxedLoadingPrincipalInfoTemp;
}
OptionalURIParams optionalResultPrincipalURI = mozilla::void_t();
nsCOMPtr<nsIURI> resultPrincipalURI;
Unused << aLoadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
if (resultPrincipalURI) {
SerializeURI(resultPrincipalURI, optionalResultPrincipalURI);
}
nsTArray<RedirectHistoryEntryInfo> redirectChainIncludingInternalRedirects;
for (const nsCOMPtr<nsIRedirectHistoryEntry>& redirectEntry :
aLoadInfo->RedirectChainIncludingInternalRedirects()) {
@ -368,6 +376,7 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
triggeringPrincipalInfo,
principalToInheritInfo,
sandboxedLoadingPrincipalInfo,
optionalResultPrincipalURI,
aLoadInfo->GetSecurityFlags(),
aLoadInfo->InternalContentPolicyType(),
static_cast<uint32_t>(aLoadInfo->GetTainting()),
@ -434,6 +443,12 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs,
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr<nsIURI> resultPrincipalURI;
if (loadInfoArgs.resultPrincipalURI().type() != OptionalURIParams::Tvoid_t) {
resultPrincipalURI = DeserializeURI(loadInfoArgs.resultPrincipalURI());
NS_ENSURE_TRUE(resultPrincipalURI, NS_ERROR_UNEXPECTED);
}
RedirectHistoryArray redirectChainIncludingInternalRedirects;
for (const RedirectHistoryEntryInfo& entryInfo :
loadInfoArgs.redirectChainIncludingInternalRedirects()) {
@ -456,6 +471,7 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs,
triggeringPrincipal,
principalToInherit,
sandboxedLoadingPrincipal,
resultPrincipalURI,
loadInfoArgs.securityFlags(),
loadInfoArgs.contentPolicyType(),
static_cast<LoadTainting>(loadInfoArgs.tainting()),

View File

@ -248,6 +248,7 @@ def main(argv):
options.exclude += ['debug/bug1160182.js']
options.exclude += ['xdr/incremental-encoder.js']
options.exclude += ['xdr/bug1186973.js'] # Bug 1369785
options.exclude += ['xdr/relazify.js']
options.exclude += ['basic/werror.js']
# Prevent code coverage test that expects coverage

View File

@ -0,0 +1,10 @@
// JS shell shutdown ordering
// Avoid crashing with --no-threads
if (helperThreadCount() == 0)
quit();
evalInWorker(`
var lfGlobal = newGlobal();
lfGlobal.offThreadCompileScript(\`{ let x; throw 42; }\`);
`);

View File

@ -1496,8 +1496,12 @@ IonBuilder::visitBlock(const CFGBlock* cfgblock, MBasicBlock* mblock)
mblock->setHitCount(script()->getHitCount(mblock->pc()));
// Optimization to move a predecessor that only has this block as successor
// just before this block.
if (mblock->numPredecessors() == 1 && mblock->getPredecessor(0)->numSuccessors() == 1) {
// just before this block. Skip this optimization if the previous block is
// not part of the same function, as we might have to backtrack on inlining
// failures.
if (mblock->numPredecessors() == 1 && mblock->getPredecessor(0)->numSuccessors() == 1 &&
!mblock->getPredecessor(0)->outerResumePoint())
{
graph().removeBlockFromList(mblock->getPredecessor(0));
graph().addBlock(mblock->getPredecessor(0));
}

View File

@ -76,7 +76,7 @@ DefaultJitOptions::DefaultJitOptions()
SET_DEFAULT(checkRangeAnalysis, false);
// Toggles whether IonBuilder fallbacks to a call if we fail to inline.
SET_DEFAULT(disableInlineBacktracking, true);
SET_DEFAULT(disableInlineBacktracking, false);
// Toggles whether Alignment Mask Analysis is globally disabled.
SET_DEFAULT(disableAma, false);

View File

@ -403,14 +403,6 @@ AS_BIN=$AS
AR_EXTRACT='$(AR) x'
AS='$(CC)'
AS_DASH_C_FLAG='-c'
DLL_PREFIX=lib
LIB_PREFIX=lib
RUST_LIB_PREFIX=lib
DLL_SUFFIX=.so
OBJ_SUFFIX=o
LIB_SUFFIX=a
RUST_LIB_SUFFIX=a
IMPORT_LIB_SUFFIX=
DIRENT_INO=d_ino
MOZ_USER_DIR=".mozilla"
@ -561,7 +553,6 @@ case "$target" in
MOZ_OPTIMIZE_FLAGS="-O3 -fno-stack-protector"
CFLAGS="$CFLAGS -fno-common"
CXXFLAGS="$CXXFLAGS -fno-common -stdlib=libc++"
DLL_SUFFIX=".dylib"
DSO_LDOPTS=''
STRIP="$STRIP -x -S"
LDFLAGS="$LDFLAGS -lobjc"
@ -633,7 +624,6 @@ case "$target" in
*-mingw*)
DSO_CFLAGS=
DSO_PIC_CFLAGS=
DLL_SUFFIX=.dll
RC=rc.exe
if test -n "$GNU_CC" -o -n "$CLANG_CC"; then
CC="$CC -mwindows"
@ -652,8 +642,6 @@ case "$target" in
# mingw doesn't require kernel32, user32, and advapi32 explicitly
LIBS="$LIBS -lgdi32 -lwinmm -lwsock32"
MOZ_FIX_LINK_PATHS=
DLL_PREFIX=
IMPORT_LIB_SUFFIX=a
WIN32_CONSOLE_EXE_LDFLAGS=-mconsole
WIN32_GUI_EXE_LDFLAGS=-mwindows
@ -670,13 +658,6 @@ case "$target" in
RANLIB='echo not_ranlib'
STRIP='echo not_strip'
PKG_SKIP_STRIP=1
OBJ_SUFFIX=obj
LIB_SUFFIX=lib
RUST_LIB_SUFFIX=lib
DLL_PREFIX=
LIB_PREFIX=
RUST_LIB_PREFIX=
IMPORT_LIB_SUFFIX=lib
MKSHLIB='$(LINK) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
MKCSHLIB='$(LINK) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
WIN32_SUBSYSTEM_VERSION=6.01
@ -849,13 +830,11 @@ case "$target" in
CFLAGS="$CFLAGS -Dunix"
CXXFLAGS="$CXXFLAGS -Dunix"
if $CC -E - -dM </dev/null | grep __ELF__ >/dev/null; then
DLL_SUFFIX=".so"
DSO_PIC_CFLAGS='-fPIC -DPIC'
DSO_LDOPTS='-shared'
BIN_FLAGS='-Wl,--export-dynamic'
else
DSO_PIC_CFLAGS='-fPIC -DPIC'
DLL_SUFFIX=".so.1.0"
DSO_LDOPTS='-shared'
fi
# This will fail on a.out systems prior to 1.5.1_ALPHA.
@ -867,7 +846,6 @@ case "$target" in
;;
*-openbsd*)
DLL_SUFFIX=".so.1.0"
DSO_CFLAGS=''
DSO_PIC_CFLAGS='-fPIC'
DSO_LDOPTS='-shared -fPIC'
@ -2102,16 +2080,7 @@ AC_SUBST(MKCSHLIB)
AC_SUBST(DSO_CFLAGS)
AC_SUBST(DSO_PIC_CFLAGS)
AC_SUBST(DSO_LDOPTS)
AC_SUBST(LIB_PREFIX)
AC_SUBST(RUST_LIB_PREFIX)
AC_SUBST(DLL_PREFIX)
AC_SUBST(DLL_SUFFIX)
AC_DEFINE_UNQUOTED(MOZ_DLL_SUFFIX, "$DLL_SUFFIX")
AC_SUBST(LIB_SUFFIX)
AC_SUBST(RUST_LIB_SUFFIX)
AC_SUBST(OBJ_SUFFIX)
AC_SUBST(BIN_SUFFIX)
AC_SUBST(IMPORT_LIB_SUFFIX)
AC_SUBST(USE_N32)
AC_SUBST(CC_VERSION)
AC_SUBST(MOZ_LINKER)

View File

@ -3360,19 +3360,7 @@ WorkerMain(void* arg)
WorkerInput* input = (WorkerInput*) arg;
MOZ_ASSERT(!!input->parentRuntime != !!input->siblingContext);
JSContext* cx = nullptr;
auto guard = mozilla::MakeScopeExit([&] {
if (cx)
JS_DestroyContext(cx);
if (input->siblingContext) {
cooperationState->numThreads--;
CooperativeYield();
}
js_delete(input);
});
cx = input->parentRuntime
JSContext* cx = input->parentRuntime
? JS_NewContext(8L * 1024L * 1024L, 2L * 1024L * 1024L, input->parentRuntime)
: JS_NewCooperativeContext(input->siblingContext);
if (!cx)
@ -3382,6 +3370,16 @@ WorkerMain(void* arg)
if (!sc)
return;
auto guard = mozilla::MakeScopeExit([&] {
if (cx)
JS_DestroyContext(cx);
if (input->siblingContext) {
cooperationState->numThreads--;
CooperativeYield();
}
js_delete(input);
});
if (input->parentRuntime)
sc->isWorker = true;
JS_SetContextPrivate(cx, sc.get());

View File

@ -920,8 +920,8 @@ nsJARChannel::OnDownloadComplete(MemoryDownloader* aDownloader,
uint32_t loadFlags;
channel->GetLoadFlags(&loadFlags);
if (loadFlags & LOAD_REPLACE) {
mLoadFlags |= LOAD_REPLACE;
// Update our URI to reflect any redirects that happen during
// the HTTP request.
if (!mOriginalURI) {
SetOriginalURI(mJarURI);
}
@ -943,6 +943,9 @@ nsJARChannel::OnDownloadComplete(MemoryDownloader* aDownloader,
}
if (NS_SUCCEEDED(status) && channel) {
// In case the load info object has changed during a redirect,
// grab it from the target channel.
channel->GetLoadInfo(getter_AddRefs(mLoadInfo));
// Grab the security info from our base channel
channel->GetSecurityInfo(getter_AddRefs(mSecurityInfo));

View File

@ -934,6 +934,9 @@ pref("accessibility.AOM.enabled", false);
// See bug 781791.
pref("accessibility.delay_plugins", false);
pref("accessibility.delay_plugin_time", 10000);
// The COM handler used for Windows e10s performance and live regions
pref("accessibility.handler.enabled", true);
#endif
pref("focusmanager.testmode", false);

View File

@ -131,6 +131,74 @@ include('build/moz.configure/headers.configure',
include('build/moz.configure/warnings.configure',
when='--enable-compile-environment')
option(env='SO_VERSION', nargs=1, help='Shared library version for OpenBSD systems')
@depends(target, target_is_windows, target_is_darwin, building_with_gcc, 'SO_VERSION')
def library_name_info(target, is_windows, is_darwin, building_with_gcc, so_version):
dll_prefix = 'lib'
dll_suffix = '.so'
lib_prefix = 'lib'
lib_suffix = 'a'
rust_lib_prefix = 'lib'
rust_lib_suffix = 'a'
obj_suffix = 'o'
import_lib_suffix = ''
if is_windows:
dll_prefix = ''
dll_suffix = '.dll'
rust_lib_prefix = ''
rust_lib_suffix = 'lib'
# It's OK if we're doing an artifact build and building_with_gcc is
# inaccurate. Artifact builds with mingw ought to be pretty rare anyway.
if building_with_gcc:
import_lib_suffix = 'a'
else:
import_lib_suffix = 'lib'
lib_prefix = ''
lib_suffix = 'lib'
obj_suffix = 'obj'
elif is_darwin:
dll_suffix = '.dylib'
elif target.kernel == 'OpenBSD':
if so_version:
dll_suffix = '.so.%s' % so_version
else:
dll_suffix = '.so.1.0'
assert dll_suffix[0] == '.'
assert obj_suffix[0] != '.'
assert lib_suffix[0] != '.'
assert rust_lib_suffix[0] != '.'
return namespace(
dll_prefix=dll_prefix,
dll_suffix=dll_suffix,
lib_prefix=lib_prefix,
lib_suffix=lib_suffix,
rust_lib_prefix=rust_lib_prefix,
rust_lib_suffix=rust_lib_suffix,
obj_suffix=obj_suffix,
import_lib_suffix=import_lib_suffix,
)
set_config('DLL_PREFIX', library_name_info.dll_prefix)
set_config('DLL_SUFFIX', library_name_info.dll_suffix)
set_config('LIB_PREFIX', library_name_info.lib_prefix)
set_config('LIB_SUFFIX', library_name_info.lib_suffix)
set_config('RUST_LIB_PREFIX', library_name_info.rust_lib_prefix)
set_config('RUST_LIB_SUFFIX', library_name_info.rust_lib_suffix)
set_config('OBJ_SUFFIX', library_name_info.obj_suffix)
# Lots of compilation tests depend on this variable being present.
add_old_configure_assignment('OBJ_SUFFIX', library_name_info.obj_suffix)
set_config('IMPORT_LIB_SUFFIX', library_name_info.import_lib_suffix)
set_define('MOZ_DLL_SUFFIX', depends(library_name_info)(lambda lni: '"%s"' % lni.dll_suffix))
include(include_project_configure)
@depends('--help')

View File

@ -274,6 +274,7 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
, mTriggeringPrincipal(rhs.mTriggeringPrincipal)
, mPrincipalToInherit(rhs.mPrincipalToInherit)
, mSandboxedLoadingPrincipal(rhs.mSandboxedLoadingPrincipal)
, mResultPrincipalURI(rhs.mResultPrincipalURI)
, mLoadingContext(rhs.mLoadingContext)
, mSecurityFlags(rhs.mSecurityFlags)
, mInternalContentPolicyType(rhs.mInternalContentPolicyType)
@ -307,6 +308,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
nsIPrincipal* aTriggeringPrincipal,
nsIPrincipal* aPrincipalToInherit,
nsIPrincipal* aSandboxedLoadingPrincipal,
nsIURI* aResultPrincipalURI,
nsSecurityFlags aSecurityFlags,
nsContentPolicyType aContentPolicyType,
LoadTainting aTainting,
@ -334,6 +336,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
: mLoadingPrincipal(aLoadingPrincipal)
, mTriggeringPrincipal(aTriggeringPrincipal)
, mPrincipalToInherit(aPrincipalToInherit)
, mResultPrincipalURI(aResultPrincipalURI)
, mSecurityFlags(aSecurityFlags)
, mInternalContentPolicyType(aContentPolicyType)
, mTainting(aTainting)
@ -1009,5 +1012,19 @@ LoadInfo::GetIsTopLevelLoad(bool *aResult)
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::GetResultPrincipalURI(nsIURI **aURI)
{
NS_IF_ADDREF(*aURI = mResultPrincipalURI);
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::SetResultPrincipalURI(nsIURI *aURI)
{
mResultPrincipalURI = aURI;
return NS_OK;
}
} // namespace net
} // namespace mozilla

View File

@ -94,6 +94,7 @@ private:
nsIPrincipal* aTriggeringPrincipal,
nsIPrincipal* aPrincipalToInherit,
nsIPrincipal* aSandboxedLoadingPrincipal,
nsIURI* aResultPrincipalURI,
nsSecurityFlags aSecurityFlags,
nsContentPolicyType aContentPolicyType,
LoadTainting aTainting,
@ -143,6 +144,7 @@ private:
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
nsCOMPtr<nsIPrincipal> mPrincipalToInherit;
nsCOMPtr<nsIPrincipal> mSandboxedLoadingPrincipal;
nsCOMPtr<nsIURI> mResultPrincipalURI;
nsWeakPtr mLoadingContext;
nsSecurityFlags mSecurityFlags;
nsContentPolicyType mInternalContentPolicyType;

View File

@ -325,6 +325,17 @@ nsFileStreamBase::DoOpen()
PRFileDesc* fd;
nsresult rv;
if (mOpenParams.ioFlags & PR_CREATE_FILE) {
nsCOMPtr<nsIFile> parent;
mOpenParams.localFile->GetParent(getter_AddRefs(parent));
// Result doesn't need to be checked. If the file's parent path does not
// exist, make it. If it does exist, do nothing.
if (parent) {
Unused << parent->Create(nsIFile::DIRECTORY_TYPE, 0644);
}
}
#ifdef XP_WIN
if (mBehaviorFlags & nsIFileInputStream::SHARE_DELETE) {
nsCOMPtr<nsILocalFileWin> file = do_QueryInterface(mOpenParams.localFile);

View File

@ -11,6 +11,7 @@ interface nsIDOMDocument;
interface nsINode;
interface nsIPrincipal;
interface nsIRedirectHistoryEntry;
interface nsIURI;
%{C++
#include "nsTArray.h"
#include "mozilla/BasePrincipal.h"
@ -752,6 +753,14 @@ interface nsILoadInfo : nsISupports
*/
[infallible] readonly attribute boolean isTopLevelLoad;
/**
* If this is non-null, this property represents two things: (1) the
* URI to be used for the principal if the channel with this loadinfo
* gets a principal based on URI and (2) the URI to use for a document
* created from the channel with this loadinfo.
*/
attribute nsIURI resultPrincipalURI;
/**
* Returns the null principal of the resulting resource if the SEC_SANDBOXED
* flag is set. Otherwise returns null. This is used by

View File

@ -184,11 +184,17 @@ NS_NewChannelInternal(nsIChannel **outChannel,
NS_ENSURE_SUCCESS(rv, rv);
}
#ifdef DEBUG
nsLoadFlags channelLoadFlags = 0;
channel->GetLoadFlags(&channelLoadFlags);
// Will be removed when we remove LOAD_REPLACE altogether
// This check is trying to catch protocol handlers that still
// try to set the LOAD_REPLACE flag.
MOZ_DIAGNOSTIC_ASSERT(!(channelLoadFlags & nsIChannel::LOAD_REPLACE));
#endif
if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
// Retain the LOAD_REPLACE load flag if set.
nsLoadFlags normalLoadFlags = 0;
channel->GetLoadFlags(&normalLoadFlags);
rv = channel->SetLoadFlags(aLoadFlags | (normalLoadFlags & nsIChannel::LOAD_REPLACE));
rv = channel->SetLoadFlags(aLoadFlags);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -263,11 +269,17 @@ NS_NewChannelInternal(nsIChannel **outChannel,
NS_ENSURE_SUCCESS(rv, rv);
}
#ifdef DEBUG
nsLoadFlags channelLoadFlags = 0;
channel->GetLoadFlags(&channelLoadFlags);
// Will be removed when we remove LOAD_REPLACE altogether
// This check is trying to catch protocol handlers that still
// try to set the LOAD_REPLACE flag.
MOZ_DIAGNOSTIC_ASSERT(!(channelLoadFlags & nsIChannel::LOAD_REPLACE));
#endif
if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
// Retain the LOAD_REPLACE load flag if set.
nsLoadFlags normalLoadFlags = 0;
channel->GetLoadFlags(&normalLoadFlags);
rv = channel->SetLoadFlags(aLoadFlags | (normalLoadFlags & nsIChannel::LOAD_REPLACE));
rv = channel->SetLoadFlags(aLoadFlags);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -1886,12 +1898,15 @@ nsresult
NS_GetFinalChannelURI(nsIChannel *channel, nsIURI **uri)
{
*uri = nullptr;
nsLoadFlags loadFlags = 0;
nsresult rv = channel->GetLoadFlags(&loadFlags);
NS_ENSURE_SUCCESS(rv, rv);
if (loadFlags & nsIChannel::LOAD_REPLACE) {
return channel->GetURI(uri);
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
if (loadInfo) {
nsCOMPtr<nsIURI> resultPrincipalURI;
loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
if (resultPrincipalURI) {
resultPrincipalURI.forget(uri);
return NS_OK;
}
}
return channel->GetOriginalURI(uri);

View File

@ -781,11 +781,10 @@ nsresult NS_URIChainHasFlags(nsIURI *uri,
already_AddRefed<nsIURI> NS_GetInnermostURI(nsIURI *aURI);
/**
* Get the "final" URI for a channel. This is either the same as GetURI or
* GetOriginalURI, depending on whether this channel has
* nsIChanel::LOAD_REPLACE set. For channels without that flag set, the final
* URI is the original URI, while for ones with the flag the final URI is the
* channel URI.
* Get the "final" URI for a channel. This is either channel's load info
* resultPrincipalURI, if set, or GetOriginalURI. In most cases (but not all) load
* info resultPrincipalURI, if set, corresponds to URI of the channel if it's required
* to represent the actual principal for the channel.
*/
nsresult NS_GetFinalChannelURI(nsIChannel *channel, nsIURI **uri);

View File

@ -41,6 +41,7 @@ struct LoadInfoArgs
PrincipalInfo triggeringPrincipalInfo;
OptionalPrincipalInfo principalToInheritInfo;
OptionalPrincipalInfo sandboxedLoadingPrincipalInfo;
OptionalURIParams resultPrincipalURI;
uint32_t securityFlags;
uint32_t contentPolicyType;
uint32_t tainting;

View File

@ -251,7 +251,20 @@ nsFileUploadContentStream::OnCopyComplete()
//-----------------------------------------------------------------------------
nsFileChannel::nsFileChannel(nsIURI *uri)
: mFileURI(uri)
{
}
nsresult
nsFileChannel::Init()
{
NS_ENSURE_STATE(mLoadInfo);
nsresult rv;
rv = nsBaseChannel::Init();
NS_ENSURE_SUCCESS(rv, rv);
// If we have a link file, we should resolve its target right away.
// This is to protect against a same origin attack where the same link file
// can point to different resources right after the first resource is loaded.
@ -264,24 +277,24 @@ nsFileChannel::nsFileChannel(nsIURI *uri)
#endif
nsCOMPtr<nsIFile> resolvedFile;
bool symLink;
nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(uri);
if (fileURL &&
nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mFileURI);
if (fileURL &&
NS_SUCCEEDED(fileURL->GetFile(getter_AddRefs(file))) &&
NS_SUCCEEDED(file->IsSymlink(&symLink)) &&
NS_SUCCEEDED(file->IsSymlink(&symLink)) &&
symLink &&
#ifdef XP_WIN
NS_SUCCEEDED(file->GetTarget(fileTarget)) &&
NS_SUCCEEDED(NS_NewLocalFile(fileTarget, PR_TRUE,
NS_SUCCEEDED(NS_NewLocalFile(fileTarget, true,
getter_AddRefs(resolvedFile))) &&
#else
NS_SUCCEEDED(file->GetNativeTarget(fileTarget)) &&
NS_SUCCEEDED(NS_NewNativeLocalFile(fileTarget, PR_TRUE,
NS_SUCCEEDED(NS_NewNativeLocalFile(fileTarget, true,
getter_AddRefs(resolvedFile))) &&
#endif
NS_SUCCEEDED(NS_NewFileURI(getter_AddRefs(targetURI),
resolvedFile, nullptr))) {
NS_SUCCEEDED(NS_NewFileURI(getter_AddRefs(targetURI),
resolvedFile, nullptr))) {
// Make an effort to match up the query strings.
nsCOMPtr<nsIURL> origURL = do_QueryInterface(uri);
nsCOMPtr<nsIURL> origURL = do_QueryInterface(mFileURI);
nsCOMPtr<nsIURL> targetURL = do_QueryInterface(targetURI);
nsAutoCString queryString;
if (origURL && targetURL && NS_SUCCEEDED(origURL->GetQuery(queryString))) {
@ -289,13 +302,13 @@ nsFileChannel::nsFileChannel(nsIURI *uri)
}
SetURI(targetURI);
SetOriginalURI(uri);
nsLoadFlags loadFlags = 0;
GetLoadFlags(&loadFlags);
SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE);
SetOriginalURI(mFileURI);
mLoadInfo->SetResultPrincipalURI(targetURI);
} else {
SetURI(uri);
SetURI(mFileURI);
}
return NS_OK;
}
nsFileChannel::~nsFileChannel()

View File

@ -22,6 +22,8 @@ public:
explicit nsFileChannel(nsIURI *uri);
nsresult Init();
protected:
~nsFileChannel();
@ -40,6 +42,7 @@ protected:
private:
nsCOMPtr<nsIInputStream> mUploadStream;
int64_t mUploadLength;
nsCOMPtr<nsIURI> mFileURI;
};
#endif // !nsFileChannel_h__

View File

@ -190,6 +190,8 @@ nsFileProtocolHandler::NewChannel2(nsIURI* uri,
nsILoadInfo* aLoadInfo,
nsIChannel** result)
{
nsresult rv;
nsFileChannel *chan;
if (IsNeckoChild()) {
chan = new mozilla::net::FileChannelChild(uri);
@ -200,14 +202,16 @@ nsFileProtocolHandler::NewChannel2(nsIURI* uri,
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(chan);
nsresult rv = chan->Init();
// set the loadInfo on the new channel ; must do this
// before calling Init() on it, since it needs the load
// info be already set.
rv = chan->SetLoadInfo(aLoadInfo);
if (NS_FAILED(rv)) {
NS_RELEASE(chan);
return rv;
}
// set the loadInfo on the new channel
rv = chan->SetLoadInfo(aLoadInfo);
rv = chan->Init();
if (NS_FAILED(rv)) {
NS_RELEASE(chan);
return rv;

View File

@ -3021,6 +3021,70 @@ void HttpBaseChannel::AssertPrivateBrowsingId()
}
#endif
already_AddRefed<nsILoadInfo>
HttpBaseChannel::CloneLoadInfoForRedirect(nsIURI * newURI, uint32_t redirectFlags)
{
// make a copy of the loadinfo, append to the redirectchain
// this will be set on the newly created channel for the redirect target.
if (!mLoadInfo) {
return nullptr;
}
nsCOMPtr<nsILoadInfo> newLoadInfo =
static_cast<mozilla::LoadInfo*>(mLoadInfo.get())->Clone();
nsContentPolicyType contentPolicyType = mLoadInfo->GetExternalContentPolicyType();
if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
nsCOMPtr<nsIPrincipal> nullPrincipalToInherit = NullPrincipal::Create();
newLoadInfo->SetPrincipalToInherit(nullPrincipalToInherit);
}
// re-compute the origin attributes of the loadInfo if it's top-level load.
bool isTopLevelDoc =
newLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DOCUMENT;
if (isTopLevelDoc) {
nsCOMPtr<nsILoadContext> loadContext;
NS_QueryNotificationCallbacks(this, loadContext);
OriginAttributes docShellAttrs;
if (loadContext) {
loadContext->GetOriginAttributes(docShellAttrs);
}
OriginAttributes attrs = newLoadInfo->GetOriginAttributes();
MOZ_ASSERT(docShellAttrs.mUserContextId == attrs.mUserContextId,
"docshell and necko should have the same userContextId attribute.");
MOZ_ASSERT(docShellAttrs.mInIsolatedMozBrowser == attrs.mInIsolatedMozBrowser,
"docshell and necko should have the same inIsolatedMozBrowser attribute.");
MOZ_ASSERT(docShellAttrs.mPrivateBrowsingId == attrs.mPrivateBrowsingId,
"docshell and necko should have the same privateBrowsingId attribute.");
attrs = docShellAttrs;
attrs.SetFirstPartyDomain(true, newURI);
newLoadInfo->SetOriginAttributes(attrs);
}
// Leave empty, we want a 'clean ground' when creating the new channel.
// This will be ensured to be either set by the protocol handler or set
// to the redirect target URI properly after the channel creation.
newLoadInfo->SetResultPrincipalURI(nullptr);
bool isInternalRedirect =
(redirectFlags & (nsIChannelEventSink::REDIRECT_INTERNAL |
nsIChannelEventSink::REDIRECT_STS_UPGRADE));
nsCString remoteAddress;
Unused << GetRemoteAddress(remoteAddress);
nsCOMPtr<nsIRedirectHistoryEntry> entry =
new nsRedirectHistoryEntry(GetURIPrincipal(), mReferrer, remoteAddress);
newLoadInfo->AppendRedirectHistoryEntry(entry, isInternalRedirect);
return newLoadInfo.forget();
}
//-----------------------------------------------------------------------------
// nsHttpChannel::nsITraceableChannel
//-----------------------------------------------------------------------------
@ -3170,10 +3234,33 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
bool preserveMethod,
uint32_t redirectFlags)
{
nsresult rv;
LOG(("HttpBaseChannel::SetupReplacementChannel "
"[this=%p newChannel=%p preserveMethod=%d]",
this, newChannel, preserveMethod));
// Ensure the channel's loadInfo's result principal URI so that it's
// either non-null or updated to the redirect target URI.
// We must do this because in case the loadInfo's result principal URI
// is null, it would be taken from OriginalURI of the channel. But we
// overwrite it with the whole redirect chain first URI before opening
// the target channel, hence the information would be lost.
// If the protocol handler that created the channel wants to use
// the originalURI of the channel as the principal URI, this fulfills
// that request - newURI is the original URI of the channel.
nsCOMPtr<nsILoadInfo> newLoadInfo = newChannel->GetLoadInfo();
if (newLoadInfo) {
nsCOMPtr<nsIURI> resultPrincipalURI;
rv = newLoadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
NS_ENSURE_SUCCESS(rv, rv);
if (!resultPrincipalURI) {
rv = newLoadInfo->SetResultPrincipalURI(newURI);
NS_ENSURE_SUCCESS(rv, rv);
}
}
uint32_t newLoadFlags = mLoadFlags | LOAD_REPLACE;
// if the original channel was using SSL and this channel is not using
// SSL, then no need to inhibit persistent caching. however, if the
@ -3182,7 +3269,7 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
// since we force set INHIBIT_PERSISTENT_CACHING on all HTTPS channels,
// we only need to check if the original channel was using SSL.
bool usingSSL = false;
nsresult rv = mURI->SchemeIs("https", &usingSSL);
rv = mURI->SchemeIs("https", &usingSSL);
if (NS_SUCCEEDED(rv) && usingSSL)
newLoadFlags &= ~INHIBIT_PERSISTENT_CACHING;
@ -3207,62 +3294,6 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
}
}
// make a copy of the loadinfo, append to the redirectchain
// and set it on the new channel
if (mLoadInfo) {
nsCOMPtr<nsILoadInfo> newLoadInfo =
static_cast<mozilla::LoadInfo*>(mLoadInfo.get())->Clone();
nsContentPolicyType contentPolicyType = mLoadInfo->GetExternalContentPolicyType();
if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
nsCOMPtr<nsIPrincipal> nullPrincipalToInherit = NullPrincipal::Create();
newLoadInfo->SetPrincipalToInherit(nullPrincipalToInherit);
}
// re-compute the origin attributes of the loadInfo if it's top-level load.
bool isTopLevelDoc =
newLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DOCUMENT;
if (isTopLevelDoc) {
nsCOMPtr<nsILoadContext> loadContext;
NS_QueryNotificationCallbacks(this, loadContext);
OriginAttributes docShellAttrs;
if (loadContext) {
loadContext->GetOriginAttributes(docShellAttrs);
}
OriginAttributes attrs = newLoadInfo->GetOriginAttributes();
MOZ_ASSERT(docShellAttrs.mUserContextId == attrs.mUserContextId,
"docshell and necko should have the same userContextId attribute.");
MOZ_ASSERT(docShellAttrs.mInIsolatedMozBrowser == attrs.mInIsolatedMozBrowser,
"docshell and necko should have the same inIsolatedMozBrowser attribute.");
MOZ_ASSERT(docShellAttrs.mPrivateBrowsingId == attrs.mPrivateBrowsingId,
"docshell and necko should have the same privateBrowsingId attribute.");
attrs = docShellAttrs;
attrs.SetFirstPartyDomain(true, newURI);
newLoadInfo->SetOriginAttributes(attrs);
}
bool isInternalRedirect =
(redirectFlags & (nsIChannelEventSink::REDIRECT_INTERNAL |
nsIChannelEventSink::REDIRECT_STS_UPGRADE));
nsCString remoteAddress;
Unused << GetRemoteAddress(remoteAddress);
nsCOMPtr<nsIRedirectHistoryEntry> entry =
new nsRedirectHistoryEntry(GetURIPrincipal(), mReferrer, remoteAddress);
newLoadInfo->AppendRedirectHistoryEntry(entry, isInternalRedirect);
newChannel->SetLoadInfo(newLoadInfo);
}
else {
// the newChannel was created with a dummy loadInfo, we should clear
// it in case the original channel does not have a loadInfo
newChannel->SetLoadInfo(nullptr);
}
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
if (!httpChannel)
return NS_OK; // no other options to set

View File

@ -432,6 +432,9 @@ protected:
void AssertPrivateBrowsingId();
#endif
// Called before we create the redirect target channel.
already_AddRefed<nsILoadInfo> CloneLoadInfoForRedirect(nsIURI *newURI, uint32_t redirectFlags);
friend class PrivateBrowsingChannel<HttpBaseChannel>;
friend class InterceptFailedOnStop;

View File

@ -1506,9 +1506,10 @@ HttpChannelChild::SetupRedirect(nsIURI* uri,
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIChannel> newChannel;
nsCOMPtr<nsILoadInfo> redirectLoadInfo = CloneLoadInfoForRedirect(uri, redirectFlags);
rv = NS_NewChannelInternal(getter_AddRefs(newChannel),
uri,
mLoadInfo,
redirectLoadInfo,
nullptr, // aLoadGroup
nullptr, // aCallbacks
nsIRequest::LOAD_NORMAL,

View File

@ -2788,6 +2788,8 @@ nsHttpChannel::StartRedirectChannelToURI(nsIURI *upgradedURI, uint32_t flags)
LOG(("nsHttpChannel::StartRedirectChannelToURI()\n"));
nsCOMPtr<nsIChannel> newChannel;
nsCOMPtr<nsILoadInfo> redirectLoadInfo = CloneLoadInfoForRedirect(upgradedURI,
flags);
nsCOMPtr<nsIIOService> ioService;
rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
@ -2795,7 +2797,7 @@ nsHttpChannel::StartRedirectChannelToURI(nsIURI *upgradedURI, uint32_t flags)
rv = NS_NewChannelInternal(getter_AddRefs(newChannel),
upgradedURI,
mLoadInfo,
redirectLoadInfo,
nullptr, // aLoadGroup
nullptr, // aCallbacks
nsIRequest::LOAD_NORMAL,
@ -5679,22 +5681,23 @@ nsHttpChannel::ContinueProcessRedirectionAfterFallback(nsresult rv)
rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIChannel> newChannel;
rv = NS_NewChannelInternal(getter_AddRefs(newChannel),
mRedirectURI,
mLoadInfo,
nullptr, // aLoadGroup
nullptr, // aCallbacks
nsIRequest::LOAD_NORMAL,
ioService);
NS_ENSURE_SUCCESS(rv, rv);
uint32_t redirectFlags;
if (nsHttp::IsPermanentRedirect(mRedirectType))
redirectFlags = nsIChannelEventSink::REDIRECT_PERMANENT;
else
redirectFlags = nsIChannelEventSink::REDIRECT_TEMPORARY;
nsCOMPtr<nsIChannel> newChannel;
nsCOMPtr<nsILoadInfo> redirectLoadInfo = CloneLoadInfoForRedirect(mRedirectURI, redirectFlags);
rv = NS_NewChannelInternal(getter_AddRefs(newChannel),
mRedirectURI,
redirectLoadInfo,
nullptr, // aLoadGroup
nullptr, // aCallbacks
nsIRequest::LOAD_NORMAL,
ioService);
NS_ENSURE_SUCCESS(rv, rv);
rv = SetupReplacementChannel(mRedirectURI, newChannel,
!rewriteToGET, redirectFlags);
if (NS_FAILED(rv)) return rv;

View File

@ -33,6 +33,10 @@ protected:
const nsACString& aPathname,
nsACString& aResult) override;
// |result| is an inout param. On entry to this function, *result
// is expected to be non-null and already addrefed. This function
// may release the object stored in *result on entry and write
// a new pointer to an already addrefed channel to *result.
virtual MOZ_MUST_USE nsresult SubstituteChannel(nsIURI* uri,
nsILoadInfo* aLoadInfo,
nsIChannel** result) override;

View File

@ -246,6 +246,8 @@ SubstitutingProtocolHandler::NewChannel2(nsIURI* uri,
nsIChannel** result)
{
NS_ENSURE_ARG_POINTER(uri);
NS_ENSURE_ARG_POINTER(aLoadInfo);
nsAutoCString spec;
nsresult rv = ResolveURI(uri, spec);
NS_ENSURE_SUCCESS(rv, rv);
@ -254,12 +256,18 @@ SubstitutingProtocolHandler::NewChannel2(nsIURI* uri,
rv = NS_NewURI(getter_AddRefs(newURI), spec);
NS_ENSURE_SUCCESS(rv, rv);
// We don't want to allow the inner protocol handler to modify the result
// principal URI since we want either |uri| or anything pre-set by upper
// layers to prevail.
nsCOMPtr<nsIURI> savedResultPrincipalURI;
rv = aLoadInfo->GetResultPrincipalURI(getter_AddRefs(savedResultPrincipalURI));
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_NewChannelInternal(result, newURI, aLoadInfo);
NS_ENSURE_SUCCESS(rv, rv);
nsLoadFlags loadFlags = 0;
(*result)->GetLoadFlags(&loadFlags);
(*result)->SetLoadFlags(loadFlags & ~nsIChannel::LOAD_REPLACE);
rv = aLoadInfo->SetResultPrincipalURI(savedResultPrincipalURI);
NS_ENSURE_SUCCESS(rv, rv);
rv = (*result)->SetOriginalURI(uri);
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -877,6 +877,10 @@ nsMultiMixedConv::SendStart()
mPartChannel->SetContentDisposition(mContentDisposition);
// Each part of a multipart/replace response can be used
// for the top level document. We must inform upper layers
// about this by setting the LOAD_REPLACE flag so that certain
// state assertions are evaluated as positive.
nsLoadFlags loadFlags = 0;
mPartChannel->GetLoadFlags(&loadFlags);
loadFlags |= nsIChannel::LOAD_REPLACE;

View File

@ -232,9 +232,6 @@ function test_load_replace() {
file = do_get_file("data/system_root.lnk", false);
var chan = new_file_channel(file);
// The LOAD_REPLACE flag should be set
do_check_eq(chan.loadFlags & chan.LOAD_REPLACE, chan.LOAD_REPLACE);
// The original URI path should differ from the URI path
do_check_neq(chan.URI.path, chan.originalURI.path);

View File

@ -502,14 +502,6 @@ AS_BIN=$AS
AR_EXTRACT='$(AR) x'
AS='$(CC)'
AS_DASH_C_FLAG='-c'
DLL_PREFIX=lib
LIB_PREFIX=lib
RUST_LIB_PREFIX=lib
DLL_SUFFIX=.so
OBJ_SUFFIX=o
LIB_SUFFIX=a
RUST_LIB_SUFFIX=a
IMPORT_LIB_SUFFIX=
DIRENT_INO=d_ino
MOZ_USER_DIR=".mozilla"
@ -815,7 +807,6 @@ case "$target" in
MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
MOZ_OPTIMIZE_FLAGS="-O3"
CXXFLAGS="$CXXFLAGS -stdlib=libc++"
DLL_SUFFIX=".dylib"
DSO_LDOPTS=''
STRIP_FLAGS="$STRIP_FLAGS -x -S"
# Ensure that if we're targeting iOS an SDK was provided.
@ -906,7 +897,6 @@ case "$target" in
*-mingw*)
DSO_CFLAGS=
DSO_PIC_CFLAGS=
DLL_SUFFIX=.dll
RC=rc.exe
# certain versions of cygwin's makedepend barf on the
# #include <string> vs -I./dist/include/string issue so don't use it
@ -928,10 +918,6 @@ case "$target" in
# mingw doesn't require kernel32, user32, and advapi32 explicitly
LIBS="$LIBS -luuid -lgdi32 -lwinmm -lwsock32 -luserenv -lsecur32"
MOZ_FIX_LINK_PATHS=
DLL_PREFIX=
IMPORT_LIB_SUFFIX=a
RUST_LIB_PREFIX=
RUST_LIB_SUFFIX=lib
WIN32_CONSOLE_EXE_LDFLAGS=-mconsole
WIN32_GUI_EXE_LDFLAGS=-mwindows
@ -952,13 +938,6 @@ case "$target" in
RANLIB='echo not_ranlib'
STRIP='echo not_strip'
PKG_SKIP_STRIP=1
OBJ_SUFFIX=obj
LIB_SUFFIX=lib
RUST_LIB_SUFFIX=lib
DLL_PREFIX=
LIB_PREFIX=
RUST_LIB_PREFIX=
IMPORT_LIB_SUFFIX=lib
MKSHLIB='$(LINK) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
MKCSHLIB='$(LINK) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
WIN32_SUBSYSTEM_VERSION=6.01
@ -1157,13 +1136,11 @@ case "$target" in
CFLAGS="$CFLAGS -Dunix"
CXXFLAGS="$CXXFLAGS -Dunix"
if $CC -E - -dM </dev/null | grep __ELF__ >/dev/null; then
DLL_SUFFIX=".so"
DSO_PIC_CFLAGS='-fPIC -DPIC'
DSO_LDOPTS='-shared'
BIN_FLAGS='-Wl,--export-dynamic'
else
DSO_PIC_CFLAGS='-fPIC -DPIC'
DLL_SUFFIX=".so.1.0"
DSO_LDOPTS='-shared'
fi
# This will fail on a.out systems prior to 1.5.1_ALPHA.
@ -1175,11 +1152,6 @@ case "$target" in
;;
*-openbsd*)
if test "$SO_VERSION"; then
DLL_SUFFIX=".so.$SO_VERSION"
else
DLL_SUFFIX=".so.1.0"
fi
if test -z "$X11BASE"; then
X11BASE=/usr/X11R6
fi
@ -5271,16 +5243,7 @@ AC_SUBST(MKCSHLIB)
AC_SUBST(DSO_CFLAGS)
AC_SUBST(DSO_PIC_CFLAGS)
AC_SUBST(DSO_LDOPTS)
AC_SUBST(LIB_PREFIX)
AC_SUBST(RUST_LIB_PREFIX)
AC_SUBST(DLL_PREFIX)
AC_SUBST(DLL_SUFFIX)
AC_DEFINE_UNQUOTED(MOZ_DLL_SUFFIX, "$DLL_SUFFIX")
AC_SUBST(LIB_SUFFIX)
AC_SUBST(RUST_LIB_SUFFIX)
AC_SUBST(OBJ_SUFFIX)
AC_SUBST(BIN_SUFFIX)
AC_SUBST(IMPORT_LIB_SUFFIX)
AC_SUBST(USE_N32)
AC_SUBST(CC_VERSION)
AC_SUBST(NS_ENABLE_TSF)

View File

@ -229,6 +229,20 @@ class LcovFile(object):
# LF:<number of instrumented lines>
# LH:<number of lines with a non-zero execution count>
# end_of_record
PREFIX_TYPES = {
'TN': 0,
'SF': 0,
'FN': 1,
'FNDA': 1,
'FNF': 0,
'FNH': 0,
'BRDA': 3,
'BRF': 0,
'BRH': 0,
'DA': 2,
'LH': 0,
'LF': 0,
}
def __init__(self, lcov_fh):
# These are keyed by source file because output will split sources (at
@ -267,14 +281,10 @@ class LcovFile(object):
# We occasionally end up with multi-line scripts in data:
# uris that will trip up the parser, just skip them for now.
if colon < 0 or prefix not in ('TN', 'SF', 'FN', 'FNDA', 'FNF',
'FNH', 'BRDA', 'BRF', 'BRH', 'DA',
'LF', 'LH'):
if colon < 0 or prefix not in self.PREFIX_TYPES:
continue
if prefix not in ('SF', 'TN'):
args = line[(colon + 1):].split(',')
else:
args = line[(colon + 1):],
args = line[(colon + 1):].split(',', self.PREFIX_TYPES[prefix])
def try_convert(a):
try:

View File

@ -83,6 +83,22 @@ LH:8
end_of_record
"""
fn_with_multiple_commas = """TN:Compartment_5f7f5c30251800
SF:resource://gre/modules/osfile.jsm
FN:1,function,name,with,commas
FNDA:1,function,name,with,commas
FNF:1
FNH:1
BRDA:9,0,61,1
BRF:1
BRH:1
DA:9,1
DA:24,1
LF:2
LH:2
end_of_record
"""
class TestLcovParser(unittest.TestCase):
def get_lcov(self, lcov_string):
@ -112,6 +128,9 @@ class TestLcovParser(unittest.TestCase):
output = self.parser_roundtrip(multiple_records, True)
self.assertEqual(multiple_records, output)
def test_multiple_commas(self):
output = self.parser_roundtrip(fn_with_multiple_commas, True)
self.assertEqual(fn_with_multiple_commas, output)
multiple_included_files = """//@line 1 "foo.js"
bazfoobar

View File

@ -328,6 +328,7 @@ jsreftest:
android-4.3-arm7-api-15/debug: 100
android.*: 40
windows.*: 2
linux64-ccov/.*: 5
linux64-qr/.*: 4
macosx.*: 2
default: 3

View File

@ -33,7 +33,8 @@ config = {
],
"channel_names": ["beta-dev", "beta-dev-localtest", "beta-dev-cdntest"],
"rules_to_update": ["firefox-beta-dev-cdntest", "firefox-beta-dev-localtest"],
"publish_rules": ["firefox-beta"],
"publish_rules": ["firefox-beta"],
"schedule_asap": True,
},
"release-dev": {
"version_regex": r"^\d+\.\d+(\.\d+)?$",

View File

@ -28,7 +28,7 @@ config = {
"mar_channel_ids": [],
"channel_names": ["beta", "beta-localtest", "beta-cdntest"],
"rules_to_update": ["firefox-beta-cdntest", "firefox-beta-localtest"],
"publish_rules": ["firefox-beta"],
"publish_rules": [32],
},
},
"balrog_use_dummy_suffix": False,

View File

@ -31,7 +31,7 @@ config = {
"mar_channel_ids": [],
"channel_names": ["aurora", "aurora-localtest", "aurora-cdntest"],
"rules_to_update": ["devedition-cdntest", "devedition-localtest"],
"publish_rules": ["devedition"],
"publish_rules": [10],
},
},
"balrog_use_dummy_suffix": False,

View File

@ -28,7 +28,7 @@ config = {
"mar_channel_ids": [],
"channel_names": ["esr", "esr-localtest", "esr-cdntest"],
"rules_to_update": ["esr52-cdntest", "esr52-localtest"],
"publish_rules": ["esr52"],
"publish_rules": [521],
},
},
"balrog_use_dummy_suffix": False,

View File

@ -30,7 +30,8 @@ config = {
],
"channel_names": ["beta", "beta-localtest", "beta-cdntest"],
"rules_to_update": ["firefox-beta-cdntest", "firefox-beta-localtest"],
"publish_rules": ["firefox-beta"],
"publish_rules": [32],
"schedule_asap": True,
},
"release": {
"version_regex": r"^\d+\.\d+(\.\d+)?$",
@ -40,7 +41,7 @@ config = {
"mar_channel_ids": [],
"channel_names": ["release", "release-localtest", "release-cdntest"],
"rules_to_update": ["firefox-release-cdntest", "firefox-release-localtest"],
"publish_rules": ["firefox-release"],
"publish_rules": [145],
},
},
"balrog_use_dummy_suffix": False,

View File

@ -14,7 +14,6 @@ import sys
import signal
import socket
import subprocess
import telnetlib
import time
import tempfile
@ -262,12 +261,6 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin
self.info('stderr: %s' % str(err.strip()))
return out
def _telnet_cmd(self, telnet, command):
telnet.write('%s\n' % command)
result = telnet.read_until('OK', 10)
self.info('%s: %s' % (command, result))
return result
def _verify_adb(self):
self.info('Verifying adb connectivity')
self._run_with_timeout(180, [self.adb_path, 'wait-for-device'])
@ -287,37 +280,6 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin
return True
return False
def _telnet_to_emulator(self):
port = self.emulator["emulator_port"]
telnet_ok = False
try:
tn = telnetlib.Telnet('localhost', port, 10)
if tn is not None:
self.info('Connected to port %d' % port)
res = tn.read_until('OK', 10)
self.info(res)
self._telnet_cmd(tn, 'avd status')
self._telnet_cmd(tn, 'redir list')
self._telnet_cmd(tn, 'network status')
tn.write('quit\n')
tn.read_all()
telnet_ok = True
else:
self.warning('Unable to connect to port %d' % port)
except socket.error, e:
self.info('Trying again after socket error: %s' % str(e))
pass
except EOFError:
self.info('Trying again after EOF')
pass
except:
self.info('Trying again after unexpected exception')
pass
finally:
if tn is not None:
tn.close()
return telnet_ok
def _verify_emulator(self):
adb_ok = self._verify_adb()
if not adb_ok:
@ -331,10 +293,6 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin
if not boot_ok:
self.warning('Unable to verify Android boot completion')
return False
telnet_ok = self._retry(4, 30, self._telnet_to_emulator, "Verify telnet to emulator")
if not telnet_ok:
self.warning('Unable to telnet to emulator on port %d' % self.emulator["emulator_port"])
return False
return True
def _verify_emulator_and_restart_on_fail(self):
@ -672,7 +630,7 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin
def verify_emulator(self):
'''
Check to see if the emulator can be contacted via adb and telnet.
Check to see if the emulator can be contacted via adb.
If any communication attempt fails, kill the emulator, re-launch, and re-check.
'''
self.mkdir_p(self.query_abs_dirs()['abs_blob_upload_dir'])

View File

@ -13,6 +13,7 @@ A script publish a release to Balrog.
import os
import sys
from datetime import datetime, timedelta
sys.path.insert(1, os.path.dirname(os.path.dirname(sys.path[0])))
from mozharness.base.vcs.vcsbase import MercurialScript
@ -74,7 +75,7 @@ class PublishBalrog(MercurialScript, BuildbotMixin):
:return: list
"""
return [(n, c) for n, c in self.config["update_channels"].items() if
n in self.config["channels"]]
n in self.config["channels"]]
def query_repos(self):
"""Build a list of repos to clone."""
@ -84,7 +85,6 @@ class PublishBalrog(MercurialScript, BuildbotMixin):
super(PublishBalrog, self).pull(
repos=self.query_repos())
def submit_to_balrog(self):
for _, channel_config in self.query_channel_configs():
self._submit_to_balrog(channel_config)
@ -107,13 +107,21 @@ class PublishBalrog(MercurialScript, BuildbotMixin):
])
for r in channel_config["publish_rules"]:
cmd.extend(["--rules", r])
if self.config.get("schedule_at"):
if channel_config.get("schedule_asap"):
# RC releases going to the beta channel have no ETA set for the
# RC-to-beta push. The corresponding task is scheduled after we
# resolve the push-to-beta human decision task, so we can schedule
# it ASAP plus some additional 30m to avoid retry() to fail.
schedule_at = datetime.utcnow() + timedelta(minutes=30)
cmd.extend(["--schedule-at", schedule_at.isoformat()])
elif self.config.get("schedule_at"):
cmd.extend(["--schedule-at", self.config["schedule_at"]])
if self.config.get("background_rate"):
cmd.extend(["--background-rate", str(self.config["background_rate"])])
self.retry(lambda: self.run_command(cmd, halt_on_failure=True))
# __main__ {{{1
if __name__ == '__main__':
PublishBalrog().run_and_exit()

View File

@ -104624,6 +104624,12 @@
{}
]
],
"intersection-observer/bounding-box.html": [
[
"/intersection-observer/bounding-box.html",
{}
]
],
"intersection-observer/client-rect.html": [
[
"/intersection-observer/client-rect.html",
@ -192591,6 +192597,10 @@
"4f94c4236168ed722f71d81bd957e0da72b29c71",
"support"
],
"intersection-observer/bounding-box.html": [
"0deef078368d11e2a55ef0988d50f548587a4c57",
"testharness"
],
"intersection-observer/client-rect.html": [
"acec9a4f59ebee1840950cf766a45676490eef84",
"testharness"

View File

@ -0,0 +1,2 @@
[bounding-box.html]
type: testharness

View File

@ -1,3 +1,2 @@
[edge-inclusive-intersection.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1359317

View File

@ -1,3 +1,2 @@
[unclipped-root.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1359317

View File

@ -0,0 +1,61 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="./resources/intersection-observer-test-utils.js"></script>
<style>
pre, #log {
position: absolute;
top: 0;
left: 200px;
}
#root {
overflow: visible;
height: 200px;
width: 160px;
border: 7px solid black;
}
#target {
margin: 10px;
width: 100px;
height: 100px;
padding: 10px;
background-color: green;
}
</style>
<div id="root">
<div id="target" style="transform: translateY(300px)"></div>
</div>
<script>
var entries = [];
var target;
runTestCycle(function() {
target = document.getElementById("target");
assert_true(!!target, "target exists");
var root = document.getElementById("root");
assert_true(!!root, "root exists");
var observer = new IntersectionObserver(function(changes) {
entries = entries.concat(changes)
}, {root: root});
observer.observe(target);
entries = entries.concat(observer.takeRecords());
assert_equals(entries.length, 0, "No initial notifications.");
runTestCycle(step0, "First rAF.");
}, "Test that the target's border bounding box is used to calculate intersection.");
function step0() {
var targetBounds = clientBounds(target);
target.style.transform = "translateY(195px)";
runTestCycle(step1, "target.style.transform = 'translateY(195px)'");
checkLastEntry(entries, 0, targetBounds.concat(0, 0, 0, 0, 8, 182, 8, 222, false));
}
function step1() {
var targetBounds = clientBounds(target);
target.style.transform = "";
checkLastEntry(entries, 1, targetBounds.concat(25, 145, 220, 222, 8, 182, 8, 222, true));
}
</script>

View File

@ -748,6 +748,7 @@ this.Extension = class extends ExtensionData {
this.parentMessageManager = null;
this.id = addonData.id;
this.version = addonData.version;
this.baseURI = NetUtil.newURI(this.getURL("")).QueryInterface(Ci.nsIURL);
this.principal = this.createPrincipal();
@ -855,7 +856,7 @@ this.Extension = class extends ExtensionData {
}
readLocaleFile(locale) {
return StartupCache.locales.get([this.id, locale],
return StartupCache.locales.get([this.id, this.version, locale],
() => super.readLocaleFile(locale))
.then(result => {
this.localeData.messages.set(locale, result);
@ -863,7 +864,7 @@ this.Extension = class extends ExtensionData {
}
parseManifest() {
return StartupCache.manifests.get([this.id, Locale.getLocale()],
return StartupCache.manifests.get([this.id, this.version, Locale.getLocale()],
() => super.parseManifest());
}

View File

@ -109,12 +109,15 @@ class EmbeddedExtension {
* An object with the following properties:
* @param {string} containerAddonParams.id
* The Add-on id of the Legacy Extension which will contain the embedded webextension.
* @param {string} containerAddonParams.version
* The add-on version.
* @param {nsIURI} containerAddonParams.resourceURI
* The nsIURI of the Legacy Extension container add-on.
*/
constructor({id, resourceURI}) {
constructor({id, resourceURI, version}) {
this.addonId = id;
this.resourceURI = resourceURI;
this.version = version;
// Setup status flag.
this.started = false;
@ -139,6 +142,7 @@ class EmbeddedExtension {
this.extension = new Extension({
id: this.addonId,
resourceURI: embeddedExtensionURI,
version: this.version,
});
// This callback is register to the "startup" event, emitted by the Extension instance
@ -227,11 +231,11 @@ EmbeddedExtensionManager = {
}
},
getEmbeddedExtensionFor({id, resourceURI}) {
getEmbeddedExtensionFor({id, resourceURI, version}) {
let embeddedExtension = this.embeddedExtensionsByAddonId.get(id);
if (!embeddedExtension) {
embeddedExtension = new EmbeddedExtension({id, resourceURI});
embeddedExtension = new EmbeddedExtension({id, resourceURI, version});
// Keep track of the embedded extension instance.
this.embeddedExtensionsByAddonId.set(id, embeddedExtension);
}

View File

@ -31,8 +31,8 @@ mozProtocolHandler.prototype = {
newChannel2(uri, loadInfo) {
let realURL = NetUtil.newURI(this.urlToLoad);
let channel = Services.io.newChannelFromURIWithLoadInfo(realURL, loadInfo)
channel.loadFlags |= Ci.nsIChannel.LOAD_REPLACE;
let channel = Services.io.newChannelFromURIWithLoadInfo(realURL, loadInfo);
loadInfo.resultPrincipalURI = realURL;
return channel;
},

View File

@ -175,8 +175,29 @@ var SessionHistoryInternal = {
entry.originalURI = shEntry.originalURI.spec;
}
if (shEntry.resultPrincipalURI) {
entry.resultPrincipalURI = shEntry.resultPrincipalURI.spec;
// For downgrade compatibility we store the loadReplace property as it
// would be stored before result principal URI introduction so that
// the old code can still create URL based principals for channels
// correctly. When resultPrincipalURI is non-null and not equal to
// channel's orignalURI in the new code, it's equal to setting
// LOAD_REPLACE in the old code. Note that we only do 'the best we can'
// here to derivate the 'old' loadReplace flag value.
entry.loadReplace = entry.resultPrincipalURI != entry.originalURI;
} else {
// We want to store the property to let the backward compatibility code,
// when reading the stored session, work. When this property is undefined
// that code will derive the result principal URI from the load replace
// flag.
entry.resultPrincipalURI = null;
}
if (shEntry.loadReplace) {
entry.loadReplace = shEntry.loadReplace;
// Storing under a new property name, since it has changed its meaning
// with the result principal URI introduction.
entry.loadReplace2 = shEntry.loadReplace;
}
if (shEntry.srcdocData)
@ -368,8 +389,17 @@ var SessionHistoryInternal = {
if (entry.originalURI) {
shEntry.originalURI = Utils.makeURI(entry.originalURI);
}
if (entry.loadReplace) {
shEntry.loadReplace = entry.loadReplace;
if (typeof entry.resultPrincipalURI === "undefined" && entry.loadReplace) {
// This is backward compatibility code for stored sessions saved prior to
// introduction of the resultPrincipalURI property. The equivalent of this
// property non-null value used to be the URL while the LOAD_REPLACE flag
// was set.
shEntry.resultPrincipalURI = shEntry.URI;
} else if (entry.resultPrincipalURI) {
shEntry.resultPrincipalURI = Utils.makeURI(entry.resultPrincipalURI);
}
if (entry.loadReplace2) {
shEntry.loadReplace = entry.loadReplace2;
}
if (entry.isSrcdocEntry)
shEntry.srcdocData = entry.srcdocData;

View File

@ -10,16 +10,18 @@
#include "Layers.h"
#include "mozilla/Sprintf.h"
using namespace mozilla;
ProfilerMarkerPayload::ProfilerMarkerPayload(UniqueProfilerBacktrace aStack)
: mStack(mozilla::Move(aStack))
: mStack(Move(aStack))
{}
ProfilerMarkerPayload::ProfilerMarkerPayload(const mozilla::TimeStamp& aStartTime,
const mozilla::TimeStamp& aEndTime,
ProfilerMarkerPayload::ProfilerMarkerPayload(const TimeStamp& aStartTime,
const TimeStamp& aEndTime,
UniqueProfilerBacktrace aStack)
: mStartTime(aStartTime)
, mEndTime(aEndTime)
, mStack(mozilla::Move(aStack))
, mStack(Move(aStack))
{}
ProfilerMarkerPayload::~ProfilerMarkerPayload()
@ -27,7 +29,7 @@ ProfilerMarkerPayload::~ProfilerMarkerPayload()
}
void
ProfilerMarkerPayload::streamCommonProps(const char* aMarkerType,
ProfilerMarkerPayload::StreamCommonProps(const char* aMarkerType,
SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks)
@ -51,30 +53,30 @@ ProfilerMarkerPayload::streamCommonProps(const char* aMarkerType,
}
}
ProfilerMarkerTracing::ProfilerMarkerTracing(const char* aCategory,
TracingKind aKind)
TracingMarkerPayload::TracingMarkerPayload(const char* aCategory,
TracingKind aKind)
: mCategory(aCategory)
, mKind(aKind)
{
}
ProfilerMarkerTracing::ProfilerMarkerTracing(const char* aCategory,
TracingKind aKind,
UniqueProfilerBacktrace aCause)
TracingMarkerPayload::TracingMarkerPayload(const char* aCategory,
TracingKind aKind,
UniqueProfilerBacktrace aCause)
: mCategory(aCategory)
, mKind(aKind)
{
if (aCause) {
SetStack(mozilla::Move(aCause));
SetStack(Move(aCause));
}
}
void
ProfilerMarkerTracing::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks)
TracingMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks)
{
streamCommonProps("tracing", aWriter, aProcessStartTime, aUniqueStacks);
StreamCommonProps("tracing", aWriter, aProcessStartTime, aUniqueStacks);
if (GetCategory()) {
aWriter.StringProperty("category", GetCategory());
@ -88,8 +90,8 @@ ProfilerMarkerTracing::StreamPayload(SpliceableJSONWriter& aWriter,
}
GPUMarkerPayload::GPUMarkerPayload(
const mozilla::TimeStamp& aCpuTimeStart,
const mozilla::TimeStamp& aCpuTimeEnd,
const TimeStamp& aCpuTimeStart,
const TimeStamp& aCpuTimeEnd,
uint64_t aGpuTimeStart,
uint64_t aGpuTimeEnd)
@ -105,7 +107,7 @@ GPUMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks)
{
streamCommonProps("gpu_timer_query", aWriter, aProcessStartTime,
StreamCommonProps("gpu_timer_query", aWriter, aProcessStartTime,
aUniqueStacks);
aWriter.DoubleProperty("cpustart",
@ -116,27 +118,12 @@ GPUMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
aWriter.IntProperty("gpuend", (int)mGpuTimeEnd);
}
ProfilerMarkerImagePayload::ProfilerMarkerImagePayload(gfxASurface *aImg)
: mImg(aImg)
{ }
void
ProfilerMarkerImagePayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks)
{
streamCommonProps("innerHTML", aWriter, aProcessStartTime, aUniqueStacks);
// TODO: Finish me
//aWriter.NameValue("innerHTML", "<img src=''/>");
}
IOMarkerPayload::IOMarkerPayload(const char* aSource,
const char* aFilename,
const mozilla::TimeStamp& aStartTime,
const mozilla::TimeStamp& aEndTime,
const TimeStamp& aStartTime,
const TimeStamp& aEndTime,
UniqueProfilerBacktrace aStack)
: ProfilerMarkerPayload(aStartTime, aEndTime,
mozilla::Move(aStack)),
: ProfilerMarkerPayload(aStartTime, aEndTime, Move(aStack)),
mSource(aSource)
{
mFilename = aFilename ? strdup(aFilename) : nullptr;
@ -152,7 +139,7 @@ IOMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks)
{
streamCommonProps("io", aWriter, aProcessStartTime, aUniqueStacks);
StreamCommonProps("io", aWriter, aProcessStartTime, aUniqueStacks);
aWriter.StringProperty("source", mSource);
if (mFilename != nullptr) {
aWriter.StringProperty("filename", mFilename);
@ -160,7 +147,7 @@ IOMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
}
UserTimingMarkerPayload::UserTimingMarkerPayload(const nsAString& aName,
const mozilla::TimeStamp& aStartTime)
const TimeStamp& aStartTime)
: ProfilerMarkerPayload(aStartTime, aStartTime, nullptr)
, mEntryType("mark")
, mName(aName)
@ -168,8 +155,8 @@ UserTimingMarkerPayload::UserTimingMarkerPayload(const nsAString& aName,
}
UserTimingMarkerPayload::UserTimingMarkerPayload(const nsAString& aName,
const mozilla::TimeStamp& aStartTime,
const mozilla::TimeStamp& aEndTime)
const TimeStamp& aStartTime,
const TimeStamp& aEndTime)
: ProfilerMarkerPayload(aStartTime, aEndTime, nullptr)
, mEntryType("measure")
, mName(aName)
@ -185,14 +172,14 @@ UserTimingMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks)
{
streamCommonProps("UserTiming", aWriter, aProcessStartTime, aUniqueStacks);
StreamCommonProps("UserTiming", aWriter, aProcessStartTime, aUniqueStacks);
aWriter.StringProperty("name", NS_ConvertUTF16toUTF8(mName).get());
aWriter.StringProperty("entryType", mEntryType);
}
DOMEventMarkerPayload::DOMEventMarkerPayload(const nsAString& aType, uint16_t aPhase,
const mozilla::TimeStamp& aStartTime,
const mozilla::TimeStamp& aEndTime)
const TimeStamp& aStartTime,
const TimeStamp& aEndTime)
: ProfilerMarkerPayload(aStartTime, aEndTime, nullptr)
, mType(aType)
, mPhase(aPhase)
@ -208,7 +195,7 @@ DOMEventMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks)
{
streamCommonProps("DOMEvent", aWriter, aProcessStartTime, aUniqueStacks);
StreamCommonProps("DOMEvent", aWriter, aProcessStartTime, aUniqueStacks);
aWriter.StringProperty("type", NS_ConvertUTF16toUTF8(mType).get());
aWriter.IntProperty("phase", mPhase);
}
@ -219,18 +206,18 @@ ProfilerJSEventMarker(const char *event)
PROFILER_MARKER(event);
}
LayerTranslationPayload::LayerTranslationPayload(mozilla::layers::Layer* aLayer,
mozilla::gfx::Point aPoint)
: ProfilerMarkerPayload(mozilla::TimeStamp::Now(), mozilla::TimeStamp::Now(), nullptr)
LayerTranslationMarkerPayload::LayerTranslationMarkerPayload(layers::Layer* aLayer,
gfx::Point aPoint)
: ProfilerMarkerPayload(TimeStamp::Now(), TimeStamp::Now(), nullptr)
, mLayer(aLayer)
, mPoint(aPoint)
{
}
void
LayerTranslationPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks)
LayerTranslationMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks)
{
const size_t bufferSize = 32;
char buffer[bufferSize];
@ -242,31 +229,16 @@ LayerTranslationPayload::StreamPayload(SpliceableJSONWriter& aWriter,
aWriter.StringProperty("category", "LayerTranslation");
}
TouchDataPayload::TouchDataPayload(const mozilla::ScreenIntPoint& aPoint)
: ProfilerMarkerPayload(mozilla::TimeStamp::Now(), mozilla::TimeStamp::Now(), nullptr)
{
mPoint = aPoint;
}
void
TouchDataPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks)
{
aWriter.IntProperty("x", mPoint.x);
aWriter.IntProperty("y", mPoint.y);
}
VsyncPayload::VsyncPayload(mozilla::TimeStamp aVsyncTimestamp)
VsyncMarkerPayload::VsyncMarkerPayload(TimeStamp aVsyncTimestamp)
: ProfilerMarkerPayload(aVsyncTimestamp, aVsyncTimestamp, nullptr)
, mVsyncTimestamp(aVsyncTimestamp)
{
}
void
VsyncPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks)
VsyncMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks)
{
aWriter.DoubleProperty("vsync",
(mVsyncTimestamp - aProcessStartTime).ToMilliseconds());
@ -275,11 +247,11 @@ VsyncPayload::StreamPayload(SpliceableJSONWriter& aWriter,
void
GCSliceMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const mozilla::TimeStamp& aProcessStartTime,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks)
{
MOZ_ASSERT(mTimingJSON);
streamCommonProps("GCSlice", aWriter, aProcessStartTime, aUniqueStacks);
StreamCommonProps("GCSlice", aWriter, aProcessStartTime, aUniqueStacks);
if (mTimingJSON) {
aWriter.SplicedJSONProperty("timings", mTimingJSON.get());
} else {
@ -289,11 +261,11 @@ GCSliceMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
void
GCMajorMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const mozilla::TimeStamp& aProcessStartTime,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks)
{
MOZ_ASSERT(mTimingJSON);
streamCommonProps("GCMajor", aWriter, aProcessStartTime, aUniqueStacks);
StreamCommonProps("GCMajor", aWriter, aProcessStartTime, aUniqueStacks);
if (mTimingJSON) {
aWriter.SplicedJSONProperty("timings", mTimingJSON.get());
} else {
@ -303,11 +275,11 @@ GCMajorMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
void
GCMinorMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const mozilla::TimeStamp& aProcessStartTime,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks)
{
MOZ_ASSERT(mTimingData);
streamCommonProps("GCMinor", aWriter, aProcessStartTime, aUniqueStacks);
StreamCommonProps("GCMinor", aWriter, aProcessStartTime, aUniqueStacks);
if (mTimingData) {
aWriter.SplicedJSONProperty("nurseryTimings", mTimingData.get());
} else {

View File

@ -76,7 +76,7 @@ Thread::GetCurrentId()
}
static void
FillInRegs(Registers& aRegs, ucontext_t* aContext)
PopulateRegsFromContext(Registers& aRegs, ucontext_t* aContext)
{
aRegs.mContext = aContext;
mcontext_t& mcontext = aContext->uc_mcontext;
@ -86,10 +86,12 @@ FillInRegs(Registers& aRegs, ucontext_t* aContext)
aRegs.mPC = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
aRegs.mSP = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
aRegs.mFP = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
aRegs.mLR = 0;
#elif defined(GP_ARCH_amd64)
aRegs.mPC = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
aRegs.mSP = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
aRegs.mFP = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
aRegs.mLR = 0;
#elif defined(GP_ARCH_arm)
aRegs.mPC = reinterpret_cast<Address>(mcontext.arm_pc);
aRegs.mSP = reinterpret_cast<Address>(mcontext.arm_sp);
@ -359,7 +361,7 @@ Sampler::SuspendAndSampleAndResumeThread(PSLockRef aLock,
// Extract the current register values.
Registers regs;
FillInRegs(regs, &sSigHandlerCoordinator->mUContext);
PopulateRegsFromContext(regs, &sSigHandlerCoordinator->mUContext);
aProcessRegs(regs);
//----------------------------------------------------------------//
@ -523,13 +525,18 @@ PlatformInit(PSLockRef aLock)
#endif
void
Registers::SyncPopulate(ucontext_t* aContext)
{
MOZ_ASSERT(aContext);
#if defined(HAVE_NATIVE_UNWIND)
// Context used by synchronous samples. It's safe to have a single one because
// only one synchronous sample can be taken at a time (due to
// profiler_get_backtrace()'s PSAutoLock).
ucontext_t sSyncUContext;
if (!getcontext(aContext)) {
FillInRegs(*this, aContext);
void
Registers::SyncPopulate()
{
if (!getcontext(&sSyncUContext)) {
PopulateRegsFromContext(*this, &sSyncUContext);
}
}
#endif

View File

@ -120,6 +120,7 @@ Sampler::SuspendAndSampleAndResumeThread(PSLockRef aLock,
regs.mPC = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
regs.mSP = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
regs.mFP = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
regs.mLR = 0;
aProcessRegs(regs);
}
@ -192,6 +193,7 @@ PlatformInit(PSLockRef aLock)
{
}
#if defined(HAVE_NATIVE_UNWIND)
void
Registers::SyncPopulate()
{
@ -207,5 +209,7 @@ Registers::SyncPopulate()
);
mPC = reinterpret_cast<Address>(__builtin_extract_return_addr(
__builtin_return_address(0)));
mLR = 0;
}
#endif

View File

@ -38,6 +38,23 @@ Thread::GetCurrentId()
return GetCurrentThreadId();
}
static void
PopulateRegsFromContext(Registers& aRegs, CONTEXT* aContext)
{
#if defined(GP_ARCH_amd64)
aRegs.mPC = reinterpret_cast<Address>(aContext->Rip);
aRegs.mSP = reinterpret_cast<Address>(aContext->Rsp);
aRegs.mFP = reinterpret_cast<Address>(aContext->Rbp);
#elif defined(GP_ARCH_x86)
aRegs.mPC = reinterpret_cast<Address>(aContext->Eip);
aRegs.mSP = reinterpret_cast<Address>(aContext->Esp);
aRegs.mFP = reinterpret_cast<Address>(aContext->Ebp);
#else
#error "bad arch"
#endif
aRegs.mLR = 0;
}
class PlatformData
{
public:
@ -139,16 +156,7 @@ Sampler::SuspendAndSampleAndResumeThread(PSLockRef aLock,
// platform-linux-android.cpp for details.
Registers regs;
#if defined(GP_ARCH_amd64)
regs.mPC = reinterpret_cast<Address>(context.Rip);
regs.mSP = reinterpret_cast<Address>(context.Rsp);
regs.mFP = reinterpret_cast<Address>(context.Rbp);
#else
regs.mPC = reinterpret_cast<Address>(context.Eip);
regs.mSP = reinterpret_cast<Address>(context.Esp);
regs.mFP = reinterpret_cast<Address>(context.Ebp);
#endif
PopulateRegsFromContext(regs, &context);
aProcessRegs(regs);
//----------------------------------------------------------------//
@ -264,20 +272,13 @@ PlatformInit(PSLockRef aLock)
{
}
#if defined(HAVE_NATIVE_UNWIND)
void
Registers::SyncPopulate()
{
CONTEXT context;
RtlCaptureContext(&context);
#if defined(GP_ARCH_amd64)
mPC = reinterpret_cast<Address>(context.Rip);
mSP = reinterpret_cast<Address>(context.Rsp);
mFP = reinterpret_cast<Address>(context.Rbp);
#elif defined(GP_ARCH_x86)
mPC = reinterpret_cast<Address>(context.Eip);
mSP = reinterpret_cast<Address>(context.Esp);
mFP = reinterpret_cast<Address>(context.Ebp);
#endif
PopulateRegsFromContext(*this, &context);
}
#endif

View File

@ -628,26 +628,19 @@ static const char* const kMainThreadName = "GeckoMain";
// BEGIN sampling/unwinding code
// The registers used for stack unwinding and a few other sampling purposes.
// The ctor does nothing; users are responsible for filling in the fields.
class Registers
{
public:
Registers()
: mPC(nullptr)
, mSP(nullptr)
, mFP(nullptr)
, mLR(nullptr)
#if defined(GP_OS_linux) || defined(GP_OS_android)
, mContext(nullptr)
#endif
{}
Registers() {}
// Fills in mContext, mPC, mSP, mFP, and mLR for a synchronous sample.
#if defined(GP_OS_linux) || defined(GP_OS_android)
void SyncPopulate(ucontext_t* aContext);
#else
#if defined(HAVE_NATIVE_UNWIND)
// Fills in mPC, mSP, mFP, mLR, and mContext for a synchronous sample.
void SyncPopulate();
#endif
void Clear() { memset(this, 0, sizeof(*this)); }
// These fields are filled in by
// SamplerThread::SuspendAndSampleAndResumeThread() for periodic and
// backtrace samples, and by SyncPopulate() for synchronous samples.
@ -2834,14 +2827,10 @@ profiler_get_backtrace()
TimeStamp now = TimeStamp::Now();
Registers regs;
#if defined(HAVE_NATIVE_UNWIND)
#if defined(GP_OS_linux) || defined(GP_OS_android)
ucontext_t context;
regs.SyncPopulate(&context);
#else
regs.SyncPopulate();
#endif
#else
regs.Clear();
#endif
auto buffer = MakeUnique<ProfileBuffer>(PROFILER_GET_BACKTRACE_ENTRIES);
@ -2975,7 +2964,7 @@ profiler_tracing(const char* aCategory, const char* aMarkerName,
return;
}
auto payload = MakeUnique<ProfilerMarkerTracing>(aCategory, aKind);
auto payload = MakeUnique<TracingMarkerPayload>(aCategory, aKind);
racy_profiler_add_marker(aMarkerName, Move(payload));
}
@ -2991,7 +2980,7 @@ profiler_tracing(const char* aCategory, const char* aMarkerName,
}
auto payload =
MakeUnique<ProfilerMarkerTracing>(aCategory, aKind, Move(aCause));
MakeUnique<TracingMarkerPayload>(aCategory, aKind, Move(aCause));
racy_profiler_add_marker(aMarkerName, Move(payload));
}

View File

@ -30,20 +30,9 @@ class SpliceableJSONWriter;
namespace mozilla {
class MallocAllocPolicy;
class TimeStamp;
template <class T,
size_t MinInlineCapacity,
class AllocPolicy>
class Vector;
namespace dom {
class Promise;
} // namespace dom
template <class T, size_t MinInlineCapacity, class AllocPolicy> class Vector;
} // namespace mozilla
class nsIProfilerStartParams;
enum TracingKind {
TRACING_EVENT,
TRACING_INTERVAL_START,
@ -59,61 +48,52 @@ struct ProfilerBacktraceDestructor
using UniqueProfilerBacktrace =
mozilla::UniquePtr<ProfilerBacktrace, ProfilerBacktraceDestructor>;
#if !defined(MOZ_GECKO_PROFILER)
#if defined(MOZ_GECKO_PROFILER)
// Use these for functions below that must be visible whether the profiler is
// enabled or not. When the profiler is disabled they are static inline
// functions (with a simple return value if they are non-void) that should be
// optimized away during compilation.
#define PROFILER_FUNC(decl, rv) static inline decl { return rv; }
#define PROFILER_FUNC_VOID(decl) static inline void decl {}
#define PROFILER_FUNC(decl, rv) decl;
#define PROFILER_FUNC_VOID(decl) void decl;
// Insert an RAII object in this scope to enter a pseudo stack frame. Any
// samples collected in this scope will contain this label in their pseudo
// stack. The name_space and info arguments must be string literals.
// Use PROFILER_LABEL_DYNAMIC if you want to add additional / dynamic
// information to the pseudo stack frame.
#define PROFILER_LABEL(name_space, info, category) do {} while (0)
// Uncomment this to turn on systrace or build with
// ac_add_options --enable-systace
//#define MOZ_USE_SYSTRACE
#ifdef MOZ_USE_SYSTRACE
# ifndef ATRACE_TAG
# define ATRACE_TAG ATRACE_TAG_ALWAYS
# endif
// We need HAVE_ANDROID_OS to be defined for Trace.h.
// If its not set we will set it temporary and remove it.
# ifndef HAVE_ANDROID_OS
# define HAVE_ANDROID_OS
# define REMOVE_HAVE_ANDROID_OS
# endif
// Android source code will include <cutils/trace.h> before this. There is no
// HAVE_ANDROID_OS defined in Firefox OS build at that time. Enabled it globally
// will cause other build break. So atrace_begin and atrace_end are not defined.
// It will cause a build-break when we include <utils/Trace.h>. Use undef
// _LIBS_CUTILS_TRACE_H will force <cutils/trace.h> to define atrace_begin and
// atrace_end with defined HAVE_ANDROID_OS again. Then there is no build-break.
# undef _LIBS_CUTILS_TRACE_H
# include <utils/Trace.h>
# define PROFILER_PLATFORM_TRACING(name) \
android::ScopedTrace \
PROFILER_APPEND_LINE_NUMBER(scopedTrace)(ATRACE_TAG, name);
# ifdef REMOVE_HAVE_ANDROID_OS
# undef HAVE_ANDROID_OS
# undef REMOVE_HAVE_ANDROID_OS
# endif
#else
# define PROFILER_PLATFORM_TRACING(name)
#endif
// Similar to PROFILER_LABEL, PROFILER_LABEL_FUNC will push/pop the enclosing
// functon name as the pseudostack label.
#define PROFILER_LABEL_FUNC(category) do {} while (0)
// Enter a pseudo stack frame in this scope and associate it with an
// additional string.
// This macro generates an RAII object. This RAII object stores the dynamicStr
// pointer in a field; it does not copy the string. This means that the string
// you pass to this macro needs to live at least until the end of the current
// scope.
// If the profiler samples the current thread and walks the pseudo stack while
// this RAII object is on the stack, it will copy the supplied string into the
// profile buffer. So there's one string copy operation, and it happens at
// sample time.
// Compare this to the plain PROFILER_LABEL macro, which only accepts literal
// strings: When the pseudo stack frames generated by PROFILER_LABEL are
// sampled, no string copy needs to be made because the profile buffer can
// just store the raw pointers to the literal strings. Consequently,
// PROFILER_LABEL frames take up considerably less space in the profile buffer
// than PROFILER_LABEL_DYNAMIC frames.
#define PROFILER_LABEL_DYNAMIC(name_space, info, category, dynamicStr) \
do {} while (0)
// Insert a marker in the profile timeline. This is useful to delimit something
// important happening such as the first paint. Unlike profiler_label that are
// only recorded if a sample is collected while it is active, marker will always
// be collected.
#define PROFILER_MARKER(marker_name) do {} while (0)
// Like PROFILER_MARKER, but with an additional payload.
//
// Note: this is deliberately not defined when MOZ_GECKO_PROFILER is undefined.
// This macro should not be used in that case -- i.e. all uses of this macro
// should be guarded by a MOZ_GECKO_PROFILER check -- because payload creation
// requires allocation, which is something we should not do in builds that
// don't contain the profiler.
//#define PROFILER_MARKER_PAYLOAD(marker_name, payload) /* undefined */
#else // defined(MOZ_GECKO_PROFILER)
#define PROFILER_APPEND_LINE_NUMBER_PASTE(id, line) id ## line
#define PROFILER_APPEND_LINE_NUMBER_EXPAND(id, line) \
PROFILER_APPEND_LINE_NUMBER_PASTE(id, line)
#define PROFILER_APPEND_LINE_NUMBER(id) \
PROFILER_APPEND_LINE_NUMBER_EXPAND(id, __LINE__)
#if defined(__GNUC__) || defined(_MSC_VER)
# define PROFILER_FUNCTION_NAME __FUNCTION__
@ -122,34 +102,76 @@ using UniqueProfilerBacktrace =
# define PROFILER_FUNCTION_NAME __func__
#endif
#define PROFILER_FUNC(decl, rv) decl;
#define PROFILER_FUNC_VOID(decl) void decl;
// we want the class and function name but can't easily get that using preprocessor macros
// __func__ doesn't have the class name and __PRETTY_FUNCTION__ has the parameters
// Insert an RAII object in this scope to enter a pseudo stack frame. Any
// samples collected in this scope will contain this label in their pseudo
// stack. The name_space and info arguments must be string literals.
// Use PROFILER_LABEL_DYNAMIC if you want to add additional / dynamic
// information to the pseudo stack frame.
#define PROFILER_LABEL(name_space, info, category) \
PROFILER_PLATFORM_TRACING(name_space "::" info) \
mozilla::AutoProfilerLabel \
PROFILER_APPEND_LINE_NUMBER(profiler_raii)(name_space "::" info, nullptr, \
__LINE__, category)
// Similar to PROFILER_LABEL, PROFILER_LABEL_FUNC will push/pop the enclosing
// functon name as the pseudostack label.
#define PROFILER_LABEL_FUNC(category) \
PROFILER_PLATFORM_TRACING(PROFILER_FUNCTION_NAME) \
mozilla::AutoProfilerLabel \
PROFILER_APPEND_LINE_NUMBER(profiler_raii)(PROFILER_FUNCTION_NAME, nullptr, \
__LINE__, category)
// Similar to PROFILER_LABEL, but with an additional string. The inserted RAII
// object stores the dynamicStr pointer in a field; it does not copy the string.
// This means that the string you pass to this macro needs to live at least
// until the end of the current scope.
//
// If the profiler samples the current thread and walks the pseudo stack while
// this RAII object is on the stack, it will copy the supplied string into the
// profile buffer. So there's one string copy operation, and it happens at
// sample time.
//
// Compare this to the plain PROFILER_LABEL macro, which only accepts literal
// strings: When the pseudo stack frames generated by PROFILER_LABEL are
// sampled, no string copy needs to be made because the profile buffer can
// just store the raw pointers to the literal strings. Consequently,
// PROFILER_LABEL frames take up considerably less space in the profile buffer
// than PROFILER_LABEL_DYNAMIC frames.
#define PROFILER_LABEL_DYNAMIC(name_space, info, category, dynamicStr) \
PROFILER_PLATFORM_TRACING(name_space "::" info) \
mozilla::AutoProfilerLabel \
PROFILER_APPEND_LINE_NUMBER(profiler_raii)(name_space "::" info, dynamicStr, \
__LINE__, category)
// Insert a marker in the profile timeline. This is useful to delimit something
// important happening such as the first paint. Unlike labels, which are only
// recorded in the profile buffer if a sample is collected while the label is
// on the pseudostack, markers will always be recorded in the profile buffer.
#define PROFILER_MARKER(marker_name) profiler_add_marker(marker_name)
// Like PROFILER_MARKER, but with an additional payload.
#define PROFILER_MARKER_PAYLOAD(marker_name, payload) \
profiler_add_marker(marker_name, payload)
#else // defined(MOZ_GECKO_PROFILER)
#define PROFILER_FUNC(decl, rv) static inline decl { return rv; }
#define PROFILER_FUNC_VOID(decl) static inline void decl {}
#define PROFILER_LABEL(name_space, info, category) do {} while (0)
#define PROFILER_LABEL_FUNC(category) do {} while (0)
#define PROFILER_LABEL_DYNAMIC(name_space, info, category, dynamicStr) \
do {} while (0)
#define PROFILER_MARKER(marker_name) do {} while (0)
// Note: this is deliberately not defined when MOZ_GECKO_PROFILER is undefined.
// This macro should not be used in that case -- i.e. all uses of this macro
// should be guarded by a MOZ_GECKO_PROFILER check -- because payload creation
// requires allocation, which is something we should not do in builds that
// don't contain the profiler.
//#define PROFILER_MARKER_PAYLOAD(marker_name, payload) /* undefined */
#endif // defined(MOZ_GECKO_PROFILER)
// Higher-order macro containing all the feature info in one place. Define
@ -415,7 +437,6 @@ PROFILER_FUNC_VOID(profiler_suspend_and_sample_thread(int aThreadId,
# undef min
#endif
class nsISupports;
class ProfilerMarkerPayload;
// This exists purely for AutoProfilerLabel. See the comment on the
@ -428,44 +449,6 @@ void profiler_add_marker(const char* aMarkerName);
void profiler_add_marker(const char* aMarkerName,
mozilla::UniquePtr<ProfilerMarkerPayload> aPayload);
#define PROFILER_APPEND_LINE_NUMBER_PASTE(id, line) id ## line
#define PROFILER_APPEND_LINE_NUMBER_EXPAND(id, line) \
PROFILER_APPEND_LINE_NUMBER_PASTE(id, line)
#define PROFILER_APPEND_LINE_NUMBER(id) \
PROFILER_APPEND_LINE_NUMBER_EXPAND(id, __LINE__)
// Uncomment this to turn on systrace or build with
// ac_add_options --enable-systace
//#define MOZ_USE_SYSTRACE
#ifdef MOZ_USE_SYSTRACE
# ifndef ATRACE_TAG
# define ATRACE_TAG ATRACE_TAG_ALWAYS
# endif
// We need HAVE_ANDROID_OS to be defined for Trace.h.
// If its not set we will set it temporary and remove it.
# ifndef HAVE_ANDROID_OS
# define HAVE_ANDROID_OS
# define REMOVE_HAVE_ANDROID_OS
# endif
// Android source code will include <cutils/trace.h> before this. There is no
// HAVE_ANDROID_OS defined in Firefox OS build at that time. Enabled it globally
// will cause other build break. So atrace_begin and atrace_end are not defined.
// It will cause a build-break when we include <utils/Trace.h>. Use undef
// _LIBS_CUTILS_TRACE_H will force <cutils/trace.h> to define atrace_begin and
// atrace_end with defined HAVE_ANDROID_OS again. Then there is no build-break.
# undef _LIBS_CUTILS_TRACE_H
# include <utils/Trace.h>
# define PROFILER_PLATFORM_TRACING(name) \
android::ScopedTrace \
PROFILER_APPEND_LINE_NUMBER(scopedTrace)(ATRACE_TAG, name);
# ifdef REMOVE_HAVE_ANDROID_OS
# undef HAVE_ANDROID_OS
# undef REMOVE_HAVE_ANDROID_OS
# endif
#else
# define PROFILER_PLATFORM_TRACING(name)
#endif
#if !defined(ARCH_ARMV6)
# define PROFILER_DEFAULT_ENTRIES 1000000
#else

View File

@ -1,10 +1,11 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef PROFILER_MARKERS_H
#define PROFILER_MARKERS_H
#ifndef ProfilerMarkerPayload_h
#define ProfilerMarkerPayload_h
#include "mozilla/TimeStamp.h"
#include "mozilla/Attributes.h"
@ -25,18 +26,11 @@ class Layer;
class SpliceableJSONWriter;
class UniqueStacks;
/**
* This is an abstract object that can be implied to supply
* data to be attached with a profiler marker. Most data inserted
* into a profile is stored in a circular buffer. This buffer
* typically wraps around and overwrites most entries. Because
* of this, this structure is designed to defer the work of
* prepare the payload only when 'preparePayload' is called.
*
* Note when implementing that this object is typically constructed
* on a particular thread but 'preparePayload' and the destructor
* is called from the main thread.
*/
// This is an abstract class that can be implemented to supply data to be
// attached with a profiler marker.
//
// When subclassing this, note that the destructor can be called on any thread,
// i.e. not necessarily on the thread that created the object.
class ProfilerMarkerPayload
{
public:
@ -45,14 +39,8 @@ public:
const mozilla::TimeStamp& aEndTime,
UniqueProfilerBacktrace aStack = nullptr);
/**
* Called from the main thread
*/
virtual ~ProfilerMarkerPayload();
/**
* Called from the main thread
*/
virtual void StreamPayload(SpliceableJSONWriter& aWriter,
const mozilla::TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) = 0;
@ -60,28 +48,28 @@ public:
mozilla::TimeStamp GetStartTime() const { return mStartTime; }
protected:
/**
* Called from the main thread
*/
void streamCommonProps(const char* aMarkerType,
void StreamCommonProps(const char* aMarkerType,
SpliceableJSONWriter& aWriter,
const mozilla::TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks);
void SetStack(UniqueProfilerBacktrace aStack) { mStack = mozilla::Move(aStack); }
void SetStack(UniqueProfilerBacktrace aStack)
{
mStack = mozilla::Move(aStack);
}
private:
mozilla::TimeStamp mStartTime;
mozilla::TimeStamp mEndTime;
UniqueProfilerBacktrace mStack;
mozilla::TimeStamp mStartTime;
mozilla::TimeStamp mEndTime;
UniqueProfilerBacktrace mStack;
};
class ProfilerMarkerTracing : public ProfilerMarkerPayload
class TracingMarkerPayload : public ProfilerMarkerPayload
{
public:
ProfilerMarkerTracing(const char* aCategory, TracingKind aKind);
ProfilerMarkerTracing(const char* aCategory, TracingKind aKind,
UniqueProfilerBacktrace aCause);
TracingMarkerPayload(const char* aCategory, TracingKind aKind);
TracingMarkerPayload(const char* aCategory, TracingKind aKind,
UniqueProfilerBacktrace aCause);
const char *GetCategory() const { return mCategory; }
TracingKind GetKind() const { return mKind; }
@ -95,19 +83,6 @@ private:
TracingKind mKind;
};
class ProfilerMarkerImagePayload : public ProfilerMarkerPayload
{
public:
explicit ProfilerMarkerImagePayload(gfxASurface *aImg);
virtual void StreamPayload(SpliceableJSONWriter& aWriter,
const mozilla::TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) override;
private:
RefPtr<gfxASurface> mImg;
};
class IOMarkerPayload : public ProfilerMarkerPayload
{
public:
@ -163,14 +138,12 @@ private:
nsString mName;
};
/**
* Contains the translation applied to a 2d layer so we can
* track the layer position at each frame.
*/
class LayerTranslationPayload : public ProfilerMarkerPayload
// Contains the translation applied to a 2d layer so we can track the layer
// position at each frame.
class LayerTranslationMarkerPayload : public ProfilerMarkerPayload
{
public:
LayerTranslationPayload(mozilla::layers::Layer* aLayer,
LayerTranslationMarkerPayload(mozilla::layers::Layer* aLayer,
mozilla::gfx::Point aPoint);
virtual void StreamPayload(SpliceableJSONWriter& aWriter,
@ -184,32 +157,12 @@ private:
#include "Units.h" // For ScreenIntPoint
/**
* Tracks when touch events are processed by gecko, not when
* the touch actually occured in gonk/android.
*/
class TouchDataPayload : public ProfilerMarkerPayload
// Tracks when a vsync occurs according to the HardwareComposer.
class VsyncMarkerPayload : public ProfilerMarkerPayload
{
public:
explicit TouchDataPayload(const mozilla::ScreenIntPoint& aPoint);
virtual ~TouchDataPayload() {}
virtual void StreamPayload(SpliceableJSONWriter& aWriter,
const mozilla::TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) override;
private:
mozilla::ScreenIntPoint mPoint;
};
/**
* Tracks when a vsync occurs according to the HardwareComposer.
*/
class VsyncPayload : public ProfilerMarkerPayload
{
public:
explicit VsyncPayload(mozilla::TimeStamp aVsyncTimestamp);
virtual ~VsyncPayload() {}
explicit VsyncMarkerPayload(mozilla::TimeStamp aVsyncTimestamp);
virtual ~VsyncMarkerPayload() {}
virtual void StreamPayload(SpliceableJSONWriter& aWriter,
const mozilla::TimeStamp& aProcessStartTime,
@ -299,5 +252,4 @@ private:
JS::UniqueChars mTimingData;
};
#endif // PROFILER_MARKERS_H
#endif // ProfilerMarkerPayload_h

View File

@ -10,6 +10,8 @@
#include "mozilla/RefPtr.h"
#include "mozilla/PProfilerParent.h"
class nsIProfilerStartParams;
namespace mozilla {
class ProfilerParentTracker;

View File

@ -322,22 +322,22 @@ TEST(GeckoProfiler, Pause)
// A class that keeps track of how many instances have been created, streamed,
// and destroyed.
class GTestPayload : public ProfilerMarkerPayload
class GTestMarkerPayload : public ProfilerMarkerPayload
{
public:
explicit GTestPayload(int aN)
explicit GTestMarkerPayload(int aN)
: mN(aN)
{
sNumCreated++;
}
virtual ~GTestPayload() { sNumDestroyed++; }
virtual ~GTestMarkerPayload() { sNumDestroyed++; }
virtual void StreamPayload(SpliceableJSONWriter& aWriter,
const mozilla::TimeStamp& aStartTime,
UniqueStacks& aUniqueStacks) override
{
streamCommonProps("gtest", aWriter, aStartTime, aUniqueStacks);
StreamCommonProps("gtest", aWriter, aStartTime, aUniqueStacks);
char buf[64];
SprintfLiteral(buf, "gtest-%d", mN);
aWriter.IntProperty(buf, mN);
@ -348,16 +348,16 @@ private:
int mN;
public:
// The number of GTestPayload instances that have been created, streamed, and
// destroyed.
// The number of GTestMarkerPayload instances that have been created,
// streamed, and destroyed.
static int sNumCreated;
static int sNumStreamed;
static int sNumDestroyed;
};
int GTestPayload::sNumCreated = 0;
int GTestPayload::sNumStreamed = 0;
int GTestPayload::sNumDestroyed = 0;
int GTestMarkerPayload::sNumCreated = 0;
int GTestMarkerPayload::sNumStreamed = 0;
int GTestMarkerPayload::sNumDestroyed = 0;
TEST(GeckoProfiler, Markers)
{
@ -382,15 +382,15 @@ TEST(GeckoProfiler, Markers)
profiler_add_marker("M1");
profiler_add_marker("M2",
MakeUnique<ProfilerMarkerTracing>("C", TRACING_EVENT));
MakeUnique<TracingMarkerPayload>("C", TRACING_EVENT));
PROFILER_MARKER("M3");
PROFILER_MARKER_PAYLOAD(
"M4",
MakeUnique<ProfilerMarkerTracing>("C", TRACING_EVENT,
profiler_get_backtrace()));
MakeUnique<TracingMarkerPayload>("C", TRACING_EVENT,
profiler_get_backtrace()));
for (int i = 0; i < 10; i++) {
PROFILER_MARKER_PAYLOAD("M5", MakeUnique<GTestPayload>(i));
PROFILER_MARKER_PAYLOAD("M5", MakeUnique<GTestMarkerPayload>(i));
}
// Sleep briefly to ensure a sample is taken and the pending markers are
@ -402,11 +402,11 @@ TEST(GeckoProfiler, Markers)
UniquePtr<char[]> profile = w.WriteFunc()->CopyData();
// The GTestPayloads should have been created and streamed, but not yet
// The GTestMarkerPayloads should have been created and streamed, but not yet
// destroyed.
ASSERT_TRUE(GTestPayload::sNumCreated == 10);
ASSERT_TRUE(GTestPayload::sNumStreamed == 10);
ASSERT_TRUE(GTestPayload::sNumDestroyed == 0);
ASSERT_TRUE(GTestMarkerPayload::sNumCreated == 10);
ASSERT_TRUE(GTestMarkerPayload::sNumStreamed == 10);
ASSERT_TRUE(GTestMarkerPayload::sNumDestroyed == 0);
for (int i = 0; i < 10; i++) {
char buf[64];
SprintfLiteral(buf, "\"gtest-%d\"", i);
@ -415,11 +415,11 @@ TEST(GeckoProfiler, Markers)
profiler_stop();
// The GTestPayloads should have been destroyed.
ASSERT_TRUE(GTestPayload::sNumDestroyed == 10);
// The GTestMarkerPayloads should have been destroyed.
ASSERT_TRUE(GTestMarkerPayload::sNumDestroyed == 10);
for (int i = 0; i < 10; i++) {
PROFILER_MARKER_PAYLOAD("M5", MakeUnique<GTestPayload>(i));
PROFILER_MARKER_PAYLOAD("M5", MakeUnique<GTestMarkerPayload>(i));
}
profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL,
@ -429,10 +429,10 @@ TEST(GeckoProfiler, Markers)
profiler_stop();
// The second set of GTestPayloads should not have been streamed.
ASSERT_TRUE(GTestPayload::sNumCreated == 20);
ASSERT_TRUE(GTestPayload::sNumStreamed == 10);
ASSERT_TRUE(GTestPayload::sNumDestroyed == 20);
// The second set of GTestMarkerPayloads should not have been streamed.
ASSERT_TRUE(GTestMarkerPayload::sNumCreated == 20);
ASSERT_TRUE(GTestMarkerPayload::sNumStreamed == 10);
ASSERT_TRUE(GTestMarkerPayload::sNumDestroyed == 20);
}
TEST(GeckoProfiler, Time)

View File

@ -93,6 +93,18 @@ public:
// @return True if the array is empty or false otherwise.
bool IsEmpty() const { return mArray.IsEmpty(); }
// This method provides direct, readonly access to the array elements.
// @return A pointer to the first element of the array. If the array is
// empty, then this pointer must not be dereferenced.
const elem_type* Elements() const
{
return mArray.Elements();
}
elem_type* Elements()
{
return mArray.Elements();
}
// This method provides direct access to an element of the array. The given
// index must be within the array bounds. If the underlying array may change
// during iteration, use an iterator instead of this function.
@ -251,7 +263,8 @@ public:
}
// See nsTArray::RemoveElementsBy.
void RemoveElementsBy(const std::function<bool(const elem_type&)>& aPredicate)
template <typename Predicate>
void RemoveElementsBy(Predicate aPredicate)
{
index_type i = 0;
mArray.RemoveElementsBy([&](const elem_type& aItem) {
@ -361,7 +374,7 @@ public:
elem_type& GetNext()
{
NS_ASSERTION(HasMore(), "iterating beyond end of array");
return base_type::mArray.ElementAt(base_type::mPosition++);
return base_type::mArray.Elements()[base_type::mPosition++];
}
};
@ -390,7 +403,7 @@ public:
elem_type& GetNext()
{
NS_ASSERTION(HasMore(), "iterating beyond end of array");
return base_type::mArray.ElementAt(base_type::mPosition++);
return base_type::mArray.Elements()[base_type::mPosition++];
}
private:
@ -426,7 +439,7 @@ public:
elem_type& GetNext()
{
NS_ASSERTION(HasMore(), "iterating beyond start of array");
return base_type::mArray.ElementAt(--base_type::mPosition);
return base_type::mArray.Elements()[--base_type::mPosition];
}
// Removes the element at the current iterator position.