diff --git a/browser/components/extensions/parent/ext-tabs.js b/browser/components/extensions/parent/ext-tabs.js index 8795af3a14558..b62322ebe40c8 100644 --- a/browser/components/extensions/parent/ext-tabs.js +++ b/browser/components/extensions/parent/ext-tabs.js @@ -1163,7 +1163,6 @@ this.tabs = class extends ExtensionAPI { printSettings.printSilent = true; printSettings.showPrintProgress = false; - printSettings.printFrameType = Ci.nsIPrintSettings.kFramesAsIs; printSettings.outputFormat = Ci.nsIPrintSettings.kOutputFormatPDF; if (pageSettings.paperSizeUnit !== null) { diff --git a/devtools/client/inspector/grids/grid-inspector.js b/devtools/client/inspector/grids/grid-inspector.js index d0a5d480063f1..87bb066b01f84 100644 --- a/devtools/client/inspector/grids/grid-inspector.js +++ b/devtools/client/inspector/grids/grid-inspector.js @@ -346,6 +346,10 @@ class GridInspector { return; } + if (!parentGridNodeFront) { + return; + } + const parentIndex = grids.findIndex(g => g.nodeFront.actorID === parentGridNodeFront.actorID); gridData.parentNodeActorID = parentGridNodeFront.actorID; @@ -504,10 +508,18 @@ class GridInspector { customGridColors[hostname][grid.id] = color; await asyncStorage.setItem("gridInspectorHostColors", customGridColors); + if (!this.isPanelVisible()) { + // This call might fail if called asynchrously after the toolbox is finished + // closing. + return; + } + // If the grid for which the color was updated currently has a highlighter, update // the color. - if (grid.highlighted) { + if (this.highlighters.gridHighlighters.has(node)) { this.highlighters.showGridHighlighter(node); + } else if (this.highlighters.parentGridHighlighters.has(node)) { + this.highlighters.showParentGridHighlighter(node); } } } diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-list-subgrids.js b/devtools/client/inspector/grids/test/browser_grids_grid-list-subgrids.js index e420f687d3ec7..6707b100a02b1 100644 --- a/devtools/client/inspector/grids/test/browser_grids_grid-list-subgrids.js +++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-subgrids.js @@ -25,28 +25,62 @@ add_task(async function() { "Got the correct number of subgrids in div.container"); is(getGridItemElements(mainSubgridListEl).length, 2, "Got the correct number of subgrids in main.subgrid"); - ok(!highlighters.gridHighlighters.size, "No CSS grid highlighter is shown."); + ok(!highlighters.gridHighlighters.size && !highlighters.parentGridHighlighters.size, + "No CSS grid highlighter is shown."); - info("Toggling ON the CSS grid highlighter from the layout panel."); - const onHighlighterShown = highlighters.once("grid-highlighter-shown"); + info("Toggling ON the CSS grid highlighter for header."); + let onHighlighterShown = highlighters.once("grid-highlighter-shown"); let onCheckboxChange = waitUntilState(store, state => state.grids[1].highlighted); - const checkbox = containerSubgridListEl.children[0].querySelector("input"); + let checkbox = containerSubgridListEl.children[0].querySelector("input"); checkbox.click(); await onHighlighterShown; await onCheckboxChange; - info("Checking the CSS grid highlighter is created."); + info("Checking the CSS grid highlighter and parent grid highlighter are created."); is(highlighters.gridHighlighters.size, 1, "CSS grid highlighter is shown."); + is(highlighters.parentGridHighlighters.size, 1, + "CSS grid highlighter for parent grid container is shown."); - info("Toggling OFF the CSS grid highlighter from the layout panel."); - const onHighlighterHidden = highlighters.once("grid-highlighter-hidden"); + info("Toggling ON the CSS grid highlighter for main."); + onHighlighterShown = highlighters.once("grid-highlighter-shown"); + onCheckboxChange = waitUntilState(store, state => + state.grids[1].highlighted && state.grids[2].highlighted); + checkbox = containerSubgridListEl.children[1].querySelector("input"); + checkbox.click(); + await onHighlighterShown; + await onCheckboxChange; + + info("Checking the number of CSS grid highlighters present."); + is(highlighters.gridHighlighters.size, 2, + "Got the correct number of CSS grid highlighter shown."); + is(highlighters.parentGridHighlighters.size, 1, + "Only 1 parent grid highlighter should be shown for the same subgrid parent."); + + info("Toggling OFF the CSS grid highlighter for main."); + let onHighlighterHidden = highlighters.once("grid-highlighter-hidden"); + onCheckboxChange = waitUntilState(store, state => + state.grids[1].highlighted && !state.grids[2].highlighted); + checkbox.click(); + await onHighlighterHidden; + await onCheckboxChange; + + info("Checking the number of CSS grid highlighters present."); + is(highlighters.gridHighlighters.size, 1, + "Got the correct number of CSS grid highlighter shown."); + is(highlighters.parentGridHighlighters.size, 1, + "Got the correct number of CSS grid parent highlighter shown."); + + info("Toggling OFF the CSS grid highlighter for header."); + onHighlighterHidden = highlighters.once("grid-highlighter-hidden"); onCheckboxChange = waitUntilState(store, state => !state.grids[1].highlighted); + checkbox = containerSubgridListEl.children[0].querySelector("input"); checkbox.click(); await onHighlighterHidden; await onCheckboxChange; info("Checking the CSS grid highlighter is not shown."); - ok(!highlighters.gridHighlighters.size, "No CSS grid highlighter is shown."); + ok(!highlighters.gridHighlighters.size && !highlighters.parentGridHighlighters.size, + "No CSS grid highlighter is shown."); }); /** diff --git a/devtools/client/inspector/markup/views/text-editor.js b/devtools/client/inspector/markup/views/text-editor.js index ff65098e47253..c6d49bc475689 100644 --- a/devtools/client/inspector/markup/views/text-editor.js +++ b/devtools/client/inspector/markup/views/text-editor.js @@ -32,7 +32,6 @@ function TextEditor(container, node, type) { this.showTextEditor = this.showTextEditor.bind(this); this.buildMarkup(type); - this.update(); } TextEditor.prototype = { @@ -42,11 +41,13 @@ TextEditor.prototype = { this.elt = doc.createElement("span"); this.elt.classList.add("editor", type); - this.textNode = this.ReactDOM.render(TextNode({ - showTextEditor: this.showTextEditor, - type, - value: "", - }), this.elt); + getLongString(this.node.getNodeValue()).then(value => { + this.textNode = this.ReactDOM.render(TextNode({ + showTextEditor: this.showTextEditor, + type, + value, + }), this.elt); + }); }, get ReactDOM() { diff --git a/devtools/client/inspector/shared/highlighters-overlay.js b/devtools/client/inspector/shared/highlighters-overlay.js index 283b74a124c90..7177e1426f0d6 100644 --- a/devtools/client/inspector/shared/highlighters-overlay.js +++ b/devtools/client/inspector/shared/highlighters-overlay.js @@ -17,6 +17,7 @@ loader.lazyRequireGetter(this, "parseURL", "devtools/client/shared/source-utils" loader.lazyRequireGetter(this, "asyncStorage", "devtools/shared/async-storage"); const DEFAULT_HIGHLIGHTER_COLOR = "#9400FF"; +const SUBGRID_PARENT_ALPHA = 0.5; /** * Highlighters overlay is a singleton managing all highlighters in the Inspector. @@ -30,7 +31,9 @@ class HighlightersOverlay { this.inspector = inspector; this.inspectorFront = this.inspector.inspector; this.store = this.inspector.store; - this.telemetry = inspector.telemetry; + this.target = this.inspector.target; + this.telemetry = this.inspector.telemetry; + this.walker = this.inspector.walker; this.maxGridHighlighters = Services.prefs.getIntPref("devtools.gridinspector.maxHighlighters"); @@ -39,10 +42,16 @@ class HighlightersOverlay { this.highlighters = {}; // Map of grid container NodeFront to their instantiated grid highlighter actors. this.gridHighlighters = new Map(); + // Map of parent grid container NodeFront to their instantiated grid highlighter + // actors. + this.parentGridHighlighters = new Map(); // Array of reusable grid highlighters that have been instantiated and are not // associated with any NodeFront. this.extraGridHighlighterPool = []; + // Map of grid container NodeFront to their parent grid container. + this.subgridToParentMap = new Map(); + // Boolean flag to keep track of whether or not the telemetry timer for the grid // highlighter active time is active. We keep track of this to avoid re-starting a // new timer when an additional grid highlighter is turned on. @@ -94,12 +103,21 @@ class HighlightersOverlay { // Add inspector events, not specific to a given view. this.inspector.on("markupmutation", this.onMarkupMutation); - this.inspector.walker.on("display-change", this.onDisplayChange); - this.inspector.target.on("will-navigate", this.onWillNavigate); + this.target.on("will-navigate", this.onWillNavigate); + this.walker.on("display-change", this.onDisplayChange); EventEmitter.decorate(this); } + async canGetParentGridNode() { + if (this._canGetParentGridNode === undefined) { + this._canGetParentGridNode = await this.target.actorHasMethod("domwalker", + "getParentGridNode"); + } + + return this._canGetParentGridNode; + } + /** * Returns true if the grid highlighter can be toggled on/off for the given node, and * false otherwise. A grid container can be toggled on if the max grid highlighters @@ -274,8 +292,8 @@ class HighlightersOverlay { // ex: `data:` uri, and `about:` pages let hostname; try { - hostname = parseURL(this.inspector.target.url).hostname || - parseURL(this.inspector.target.url).protocol; + hostname = parseURL(this.target.url).hostname || + parseURL(this.target.url).protocol; } catch (e) { this._handleRejection(e); } @@ -353,7 +371,7 @@ class HighlightersOverlay { try { // Save flexbox highlighter state. - const { url } = this.inspector.target; + const { url } = this.target; const selector = await node.getUniqueSelector(); this.state.flexbox = { selector, options, url }; this.flexboxHighlighterShown = node; @@ -487,7 +505,7 @@ class HighlightersOverlay { * The NodeFront of the grid container element to highlight. * @param {Object} options * Object used for passing options to the grid highlighter. - * @param. {String} trigger + * @param {String} trigger * String name matching "grid", "markup" or "rule" to indicate where the * grid highlighter was toggled on from. "grid" represents the grid view. * "markup" represents the markup view. "rule" represents the rule view. @@ -507,6 +525,18 @@ class HighlightersOverlay { // any additional grid highlighters. return; } + } else if (this.parentGridHighlighters.has(node)) { + // A translucent parent grid container is being highlighted, hide the translucent + // highlight of the parent grid container. + await this.hideGridHighlighter(node); + } + + if (node.displayType === "subgrid" && await this.canGetParentGridNode()) { + // Show a translucent highlight of the parent grid container if the given node is + // a subgrid. + const parentGridNode = await this.walker.getParentGridNode(node); + this.subgridToParentMap.set(node, parentGridNode); + await this.showParentGridHighlighter(parentGridNode); } const highlighter = await this._getGridHighlighter(node); @@ -539,7 +569,7 @@ class HighlightersOverlay { try { // Save grid highlighter state. - const { url } = this.inspector.target; + const { url } = this.target; const selector = await node.getUniqueSelector(); this.state.grids.set(node, { selector, options, url }); @@ -551,6 +581,24 @@ class HighlightersOverlay { } } + /** + * Show the grid highlighter for the given parent grid container element. + * + * @param {NodeFront} node + * The NodeFront of the parent grid container element to highlight. + */ + async showParentGridHighlighter(node) { + const highlighter = await this._getGridHighlighter(node, true); + if (!highlighter) { + return; + } + + await highlighter.show(node, { + ...this.getGridHighlighterSettings(node), + globalAlpha: SUBGRID_PARENT_ALPHA, + }); + } + /** * Hide the grid highlighter for the given grid container element. * @@ -558,18 +606,29 @@ class HighlightersOverlay { * The NodeFront of the grid container element to unhighlight. */ async hideGridHighlighter(node) { - if (!this.gridHighlighters.has(node)) { + let highlighter; + + if (this.gridHighlighters.has(node)) { + highlighter = this.gridHighlighters.get(node); + this.gridHighlighters.delete(node); + } else if (this.parentGridHighlighters.has(node)) { + highlighter = this.parentGridHighlighters.get(node); + this.parentGridHighlighters.delete(node); + } else { return; } // Hide the highlighter and put it in the pool of extra grid highlighters // so that it can be reused. - const highlighter = this.gridHighlighters.get(node); await highlighter.hide(); this.extraGridHighlighterPool.push(highlighter); - this.state.grids.delete(node); - this.gridHighlighters.delete(node); + + if (this.subgridToParentMap.has(node)) { + const parentGridNode = this.subgridToParentMap.get(node); + this.subgridToParentMap.delete(node); + await this.hideParentGridHighlighter(parentGridNode); + } this._toggleRuleViewIcon(node, false, ".ruleview-grid"); @@ -584,6 +643,30 @@ class HighlightersOverlay { this.emit("grid-highlighter-hidden", node); } + /** + * Hide the parent grid highlighter for the given parent grid container element. + * + * @param {NodeFront} node + * The NodeFront of the parent grid container element to unhiglight. + */ + async hideParentGridHighlighter(node) { + // Before hiding the parent grid highlighter, check if there are any other subgrids + // highlighted with the same parent grid container. + for (const parentGridNode of this.subgridToParentMap.values()) { + if (parentGridNode === node) { + // Don't hide the parent grid highlighter if another subgrid is highlighted + // with the given parent node. + return; + } + } + + const highlighter = this.parentGridHighlighters.get(node); + await highlighter.hide(); + this.extraGridHighlighterPool.push(highlighter); + this.state.grids.delete(node); + this.parentGridHighlighters.delete(node); + } + /** * Show the box model highlighter for the given node. * @@ -719,15 +802,14 @@ class HighlightersOverlay { async restoreState(name, state, showFunction) { const { selector, options, url } = state; - if (!selector || url !== this.inspector.target.url) { + if (!selector || url !== this.target.url) { // Bail out if no selector was saved, or if we are on a different page. this.emit(`${name}-state-restored`, { restored: false }); return; } - const walker = this.inspector.walker; - const rootNode = await walker.getRootNode(); - const nodeFront = await walker.querySelector(rootNode, selector); + const rootNode = await this.walker.getRootNode(); + const nodeFront = await this.walker.querySelector(rootNode, selector); if (nodeFront) { if (options.hoverPoint) { @@ -814,10 +896,14 @@ class HighlightersOverlay { * * @param {NodeFront} node * The NodeFront of the grid container element to highlight. + * @param {Boolean} isParent + * Whether or not the given node is a parent grid container element. * @return {Promise} that resolves to the grid highlighter front. */ - async _getGridHighlighter(node) { - if (this.gridHighlighters.has(node)) { + async _getGridHighlighter(node, isParent) { + if (isParent && this.parentGridHighlighters.has(node)) { + return this.parentGridHighlighters.get(node); + } else if (this.gridHighlighters.has(node)) { return this.gridHighlighters.get(node); } @@ -840,7 +926,12 @@ class HighlightersOverlay { return null; } - this.gridHighlighters.set(node, highlighter); + if (isParent) { + this.parentGridHighlighters.set(node, highlighter); + } else { + this.gridHighlighters.set(node, highlighter); + } + return highlighter; } @@ -938,7 +1029,7 @@ class HighlightersOverlay { } try { - const isInTree = await this.inspector.walker.isInDOMTree(node); + const isInTree = await this.walker.isInDOMTree(node); if (!isInTree) { hideHighlighter(node); } @@ -1079,7 +1170,13 @@ class HighlightersOverlay { // Hide the grid highlighter if the node is no longer a grid container. if (display !== "grid" && display !== "inline-grid" && - this.gridHighlighters.has(node)) { + (this.gridHighlighters.has(node) || this.parentGridHighlighters.has(node))) { + await this.hideGridHighlighter(node); + return; + } + + // Hide the grid highlighter if the node is no longer a subgrid. + if (display !== "subgrid" && this.gridHighlighters.has(node)) { await this.hideGridHighlighter(node); return; } @@ -1166,6 +1263,10 @@ class HighlightersOverlay { await this._hideHighlighterIfDeadNode(node, this.hideGridHighlighter); } + for (const node of this.parentGridHighlighters.keys()) { + await this._hideHighlighterIfDeadNode(node, this.hideGridHighlighter); + } + await this._hideHighlighterIfDeadNode(this.flexboxHighlighterShown, this.hideFlexboxHighlighter); await this._hideHighlighterIfDeadNode(this.flexItemHighlighterShown, @@ -1186,7 +1287,13 @@ class HighlightersOverlay { this.extraGridHighlighterPool.push(highlighter); } + for (const highlighter of this.parentGridHighlighters.values()) { + this.extraGridHighlighterPool.push(highlighter); + } + this.gridHighlighters.clear(); + this.parentGridHighlighters.clear(); + this.subgridToParentMap.clear(); this.boxModelHighlighterShown = null; this.flexboxHighlighterShown = null; @@ -1218,13 +1325,19 @@ class HighlightersOverlay { highlighter.finalize(); } + for (const highlighter of this.parentGridHighlighters.values()) { + highlighter.finalize(); + } + for (const highlighter of this.extraGridHighlighterPool) { highlighter.finalize(); } this.gridHighlighters.clear(); + this.parentGridHighlighters.clear(); this.gridHighlighters = null; + this.parentGridHighlighters = null; this.extraGridHighlighterPool = null; } @@ -1248,18 +1361,26 @@ class HighlightersOverlay { */ destroy() { this.inspector.off("markupmutation", this.onMarkupMutation); - this.inspector.target.off("will-navigate", this.onWillNavigate); + this.target.off("will-navigate", this.onWillNavigate); + this.walker.off("display-change", this.onDisplayChange); this.destroyEditors(); this.destroyGridHighlighters(); this.destroyHighlighters(); + this.subgridToParentMap.clear(); + + this._canGetParentGridNode = null; this._lastHovered = null; this.inspector = null; this.inspectorFront = null; this.state = null; this.store = null; + this.subgridToParentMap = null; + this.target = null; + this.telemetry = null; + this.walker = null; this.boxModelHighlighterShown = null; this.flexboxHighlighterShown = null; diff --git a/devtools/server/actors/errordocs.js b/devtools/server/actors/errordocs.js index 88d9cc5325243..deb2542acff39 100644 --- a/devtools/server/actors/errordocs.js +++ b/devtools/server/actors/errordocs.js @@ -90,6 +90,7 @@ const ErrorDocs = { JSMSG_PROPERTY_FAIL: "cant_access_property", JSMSG_PROPERTY_FAIL_EXPR: "cant_access_property", JSMSG_REDECLARED_VAR: "Redeclared_parameter", + JSMSG_SET_NON_OBJECT_RECEIVER: "Cant_assign_to_property", }; const MIXED_CONTENT_LEARN_MORE = "https://developer.mozilla.org/docs/Web/Security/Mixed_content"; diff --git a/devtools/server/actors/highlighters/css-grid.js b/devtools/server/actors/highlighters/css-grid.js index 8411f4de8672c..3be3104bc5e9d 100644 --- a/devtools/server/actors/highlighters/css-grid.js +++ b/devtools/server/actors/highlighters/css-grid.js @@ -136,6 +136,9 @@ const gCachedGridPattern = new Map(); * * @param {String} options.color * The color that should be used to draw the highlighter for this grid. + * @param {Number} options.globalAlpha + * The alpha (transparency) value that should be used to draw the highlighter for + * this grid. * @param {Boolean} options.showAllGridAreas * Shows all the grid area highlights for the current grid if isShown is * true. @@ -494,6 +497,10 @@ class CssGridHighlighter extends AutoRefreshHighlighter { return this.canvas.getCanvasContext("2d"); } + get globalAlpha() { + return this.options.globalAlpha || 1; + } + getElement(id) { return this.markup.getElement(this.ID_CLASS_PREFIX + id); } @@ -550,7 +557,7 @@ class CssGridHighlighter extends AutoRefreshHighlighter { } ctx.strokeStyle = this.color; - ctx.globalAlpha = GRID_GAP_ALPHA; + ctx.globalAlpha = GRID_GAP_ALPHA * this.globalAlpha; ctx.stroke(); ctx.restore(); @@ -880,6 +887,7 @@ class CssGridHighlighter extends AutoRefreshHighlighter { this.ctx.save(); this.ctx.translate(offset - canvasX, offset - canvasY); this.ctx.font = fontSize + "px " + GRID_FONT_FAMILY; + this.ctx.globalAlpha = this.globalAlpha; this.ctx.strokeStyle = this.color; this.ctx.textAlign = "center"; this.ctx.textBaseline = "middle"; @@ -1210,6 +1218,7 @@ class CssGridHighlighter extends AutoRefreshHighlighter { this.ctx.lineWidth = 2 * displayPixelRatio; this.ctx.strokeStyle = this.color; this.ctx.fillStyle = "white"; + this.ctx.globalAlpha = this.globalAlpha; // See param definitions of drawBubbleRect. const radius = 2 * displayPixelRatio; @@ -1449,7 +1458,7 @@ class CssGridHighlighter extends AutoRefreshHighlighter { } this.ctx.strokeStyle = this.color; - this.ctx.globalAlpha = GRID_LINES_PROPERTIES[lineType].alpha; + this.ctx.globalAlpha = GRID_LINES_PROPERTIES[lineType].alpha * this.globalAlpha; if (GRID_LINES_PROPERTIES[lineType].lineWidth) { this.ctx.lineWidth = GRID_LINES_PROPERTIES[lineType].lineWidth * devicePixelRatio; diff --git a/devtools/server/actors/object/property-iterator.js b/devtools/server/actors/object/property-iterator.js index 195a602a71c54..c4e805be9df16 100644 --- a/devtools/server/actors/object/property-iterator.js +++ b/devtools/server/actors/object/property-iterator.js @@ -109,13 +109,19 @@ const PropertyIteratorActor = protocol.ActorClassWithSpec(propertyIteratorSpec, }, }); +function waiveXrays(obj) { + return isWorker ? obj : Cu.waiveXrays(obj); +} + +function unwaiveXrays(obj) { + return isWorker ? obj : Cu.unwaiveXrays(obj); +} + /** * Helper function to create a grip from a Map/Set entry */ function gripFromEntry({ obj, hooks }, entry) { - if (!isWorker) { - entry = Cu.unwaiveXrays(entry); - } + entry = unwaiveXrays(entry); return hooks.createValueGrip( ObjectUtils.makeDebuggeeValueIfNeeded(obj, entry)); } @@ -253,22 +259,12 @@ function enumMapEntries(objectActor) { // Even then though, we might want to continue waiving Xrays here for the // same reason we do so for Arrays above - this filtering behavior is likely // to be more confusing than beneficial in the case of Object previews. - let keys, getValue; - if (isWorker) { - const keysIterator = DevToolsUtils.callPropertyOnObject(objectActor.obj, "keys"); - keys = [...DevToolsUtils.makeDebuggeeIterator(keysIterator)]; - const valuesIterator = DevToolsUtils.callPropertyOnObject(objectActor.obj, "values"); - const values = [...DevToolsUtils.makeDebuggeeIterator(valuesIterator)]; - const map = new Map(); - for (let i = 0; i < keys.length; i++) { - map.set(keys[i], values[i]); - } - getValue = key => map.get(key); - } else { - const raw = objectActor.obj.unsafeDereference(); - keys = [...Cu.waiveXrays(Map.prototype.keys.call(raw))]; - getValue = key => Map.prototype.get.call(raw, key); - } + const raw = objectActor.obj.unsafeDereference(); + const iterator = + objectActor.obj.makeDebuggeeValue(waiveXrays(Map.prototype.keys.call(raw))); + const keys = [...DevToolsUtils.makeDebuggeeIterator(iterator)]; + const getValue = + key => Map.prototype.get.call(raw, ObjectUtils.unwrapDebuggeeValue(key)); return { [Symbol.iterator]: function* () { @@ -348,20 +344,11 @@ function enumWeakMapEntries(objectActor) { // waive Xrays on the iterable, and relying on the Debugger machinery to // make sure we handle the resulting objects carefully. const raw = objectActor.obj.unsafeDereference(); - const basekeys = ChromeUtils.nondeterministicGetWeakMapKeys(raw); - const keys = isWorker ? basekeys : Cu.waiveXrays(basekeys); + const keys = waiveXrays(ChromeUtils.nondeterministicGetWeakMapKeys(raw)); const values = []; - if (isWorker) { - for (const k of keys) { - const nk = ObjectUtils.makeDebuggeeValueIfNeeded(objectActor.obj, k); - const v = DevToolsUtils.callPropertyOnObject(objectActor.obj, "get", nk); - values.push(ObjectUtils.unwrapDebuggeeValue(v)); - } - } else { - for (const k of keys) { - values.push(WeakMap.prototype.get.call(raw, k)); - } + for (const k of keys) { + values.push(WeakMap.prototype.get.call(raw, k)); } return { @@ -402,14 +389,10 @@ function enumSetEntries(objectActor) { // This code is designed to handle untrusted objects, so we can safely // waive Xrays on the iterable, and relying on the Debugger machinery to // make sure we handle the resulting objects carefully. - let values; - if (isWorker) { - const iterator = DevToolsUtils.callPropertyOnObject(objectActor.obj, "values"); - values = [...DevToolsUtils.makeDebuggeeIterator(iterator)]; - } else { - const raw = objectActor.obj.unsafeDereference(); - values = [...Cu.waiveXrays(Set.prototype.values.call(raw))]; - } + const raw = objectActor.obj.unsafeDereference(); + const iterator = + objectActor.obj.makeDebuggeeValue(waiveXrays(Set.prototype.values.call(raw))); + const values = [...DevToolsUtils.makeDebuggeeIterator(iterator)]; return { [Symbol.iterator]: function* () { @@ -443,8 +426,7 @@ function enumWeakSetEntries(objectActor) { // waive Xrays on the iterable, and relying on the Debugger machinery to // make sure we handle the resulting objects carefully. const raw = objectActor.obj.unsafeDereference(); - const basekeys = ChromeUtils.nondeterministicGetWeakSetKeys(raw); - const keys = isWorker ? basekeys : Cu.waiveXrays(basekeys); + const keys = waiveXrays(ChromeUtils.nondeterministicGetWeakSetKeys(raw)); return { [Symbol.iterator]: function* () { diff --git a/devtools/server/actors/object/utils.js b/devtools/server/actors/object/utils.js index 9ceb39a0cc06d..89cbd1d646760 100644 --- a/devtools/server/actors/object/utils.js +++ b/devtools/server/actors/object/utils.js @@ -187,12 +187,6 @@ function getArrayLength(object) { // For typed arrays, `DevToolsUtils.getProperty` is not reliable because the `length` // getter could be shadowed by an own property, and `getOwnPropertyNames` is // unnecessarily slow. Obtain the `length` getter safely and call it manually. - if (isWorker) { - // Workers can't wrap debugger values into debuggees, so do the calculations - // in the debuggee itself. - const getter = object.proto.proto.getOwnPropertyDescriptor("length").get; - return getter.call(object).return; - } const typedProto = Object.getPrototypeOf(Uint8Array.prototype); const getter = Object.getOwnPropertyDescriptor(typedProto, "length").get; return getter.call(object.unsafeDereference()); diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp index 6aad835a6a9ea..e58c876bb1cb2 100644 --- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -89,7 +89,6 @@ #include "mozilla/dom/SessionStoreListener.h" #include "mozilla/gfx/CrossProcessPaint.h" #include "mozilla/jsipc/CrossProcessObjectWrappers.h" -#include "mozilla/layout/RenderFrame.h" #include "mozilla/ServoCSSParser.h" #include "mozilla/ServoStyleSet.h" #include "nsGenericHTMLFrameElement.h" @@ -2713,7 +2712,7 @@ bool nsFrameLoader::TryRemoteBrowserInternal() { // The remoteType can be queried by asking the message manager instead. ownerElement->UnsetAttr(kNameSpaceID_None, nsGkAtoms::RemoteType, false); - // Now that browserParent is set, we can initialize the RenderFrame + // Now that browserParent is set, we can initialize graphics browserParent->InitRendering(); MaybeUpdatePrimaryBrowserParent(eBrowserParentChanged); @@ -2813,13 +2812,7 @@ BrowserBridgeChild* nsFrameLoader::GetBrowserBridgeChild() const { mozilla::layers::LayersId nsFrameLoader::GetLayersId() const { MOZ_ASSERT(mIsRemoteFrame); - if (auto* browserParent = GetBrowserParent()) { - return browserParent->GetRenderFrame()->GetLayersId(); - } - if (auto* browserBridgeChild = GetBrowserBridgeChild()) { - return browserBridgeChild->GetLayersId(); - } - return mozilla::layers::LayersId{}; + return mRemoteBrowser->GetLayersId(); } void nsFrameLoader::ActivateRemoteFrame(ErrorResult& aRv) { diff --git a/dom/base/nsFrameLoader.h b/dom/base/nsFrameLoader.h index 47e4abe144112..b9f22425ca981 100644 --- a/dom/base/nsFrameLoader.h +++ b/dom/base/nsFrameLoader.h @@ -74,10 +74,6 @@ class StructuredCloneData; namespace ipc { class MessageChannel; } // namespace ipc - -namespace layout { -class RenderFrame; -} // namespace layout } // namespace mozilla #if defined(MOZ_WIDGET_GTK) @@ -101,7 +97,6 @@ class nsFrameLoader final : public nsStubMutationObserver, typedef mozilla::dom::BrowserParent BrowserParent; typedef mozilla::dom::BrowserBridgeChild BrowserBridgeChild; typedef mozilla::dom::BrowsingContext BrowsingContext; - typedef mozilla::layout::RenderFrame RenderFrame; public: // Called by Frame Elements to create a new FrameLoader. diff --git a/dom/base/nsPIWindowRoot.h b/dom/base/nsPIWindowRoot.h index b258452a61919..5a18b7b1f510d 100644 --- a/dom/base/nsPIWindowRoot.h +++ b/dom/base/nsPIWindowRoot.h @@ -14,12 +14,7 @@ class nsPIDOMWindowOuter; class nsIControllers; class nsIController; class nsINode; - -namespace mozilla { -namespace dom { -class BrowserParent; -} // namespace dom -} // namespace mozilla +class nsIRemoteTab; #define NS_IWINDOWROOT_IID \ { \ diff --git a/dom/ipc/BrowserBridgeChild.cpp b/dom/ipc/BrowserBridgeChild.cpp index 2c317de7135e6..54eca7ff68146 100644 --- a/dom/ipc/BrowserBridgeChild.cpp +++ b/dom/ipc/BrowserBridgeChild.cpp @@ -22,8 +22,10 @@ namespace mozilla { namespace dom { BrowserBridgeChild::BrowserBridgeChild(nsFrameLoader* aFrameLoader, - BrowsingContext* aBrowsingContext) - : mLayersId{0}, + BrowsingContext* aBrowsingContext, + TabId aId) + : mId{aId}, + mLayersId{0}, mIPCOpen(true), mFrameLoader(aFrameLoader), mBrowsingContext(aBrowsingContext) {} diff --git a/dom/ipc/BrowserBridgeChild.h b/dom/ipc/BrowserBridgeChild.h index e7f137cbdd470..9ad3fbcf339ca 100644 --- a/dom/ipc/BrowserBridgeChild.h +++ b/dom/ipc/BrowserBridgeChild.h @@ -9,6 +9,7 @@ #include "mozilla/dom/PBrowserBridgeChild.h" #include "mozilla/dom/BrowserChild.h" +#include "mozilla/dom/ipc/IdType.h" namespace mozilla { @@ -26,6 +27,8 @@ class ContentChild; */ class BrowserBridgeChild : public PBrowserBridgeChild { public: + typedef mozilla::layers::LayersId LayersId; + NS_INLINE_DECL_REFCOUNTING(BrowserBridgeChild); BrowserChild* Manager() { @@ -33,7 +36,10 @@ class BrowserBridgeChild : public PBrowserBridgeChild { return static_cast(PBrowserBridgeChild::Manager()); } - mozilla::layers::LayersId GetLayersId() { return mLayersId; } + TabId GetTabId() { return mId; } + + LayersId GetLayersId() { return mLayersId; } + nsFrameLoader* GetFrameLoader() const { return mFrameLoader; } BrowsingContext* GetBrowsingContext() { return mBrowsingContext; } @@ -64,7 +70,7 @@ class BrowserBridgeChild : public PBrowserBridgeChild { friend class PBrowserBridgeChild; BrowserBridgeChild(nsFrameLoader* aFrameLoader, - BrowsingContext* aBrowsingContext); + BrowsingContext* aBrowsingContext, TabId aId); mozilla::ipc::IPCResult RecvSetLayersId( const mozilla::layers::LayersId& aLayersId); @@ -82,7 +88,8 @@ class BrowserBridgeChild : public PBrowserBridgeChild { private: ~BrowserBridgeChild(); - mozilla::layers::LayersId mLayersId; + TabId mId; + LayersId mLayersId; bool mIPCOpen; RefPtr mFrameLoader; RefPtr mBrowsingContext; diff --git a/dom/ipc/BrowserBridgeHost.cpp b/dom/ipc/BrowserBridgeHost.cpp index 5e98e964554a8..09e8635031a0c 100644 --- a/dom/ipc/BrowserBridgeHost.cpp +++ b/dom/ipc/BrowserBridgeHost.cpp @@ -23,6 +23,8 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(BrowserBridgeHost) BrowserBridgeHost::BrowserBridgeHost(BrowserBridgeChild* aChild) : mBridge(aChild) {} +TabId BrowserBridgeHost::GetTabId() const { return mBridge->GetTabId(); } + mozilla::layers::LayersId BrowserBridgeHost::GetLayersId() const { return mBridge->GetLayersId(); } diff --git a/dom/ipc/BrowserBridgeHost.h b/dom/ipc/BrowserBridgeHost.h index 71a1c8efd2551..5237a4580349c 100644 --- a/dom/ipc/BrowserBridgeHost.h +++ b/dom/ipc/BrowserBridgeHost.h @@ -37,6 +37,7 @@ class BrowserBridgeHost : public RemoteBrowser { BrowserHost* AsBrowserHost() override { return nullptr; } BrowserBridgeHost* AsBrowserBridgeHost() override { return this; } + TabId GetTabId() const override; LayersId GetLayersId() const override; BrowsingContext* GetBrowsingContext() const override; nsILoadContext* GetLoadContext() const override; diff --git a/dom/ipc/BrowserBridgeParent.cpp b/dom/ipc/BrowserBridgeParent.cpp index a16bf864d36cc..bfcb359cf4008 100644 --- a/dom/ipc/BrowserBridgeParent.cpp +++ b/dom/ipc/BrowserBridgeParent.cpp @@ -35,7 +35,7 @@ BrowserBridgeParent::~BrowserBridgeParent() { Destroy(); } nsresult BrowserBridgeParent::Init(const nsString& aPresentationURL, const nsString& aRemoteType, CanonicalBrowsingContext* aBrowsingContext, - const uint32_t& aChromeFlags) { + const uint32_t& aChromeFlags, TabId aTabId) { mIPCOpen = true; // FIXME: This should actually use a non-bogus TabContext, probably inherited @@ -64,14 +64,13 @@ nsresult BrowserBridgeParent::Init(const nsString& aPresentationURL, aBrowsingContext->SetOwnerProcessId(constructorSender->ChildID()); ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - TabId tabId(nsContentUtils::GenerateTabId()); - cpm->RegisterRemoteFrame(tabId, ContentParentId(0), TabId(0), + cpm->RegisterRemoteFrame(aTabId, ContentParentId(0), TabId(0), tabContext.AsIPCTabContext(), constructorSender->ChildID()); // Construct the BrowserParent object for our subframe. RefPtr browserParent(new BrowserParent( - constructorSender, tabId, tabContext, aBrowsingContext, aChromeFlags)); + constructorSender, aTabId, tabContext, aBrowsingContext, aChromeFlags)); browserParent->SetBrowserBridgeParent(this); // Open a remote endpoint for our PBrowser actor. DeallocPBrowserParent @@ -85,7 +84,7 @@ nsresult BrowserBridgeParent::Init(const nsString& aPresentationURL, // Tell the content process to set up its PBrowserChild. bool ok = constructorSender->SendConstructBrowser( - std::move(childEp), tabId, TabId(0), tabContext.AsIPCTabContext(), + std::move(childEp), aTabId, TabId(0), tabContext.AsIPCTabContext(), aBrowsingContext, aChromeFlags, constructorSender->ChildID(), constructorSender->IsForBrowser(), /* aIsTopLevel */ false); if (NS_WARN_IF(!ok)) { @@ -98,14 +97,8 @@ nsresult BrowserBridgeParent::Init(const nsString& aPresentationURL, mBrowserParent->SetOwnerElement(Manager()->GetOwnerElement()); mBrowserParent->InitRendering(); - RenderFrame* rf = mBrowserParent->GetRenderFrame(); - if (NS_WARN_IF(!rf)) { - MOZ_ASSERT(false, "No RenderFrame"); - return NS_ERROR_FAILURE; - } - // Send the newly created layers ID back into content. - Unused << SendSetLayersId(rf->GetLayersId()); + Unused << SendSetLayersId(mBrowserParent->GetLayersId()); return NS_OK; } @@ -128,11 +121,9 @@ void BrowserBridgeParent::Destroy() { IPCResult BrowserBridgeParent::RecvShow(const ScreenIntSize& aSize, const bool& aParentIsActive, const nsSizeMode& aSizeMode) { - RenderFrame* rf = mBrowserParent->GetRenderFrame(); - if (!rf->AttachLayerManager()) { + if (!mBrowserParent->AttachLayerManager()) { MOZ_CRASH(); } - Unused << mBrowserParent->SendShow(aSize, mBrowserParent->GetShowInfo(), aParentIsActive, aSizeMode); return IPC_OK(); diff --git a/dom/ipc/BrowserBridgeParent.h b/dom/ipc/BrowserBridgeParent.h index 48b18613e9ea8..b567647bb734d 100644 --- a/dom/ipc/BrowserBridgeParent.h +++ b/dom/ipc/BrowserBridgeParent.h @@ -9,6 +9,7 @@ #include "mozilla/dom/PBrowserBridgeParent.h" #include "mozilla/Tuple.h" +#include "mozilla/dom/ipc/IdType.h" namespace mozilla { @@ -33,7 +34,7 @@ class BrowserBridgeParent : public PBrowserBridgeParent { // Initialize this actor after performing startup. nsresult Init(const nsString& aPresentationURL, const nsString& aRemoteType, CanonicalBrowsingContext* aBrowsingContext, - const uint32_t& aChromeFlags); + const uint32_t& aChromeFlags, TabId aTabId); BrowserParent* GetBrowserParent() { return mBrowserParent; } diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp index a1ffdc931f87f..60915284a8487 100644 --- a/dom/ipc/BrowserChild.cpp +++ b/dom/ipc/BrowserChild.cpp @@ -171,49 +171,21 @@ typedef nsDataHashtable BrowserChildMap; static BrowserChildMap* sBrowserChildren; StaticMutex sBrowserChildrenMutex; -BrowserChildBase::BrowserChildBase() : mBrowserChildMessageManager(nullptr) {} - -BrowserChildBase::~BrowserChildBase() { mAnonymousGlobalScopes.Clear(); } - -NS_IMPL_CYCLE_COLLECTION_CLASS(BrowserChildBase) - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowserChildBase) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserChildMessageManager) - tmp->nsMessageManagerScriptExecutor::Unlink(); - NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebBrowserChrome) -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BrowserChildBase) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserChildMessageManager) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebBrowserChrome) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(BrowserChildBase) - tmp->nsMessageManagerScriptExecutor::Trace(aCallbacks, aClosure); -NS_IMPL_CYCLE_COLLECTION_TRACE_END - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserChildBase) - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -NS_IMPL_CYCLE_COLLECTING_ADDREF(BrowserChildBase) -NS_IMPL_CYCLE_COLLECTING_RELEASE(BrowserChildBase) - -already_AddRefed BrowserChildBase::GetTopLevelDocument() const { +already_AddRefed BrowserChild::GetTopLevelDocument() const { nsCOMPtr doc; WebNavigation()->GetDocument(getter_AddRefs(doc)); return doc.forget(); } -PresShell* BrowserChildBase::GetTopLevelPresShell() const { +PresShell* BrowserChild::GetTopLevelPresShell() const { if (RefPtr doc = GetTopLevelDocument()) { return doc->GetPresShell(); } return nullptr; } -void BrowserChildBase::DispatchMessageManagerMessage( - const nsAString& aMessageName, const nsAString& aJSONData) { +void BrowserChild::DispatchMessageManagerMessage(const nsAString& aMessageName, + const nsAString& aJSONData) { AutoSafeJSContext cx; JS::Rooted json(cx, JS::NullValue()); dom::ipc::StructuredCloneData data; @@ -235,7 +207,7 @@ void BrowserChildBase::DispatchMessageManagerMessage( IgnoreErrors()); } -bool BrowserChildBase::UpdateFrameHandler(const RepaintRequest& aRequest) { +bool BrowserChild::UpdateFrame(const RepaintRequest& aRequest) { MOZ_ASSERT(aRequest.GetScrollId() != ScrollableLayerGuid::NULL_SCROLL_ID); if (aRequest.IsRootContent()) { @@ -256,7 +228,7 @@ bool BrowserChildBase::UpdateFrameHandler(const RepaintRequest& aRequest) { return true; } -void BrowserChildBase::ProcessUpdateFrame(const RepaintRequest& aRequest) { +void BrowserChild::ProcessUpdateFrame(const RepaintRequest& aRequest) { if (!mBrowserChildMessageManager) { return; } @@ -372,6 +344,7 @@ BrowserChild::BrowserChild(ContentChild* aManager, const TabId& aTabId, BrowsingContext* aBrowsingContext, uint32_t aChromeFlags, bool aIsTopLevel) : TabContext(aContext), + mBrowserChildMessageManager(nullptr), mTabGroup(aTabGroup), mManager(aManager), mBrowsingContext(aBrowsingContext), @@ -658,20 +631,25 @@ void BrowserChild::UpdateFrameType() { NS_IMPL_CYCLE_COLLECTION_CLASS(BrowserChild) -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BrowserChild, BrowserChildBase) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowserChild) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserChildMessageManager) + tmp->nsMessageManagerScriptExecutor::Unlink(); + NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebBrowserChrome) NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusFilter) NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebNav) NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContext) NS_IMPL_CYCLE_COLLECTION_UNLINK_END -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BrowserChild, - BrowserChildBase) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BrowserChild) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserChildMessageManager) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebBrowserChrome) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusFilter) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebNav) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END -NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(BrowserChild, BrowserChildBase) +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(BrowserChild) + tmp->nsMessageManagerScriptExecutor::Trace(aCallbacks, aClosure); NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserChild) @@ -686,10 +664,11 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserChild) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) NS_INTERFACE_MAP_ENTRY(nsITooltipListener) NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener) -NS_INTERFACE_MAP_END_INHERITING(BrowserChildBase) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBrowserChild) +NS_INTERFACE_MAP_END -NS_IMPL_ADDREF_INHERITED(BrowserChild, BrowserChildBase); -NS_IMPL_RELEASE_INHERITED(BrowserChild, BrowserChildBase); +NS_IMPL_CYCLE_COLLECTING_ADDREF(BrowserChild) +NS_IMPL_CYCLE_COLLECTING_RELEASE(BrowserChild) NS_IMETHODIMP BrowserChild::SetStatus(uint32_t aStatusType, const char16_t* aStatus) { @@ -1039,6 +1018,7 @@ void BrowserChild::ActorDestroy(ActorDestroyReason why) { } BrowserChild::~BrowserChild() { + mAnonymousGlobalScopes.Clear(); if (sVisibleTabs) { sVisibleTabs->RemoveEntry(this); if (sVisibleTabs->IsEmpty()) { @@ -1291,10 +1271,6 @@ mozilla::ipc::IPCResult BrowserChild::RecvSetIsUnderHiddenEmbedderElement( return IPC_OK(); } -bool BrowserChild::UpdateFrame(const RepaintRequest& aRequest) { - return BrowserChildBase::UpdateFrameHandler(aRequest); -} - mozilla::ipc::IPCResult BrowserChild::RecvSuppressDisplayport( const bool& aEnabled) { if (RefPtr presShell = GetTopLevelPresShell()) { @@ -3332,7 +3308,8 @@ bool BrowserChild::DeallocPWindowGlobalChild(PWindowGlobalChild* aActor) { PBrowserBridgeChild* BrowserChild::AllocPBrowserBridgeChild(const nsString&, const nsString&, BrowsingContext*, - const uint32_t&) { + const uint32_t&, + const TabId&) { MOZ_CRASH( "We should never be manually allocating PBrowserBridgeChild actors"); return nullptr; diff --git a/dom/ipc/BrowserChild.h b/dom/ipc/BrowserChild.h index ff18bc831c20f..f307e28ea2d5b 100644 --- a/dom/ipc/BrowserChild.h +++ b/dom/ipc/BrowserChild.h @@ -142,67 +142,12 @@ class ContentListener final : public nsIDOMEventListener { BrowserChild* mBrowserChild; }; -// This is base clase which helps to share Viewport and touch related -// functionality between b2g/android FF/embedlite clients implementation. -// It make sense to place in this class all helper functions, and functionality -// which could be shared between Cross-process/Cross-thread implmentations. -class BrowserChildBase : public nsISupports, - public nsMessageManagerScriptExecutor, - public ipc::MessageManagerCallback { - protected: - typedef mozilla::widget::PuppetWidget PuppetWidget; - - public: - BrowserChildBase(); - - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BrowserChildBase) - - JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) { - return mBrowserChildMessageManager->WrapObject(aCx, aGivenProto); - } - - virtual nsIWebNavigation* WebNavigation() const = 0; - virtual PuppetWidget* WebWidget() = 0; - nsIPrincipal* GetPrincipal() { return mPrincipal; } - virtual bool DoUpdateZoomConstraints( - const uint32_t& aPresShellId, - const mozilla::layers::ScrollableLayerGuid::ViewID& aViewId, - const Maybe& aConstraints) = 0; - - virtual ScreenIntSize GetInnerSize() = 0; - - // Get the Document for the top-level window in this tab. - already_AddRefed GetTopLevelDocument() const; - - // Get the pres-shell of the document for the top-level window in this tab. - PresShell* GetTopLevelPresShell() const; - - protected: - virtual ~BrowserChildBase(); - - // Wraps up a JSON object as a structured clone and sends it to the browser - // chrome script. - // - // XXX/bug 780335: Do the work the browser chrome script does in C++ instead - // so we don't need things like this. - void DispatchMessageManagerMessage(const nsAString& aMessageName, - const nsAString& aJSONData); - - void ProcessUpdateFrame(const mozilla::layers::RepaintRequest& aRequest); - - bool UpdateFrameHandler(const mozilla::layers::RepaintRequest& aRequest); - - protected: - RefPtr mBrowserChildMessageManager; - nsCOMPtr mWebBrowserChrome; -}; - /** * BrowserChild implements the child actor part of the PBrowser protocol. See * PBrowser for more information. */ -class BrowserChild final : public BrowserChildBase, +class BrowserChild final : public nsMessageManagerScriptExecutor, + public ipc::MessageManagerCallback, public PBrowserChild, public nsIWebBrowserChrome2, public nsIEmbeddingSiteWindow, @@ -216,6 +161,7 @@ class BrowserChild final : public BrowserChildBase, public TabContext, public nsITooltipListener, public mozilla::ipc::IShmemAllocator { + typedef mozilla::widget::PuppetWidget PuppetWidget; typedef mozilla::dom::ClonedMessageData ClonedMessageData; typedef mozilla::dom::CoalescedMouseData CoalescedMouseData; typedef mozilla::dom::CoalescedWheelData CoalescedWheelData; @@ -260,7 +206,7 @@ class BrowserChild final : public BrowserChildBase, return mUniqueId; } - NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_NSIWEBBROWSERCHROME NS_DECL_NSIWEBBROWSERCHROME2 NS_DECL_NSIEMBEDDINGSITEWINDOW @@ -273,11 +219,22 @@ class BrowserChild final : public BrowserChildBase, NS_DECL_NSIWEBPROGRESSLISTENER2 NS_DECL_NSITOOLTIPLISTENER - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(BrowserChild, - BrowserChildBase) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(BrowserChild, + nsIBrowserChild) FORWARD_SHMEM_ALLOCATOR_TO(PBrowserChild) + JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) { + return mBrowserChildMessageManager->WrapObject(aCx, aGivenProto); + } + + nsIPrincipal* GetPrincipal() { return mPrincipal; } + // Get the Document for the top-level window in this tab. + already_AddRefed GetTopLevelDocument() const; + + // Get the pres-shell of the document for the top-level window in this tab. + PresShell* GetTopLevelPresShell() const; + BrowserChildMessageManager* GetMessageManager() { return mBrowserChildMessageManager; } @@ -297,9 +254,9 @@ class BrowserChild final : public BrowserChildBase, JS::Handle aCpows, nsIPrincipal* aPrincipal) override; - virtual bool DoUpdateZoomConstraints( + bool DoUpdateZoomConstraints( const uint32_t& aPresShellId, const ViewID& aViewId, - const Maybe& aConstraints) override; + const Maybe& aConstraints); mozilla::ipc::IPCResult RecvLoadURL(const nsCString& aURI, const ShowInfo& aInfo); @@ -455,9 +412,9 @@ class BrowserChild final : public BrowserChildBase, bool DeallocPFilePickerChild(PFilePickerChild* aActor); - virtual nsIWebNavigation* WebNavigation() const override { return mWebNav; } + nsIWebNavigation* WebNavigation() const { return mWebNav; } - virtual PuppetWidget* WebWidget() override { return mPuppetWidget; } + PuppetWidget* WebWidget() { return mPuppetWidget; } bool IsTransparent() const { return mIsTransparent; } @@ -588,7 +545,7 @@ class BrowserChild final : public BrowserChildBase, const mozilla::layers::CompositorOptions& GetCompositorOptions() const; bool AsyncPanZoomEnabled() const; - virtual ScreenIntSize GetInnerSize() override; + ScreenIntSize GetInnerSize(); // Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow(). void DoFakeShow(const ShowInfo& aShowInfo); @@ -708,7 +665,8 @@ class BrowserChild final : public BrowserChildBase, PBrowserBridgeChild* AllocPBrowserBridgeChild( const nsString& aName, const nsString& aRemoteType, - BrowsingContext* aBrowsingContext, const uint32_t& aChromeFlags); + BrowsingContext* aBrowsingContext, const uint32_t& aChromeFlags, + const TabId& aTabId); bool DeallocPBrowserBridgeChild(PBrowserBridgeChild* aActor); @@ -759,6 +717,18 @@ class BrowserChild final : public BrowserChildBase, GetContentBlockingLogResolver&& aResolve); private: + // Wraps up a JSON object as a structured clone and sends it to the browser + // chrome script. + // + // XXX/bug 780335: Do the work the browser chrome script does in C++ instead + // so we don't need things like this. + void DispatchMessageManagerMessage(const nsAString& aMessageName, + const nsAString& aJSONData); + + void ProcessUpdateFrame(const mozilla::layers::RepaintRequest& aRequest); + + bool UpdateFrameHandler(const mozilla::layers::RepaintRequest& aRequest); + void HandleDoubleTap(const CSSPoint& aPoint, const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid); @@ -829,6 +799,8 @@ class BrowserChild final : public BrowserChildBase, class DelayedDeleteRunnable; + RefPtr mBrowserChildMessageManager; + nsCOMPtr mWebBrowserChrome; TextureFactoryIdentifier mTextureFactoryIdentifier; RefPtr mWebBrowser; nsCOMPtr mWebNav; diff --git a/dom/ipc/BrowserHost.cpp b/dom/ipc/BrowserHost.cpp index 072b96221b993..b1fdacb60d438 100644 --- a/dom/ipc/BrowserHost.cpp +++ b/dom/ipc/BrowserHost.cpp @@ -35,8 +35,10 @@ BrowserHost* BrowserHost::GetFrom(nsIRemoteTab* aRemoteTab) { return static_cast(aRemoteTab); } +TabId BrowserHost::GetTabId() const { return mId; } + mozilla::layers::LayersId BrowserHost::GetLayersId() const { - return mRoot->GetRenderFrame()->GetLayersId(); + return mRoot->GetLayersId(); } BrowsingContext* BrowserHost::GetBrowsingContext() const { diff --git a/dom/ipc/BrowserHost.h b/dom/ipc/BrowserHost.h index 7371aebf85077..e752936c1d3ce 100644 --- a/dom/ipc/BrowserHost.h +++ b/dom/ipc/BrowserHost.h @@ -55,11 +55,11 @@ class BrowserHost : public RemoteBrowser, ContentParent* GetContentParent() const { return mRoot ? mRoot->Manager() : nullptr; } - TabId GetTabId() const { return mId; } BrowserHost* AsBrowserHost() override { return this; } BrowserBridgeHost* AsBrowserBridgeHost() override { return nullptr; } + TabId GetTabId() const override; LayersId GetLayersId() const override; BrowsingContext* GetBrowsingContext() const override; nsILoadContext* GetLoadContext() const override; diff --git a/dom/ipc/BrowserParent.cpp b/dom/ipc/BrowserParent.cpp index 510072786bc69..9ffceb47e9d3c 100644 --- a/dom/ipc/BrowserParent.cpp +++ b/dom/ipc/BrowserParent.cpp @@ -34,7 +34,7 @@ #include "mozilla/jsipc/CrossProcessObjectWrappers.h" #include "mozilla/layers/AsyncDragMetrics.h" #include "mozilla/layers/InputAPZContext.h" -#include "mozilla/layout/RenderFrame.h" +#include "mozilla/layout/RemoteLayerTreeOwner.h" #include "mozilla/plugins/PPluginWidgetParent.h" #include "mozilla/LookAndFeel.h" #include "mozilla/MouseEvents.h" @@ -182,7 +182,7 @@ BrowserParent::BrowserParent(ContentParent* aManager, const TabId& aTabId, mBrowserBridgeParent(nullptr), mBrowserHost(nullptr), mContentCache(*this), - mRenderFrame{}, + mRemoteLayerTreeOwner{}, mLayerTreeEpoch{1}, mChildToParentConversionMatrix{}, mRect(0, 0, 0, 0), @@ -425,11 +425,11 @@ a11y::DocAccessibleParent* BrowserParent::GetTopLevelDocAccessible() const { return nullptr; } -RenderFrame* BrowserParent::GetRenderFrame() { - if (!mRenderFrame.IsInitialized()) { - return nullptr; +LayersId BrowserParent::GetLayersId() const { + if (!mRemoteLayerTreeOwner.IsInitialized()) { + return LayersId{}; } - return &mRenderFrame; + return mRemoteLayerTreeOwner.GetLayersId(); } BrowserBridgeParent* BrowserParent::GetBrowserBridgeParent() const { @@ -526,8 +526,8 @@ void BrowserParent::SetOwnerElement(Element* aElement) { } } - if (mRenderFrame.IsInitialized()) { - mRenderFrame.OwnerContentChanged(); + if (mRemoteLayerTreeOwner.IsInitialized()) { + mRemoteLayerTreeOwner.OwnerContentChanged(); } // Set our BrowsingContext's embedder if we're not embedded within a @@ -623,8 +623,8 @@ void BrowserParent::Destroy() { mozilla::ipc::IPCResult BrowserParent::RecvEnsureLayersConnected( CompositorOptions* aCompositorOptions) { - if (mRenderFrame.IsInitialized()) { - mRenderFrame.EnsureLayersConnected(aCompositorOptions); + if (mRemoteLayerTreeOwner.IsInitialized()) { + mRemoteLayerTreeOwner.EnsureLayersConnected(aCompositorOptions); } return IPC_OK(); } @@ -638,12 +638,12 @@ mozilla::ipc::IPCResult BrowserParent::Recv__delete__() { } void BrowserParent::ActorDestroy(ActorDestroyReason why) { - if (mRenderFrame.IsInitialized()) { + if (mRemoteLayerTreeOwner.IsInitialized()) { // It's important to unmap layers after the remote browser has been // destroyed, otherwise it may still send messages to the compositor which // will reject them, causing assertions. - RemoveBrowserParentFromTable(mRenderFrame.GetLayersId()); - mRenderFrame.Destroy(); + RemoveBrowserParentFromTable(mRemoteLayerTreeOwner.GetLayersId()); + mRemoteLayerTreeOwner.Destroy(); } // Even though BrowserParent::Destroy calls this, we need to do it here too in @@ -845,19 +845,23 @@ void BrowserParent::ResumeLoad(uint64_t aPendingSwitchID) { } void BrowserParent::InitRendering() { - if (mRenderFrame.IsInitialized()) { + if (mRemoteLayerTreeOwner.IsInitialized()) { return; } - mRenderFrame.Initialize(this); + mRemoteLayerTreeOwner.Initialize(this); - layers::LayersId layersId = mRenderFrame.GetLayersId(); + layers::LayersId layersId = mRemoteLayerTreeOwner.GetLayersId(); AddBrowserParentToTable(layersId, this); TextureFactoryIdentifier textureFactoryIdentifier; - mRenderFrame.GetTextureFactoryIdentifier(&textureFactoryIdentifier); + mRemoteLayerTreeOwner.GetTextureFactoryIdentifier(&textureFactoryIdentifier); Unused << SendInitRendering(textureFactoryIdentifier, layersId, - mRenderFrame.GetCompositorOptions(), - mRenderFrame.IsLayersConnected()); + mRemoteLayerTreeOwner.GetCompositorOptions(), + mRemoteLayerTreeOwner.IsLayersConnected()); +} + +bool BrowserParent::AttachLayerManager() { + return !!mRemoteLayerTreeOwner.AttachLayerManager(); } void BrowserParent::MaybeShowFrame() { @@ -874,8 +878,8 @@ bool BrowserParent::Show(const ScreenIntSize& size, bool aParentIsActive) { return false; } - MOZ_ASSERT(mRenderFrame.IsInitialized()); - if (!mRenderFrame.AttachLayerManager()) { + MOZ_ASSERT(mRemoteLayerTreeOwner.IsInitialized()); + if (!mRemoteLayerTreeOwner.AttachLayerManager()) { return false; } @@ -1236,10 +1240,10 @@ bool BrowserParent::DeallocPWindowGlobalParent(PWindowGlobalParent* aActor) { IPCResult BrowserParent::RecvPBrowserBridgeConstructor( PBrowserBridgeParent* aActor, const nsString& aName, const nsString& aRemoteType, BrowsingContext* aBrowsingContext, - const uint32_t& aChromeFlags) { + const uint32_t& aChromeFlags, const TabId& aTabId) { nsresult rv = static_cast(aActor)->Init( aName, aRemoteType, CanonicalBrowsingContext::Cast(aBrowsingContext), - aChromeFlags); + aChromeFlags, aTabId); if (NS_FAILED(rv)) { return IPC_FAIL(this, "Failed to construct BrowserBridgeParent"); } @@ -1248,7 +1252,8 @@ IPCResult BrowserParent::RecvPBrowserBridgeConstructor( PBrowserBridgeParent* BrowserParent::AllocPBrowserBridgeParent( const nsString& aName, const nsString& aRemoteType, - BrowsingContext* aBrowsingContext, const uint32_t& aChromeFlags) { + BrowsingContext* aBrowsingContext, const uint32_t& aChromeFlags, + const TabId& aTabId) { // Reference freed in DeallocPBrowserBridgeParent. return do_AddRef(new BrowserBridgeParent()).take(); } @@ -2939,12 +2944,13 @@ void BrowserParent::ApzAwareEventRoutingToChild( // There may be cases where the APZ hit-testing code came to a different // conclusion than the main-thread hit-testing code as to where the event // is destined. In such cases the layersId of the APZ result may not match - // the layersId of this renderframe. In such cases the main-thread hit- - // testing code "wins" so we need to update the guid to reflect this. - if (mRenderFrame.IsInitialized()) { - if (aOutTargetGuid->mLayersId != mRenderFrame.GetLayersId()) { + // the layersId of this RemoteLayerTreeOwner. In such cases the + // main-thread hit- testing code "wins" so we need to update the guid to + // reflect this. + if (mRemoteLayerTreeOwner.IsInitialized()) { + if (aOutTargetGuid->mLayersId != mRemoteLayerTreeOwner.GetLayersId()) { *aOutTargetGuid = - ScrollableLayerGuid(mRenderFrame.GetLayersId(), 0, + ScrollableLayerGuid(mRemoteLayerTreeOwner.GetLayersId(), 0, ScrollableLayerGuid::NULL_SCROLL_ID); } } @@ -3143,8 +3149,8 @@ bool BrowserParent::StartApzAutoscroll(float aAnchorX, float aAnchorY, } bool success = false; - if (mRenderFrame.IsInitialized()) { - layers::LayersId layersId = mRenderFrame.GetLayersId(); + if (mRemoteLayerTreeOwner.IsInitialized()) { + layers::LayersId layersId = mRemoteLayerTreeOwner.GetLayersId(); if (nsCOMPtr widget = GetWidget()) { SLGuidAndRenderRoot guid(layersId, aPresShellId, aScrollId, gfxUtils::GetContentRenderRoot()); @@ -3172,8 +3178,8 @@ void BrowserParent::StopApzAutoscroll(nsViewID aScrollId, return; } - if (mRenderFrame.IsInitialized()) { - layers::LayersId layersId = mRenderFrame.GetLayersId(); + if (mRemoteLayerTreeOwner.IsInitialized()) { + layers::LayersId layersId = mRemoteLayerTreeOwner.GetLayersId(); if (nsCOMPtr widget = GetWidget()) { SLGuidAndRenderRoot guid(layersId, aPresShellId, aScrollId, gfxUtils::GetContentRenderRoot()); diff --git a/dom/ipc/BrowserParent.h b/dom/ipc/BrowserParent.h index 63eab0776fd4a..0c7804fffd507 100644 --- a/dom/ipc/BrowserParent.h +++ b/dom/ipc/BrowserParent.h @@ -20,7 +20,7 @@ #include "mozilla/dom/File.h" #include "mozilla/gfx/CrossProcessPaint.h" #include "mozilla/layers/CompositorBridgeParent.h" -#include "mozilla/layout/RenderFrame.h" +#include "mozilla/layout/RemoteLayerTreeOwner.h" #include "mozilla/RefPtr.h" #include "mozilla/Move.h" #include "nsCOMPtr.h" @@ -171,7 +171,7 @@ class BrowserParent final : public PBrowserParent, */ a11y::DocAccessibleParent* GetTopLevelDocAccessible() const; - layout::RenderFrame* GetRenderFrame(); + LayersId GetLayersId() const; // Returns the BrowserBridgeParent if this BrowserParent is for an // out-of-process iframe and nullptr otherwise. @@ -466,20 +466,22 @@ class BrowserParent final : public PBrowserParent, PBrowserBridgeParent* AllocPBrowserBridgeParent( const nsString& aPresentationURL, const nsString& aRemoteType, - BrowsingContext* aBrowsingContext, const uint32_t& aChromeFlags); + BrowsingContext* aBrowsingContext, const uint32_t& aChromeFlags, + const TabId& aTabId); bool DeallocPBrowserBridgeParent(PBrowserBridgeParent* aActor); virtual mozilla::ipc::IPCResult RecvPBrowserBridgeConstructor( PBrowserBridgeParent* aActor, const nsString& aPresentationURL, const nsString& aRemoteType, BrowsingContext* aBrowsingContext, - const uint32_t& aChromeFlags) override; + const uint32_t& aChromeFlags, const TabId& aTabId) override; void LoadURL(nsIURI* aURI); void ResumeLoad(uint64_t aPendingSwitchID); void InitRendering(); + bool AttachLayerManager(); void MaybeShowFrame(); bool Show(const ScreenIntSize& aSize, bool aParentIsActive); @@ -839,7 +841,7 @@ class BrowserParent final : public PBrowserParent, ContentCacheInParent mContentCache; - layout::RenderFrame mRenderFrame; + layout::RemoteLayerTreeOwner mRemoteLayerTreeOwner; LayersObserverEpoch mLayerTreeEpoch; Maybe mChildToParentConversionMatrix; diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index a81038b41bff2..4f99bb2e83f71 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -2057,13 +2057,14 @@ already_AddRefed ContentChild::CreateBrowser( chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME; } + TabId tabId(nsContentUtils::GenerateTabId()); RefPtr browserBridge = - new BrowserBridgeChild(aFrameLoader, aBrowsingContext); + new BrowserBridgeChild(aFrameLoader, aBrowsingContext, tabId); // Reference is freed in BrowserChild::DeallocPBrowserBridgeChild. browserChild->SendPBrowserBridgeConstructor( do_AddRef(browserBridge).take(), PromiseFlatString(aContext.PresentationURL()), aRemoteType, - aBrowsingContext, chromeFlags); + aBrowsingContext, chromeFlags, tabId); browserBridge->mIPCOpen = true; RefPtr browserBridgeHost = diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index b3a3e042e35d2..5f059f95aaae4 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -87,6 +87,7 @@ using mozilla::a11y::IAccessibleHolder from "mozilla/a11y/IPCTypes.h"; using mozilla::OriginAttributes from "mozilla/ipc/BackgroundUtils.h"; using refcounted class mozilla::dom::BrowsingContext from "mozilla/dom/BrowsingContext.h"; using mozilla::dom::EffectsInfo from "mozilla/dom/TabMessageUtils.h"; +using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h"; namespace mozilla { namespace dom { @@ -187,7 +188,8 @@ parent: * Construct a new Remote iframe actor. */ async PBrowserBridge(nsString aPresentationURL, nsString aRemoteType, - BrowsingContext aBrowsingContext, uint32_t aChromeFlags); + BrowsingContext aBrowsingContext, uint32_t aChromeFlags, + TabId tabId); /** * Sends an NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW to be adopted by the diff --git a/dom/ipc/RemoteBrowser.cpp b/dom/ipc/RemoteBrowser.cpp new file mode 100644 index 0000000000000..47f4660a4cd15 --- /dev/null +++ b/dom/ipc/RemoteBrowser.cpp @@ -0,0 +1,26 @@ +#include "RemoteBrowser.h" + +#include "nsFrameLoader.h" +#include "nsFrameLoaderOwner.h" + +namespace mozilla { +namespace dom { + +RemoteBrowser* RemoteBrowser::GetFrom(nsFrameLoader* aFrameLoader) { + if (!aFrameLoader) { + return nullptr; + } + return aFrameLoader->GetRemoteBrowser(); +} + +RemoteBrowser* RemoteBrowser::GetFrom(nsIContent* aContent) { + RefPtr loaderOwner = do_QueryObject(aContent); + if (!loaderOwner) { + return nullptr; + } + RefPtr frameLoader = loaderOwner->GetFrameLoader(); + return GetFrom(frameLoader); +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/ipc/RemoteBrowser.h b/dom/ipc/RemoteBrowser.h index cb8aa1f3a0df9..e02da8371f786 100644 --- a/dom/ipc/RemoteBrowser.h +++ b/dom/ipc/RemoteBrowser.h @@ -39,11 +39,15 @@ class RemoteBrowser : public nsISupports { public: typedef mozilla::layers::LayersId LayersId; + static RemoteBrowser* GetFrom(nsFrameLoader* aFrameLoader); + static RemoteBrowser* GetFrom(nsIContent* aContent); + // Try to cast this RemoteBrowser to a BrowserHost, may return null virtual BrowserHost* AsBrowserHost() = 0; // Try to cast this RemoteBrowser to a BrowserBridgeHost, may return null virtual BrowserBridgeHost* AsBrowserBridgeHost() = 0; + virtual TabId GetTabId() const = 0; virtual LayersId GetLayersId() const = 0; virtual BrowsingContext* GetBrowsingContext() const = 0; virtual nsILoadContext* GetLoadContext() const = 0; diff --git a/dom/ipc/moz.build b/dom/ipc/moz.build index edc39d5c4d414..88a56a0330683 100644 --- a/dom/ipc/moz.build +++ b/dom/ipc/moz.build @@ -105,6 +105,7 @@ UNIFIED_SOURCES += [ 'PreallocatedProcessManager.cpp', 'ProcessPriorityManager.cpp', 'ReferrerInfoUtils.cpp', + 'RemoteBrowser.cpp', 'RemoteWebProgress.cpp', 'RemoteWebProgressRequest.cpp', 'SharedMap.cpp', diff --git a/dom/localstorage/ActorsParent.cpp b/dom/localstorage/ActorsParent.cpp index 84aaea2ecdda5..4fc7c46d61baf 100644 --- a/dom/localstorage/ActorsParent.cpp +++ b/dom/localstorage/ActorsParent.cpp @@ -2925,7 +2925,7 @@ void InitUsageForOrigin(const nsACString& aOrigin, int64_t aUsage) { gUsages = new UsageHashtable(); } - MOZ_DIAGNOSTIC_ASSERT(!gUsages->Contains(aOrigin)); + MOZ_ASSERT(!gUsages->Contains(aOrigin)); gUsages->Put(aOrigin, aUsage); } diff --git a/dom/plugins/ipc/PluginInstanceParent.cpp b/dom/plugins/ipc/PluginInstanceParent.cpp index f912f2b8ae476..3b8aebf628e52 100644 --- a/dom/plugins/ipc/PluginInstanceParent.cpp +++ b/dom/plugins/ipc/PluginInstanceParent.cpp @@ -863,8 +863,7 @@ mozilla::ipc::IPCResult PluginInstanceParent::RecvShow( bool isPlugin = true; RefPtr sourceSurface = - gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, surface, - isPlugin); + gfxPlatform::GetSourceSurfaceForSurface(nullptr, surface, isPlugin); RefPtr image = new SourceSurfaceImage(surface->GetSize(), sourceSurface); @@ -1051,9 +1050,8 @@ nsresult PluginInstanceParent::BeginUpdateBackground(const nsIntRect& aRect, "Update outside of background area"); #endif - RefPtr dt = - gfxPlatform::GetPlatform()->CreateDrawTargetForSurface( - mBackground, gfx::IntSize(sz.width, sz.height)); + RefPtr dt = gfxPlatform::CreateDrawTargetForSurface( + mBackground, gfx::IntSize(sz.width, sz.height)); dt.forget(aDrawTarget); return NS_OK; diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index 4822e1a922572..8359cbfb797af 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -823,21 +823,19 @@ static bool PreserveWrapper(JSContext* cx, JS::HandleObject obj) { return mozilla::dom::TryPreserveWrapper(obj); } +static bool IsWorkerDebuggerGlobalOrSandbox(JSObject* aGlobal) { + return IsWorkerDebuggerGlobal(aGlobal) || IsWorkerDebuggerSandbox(aGlobal); +} + JSObject* Wrap(JSContext* cx, JS::HandleObject existing, JS::HandleObject obj) { JSObject* targetGlobal = JS::CurrentGlobalOrNull(cx); - if (!IsWorkerDebuggerGlobal(targetGlobal) && - !IsWorkerDebuggerSandbox(targetGlobal)) { - JS_ReportErrorASCII( - cx, "There should be no edges from the debuggee to the debugger."); - return nullptr; - } // Note: the JS engine unwraps CCWs before calling this callback. JSObject* originGlobal = JS::GetNonCCWObjectGlobal(obj); const js::Wrapper* wrapper = nullptr; - if (IsWorkerDebuggerGlobal(originGlobal) || - IsWorkerDebuggerSandbox(originGlobal)) { + if (IsWorkerDebuggerGlobalOrSandbox(targetGlobal) && + IsWorkerDebuggerGlobalOrSandbox(originGlobal)) { wrapper = &js::CrossCompartmentWrapper::singleton; } else { wrapper = &js::OpaqueCrossCompartmentWrapper::singleton; diff --git a/gfx/layers/TextureDIB.cpp b/gfx/layers/TextureDIB.cpp index 322ae4243df25..b9909ee2053b1 100644 --- a/gfx/layers/TextureDIB.cpp +++ b/gfx/layers/TextureDIB.cpp @@ -116,8 +116,7 @@ void DIBTextureData::FillInfo(TextureData::Info& aInfo) const { } already_AddRefed DIBTextureData::BorrowDrawTarget() { - return gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mSurface, - mSize); + return gfxPlatform::CreateDrawTargetForSurface(mSurface, mSize); } DIBTextureData* DIBTextureData::Create(gfx::IntSize aSize, diff --git a/gfx/layers/apz/src/FocusTarget.cpp b/gfx/layers/apz/src/FocusTarget.cpp index bbc5cfa156e40..40366d70a6cee 100644 --- a/gfx/layers/apz/src/FocusTarget.cpp +++ b/gfx/layers/apz/src/FocusTarget.cpp @@ -8,9 +8,8 @@ #include "mozilla/dom/BrowserBridgeChild.h" // for BrowserBridgeChild #include "mozilla/dom/EventTarget.h" // for EventTarget -#include "mozilla/dom/BrowserParent.h" // for BrowserParent +#include "mozilla/dom/RemoteBrowser.h" // For RemoteBrowser #include "mozilla/EventDispatcher.h" // for EventDispatcher -#include "mozilla/layout/RenderFrame.h" // For RenderFrame #include "mozilla/PresShell.h" // For PresShell #include "nsIContentInlines.h" // for nsINode::IsEditable() #include "nsLayoutUtils.h" // for nsLayoutUtils @@ -157,17 +156,16 @@ FocusTarget::FocusTarget(PresShell* aRootPresShell, } // Check if the key event target is a remote browser - if (BrowserParent* browserParent = BrowserParent::GetFrom(keyEventTarget)) { - RenderFrame* rf = browserParent->GetRenderFrame(); + if (RemoteBrowser* remoteBrowser = RemoteBrowser::GetFrom(keyEventTarget)) { + LayersId layersId = remoteBrowser->GetLayersId(); // The globally focused element for scrolling is in a remote layer tree - if (rf) { + if (layersId.IsValid()) { FT_LOG("Creating reflayer target with seq=%" PRIu64 ", kl=%d, lt=%" PRIu64 "\n", - aFocusSequenceNumber, mFocusHasKeyEventListeners, - rf->GetLayersId()); + aFocusSequenceNumber, mFocusHasKeyEventListeners, layersId); - mData = AsVariant(rf->GetLayersId()); + mData = AsVariant(std::move(layersId)); return; } @@ -178,17 +176,6 @@ FocusTarget::FocusTarget(PresShell* aRootPresShell, return; } - // Check if the key event target is a remote browser - if (BrowserBridgeChild* bbc = BrowserBridgeChild::GetFrom(keyEventTarget)) { - FT_LOG("Creating oopif reflayer target with seq=%" PRIu64 - ", kl=%d, lt=%" PRIu64 "\n", - aFocusSequenceNumber, mFocusHasKeyEventListeners, - bbc->GetLayersId()); - - mData = AsVariant(bbc->GetLayersId()); - return; - } - // The content to scroll is either the focused element or the focus node of // the selection. It's difficult to determine if an element is an interactive // element requiring async keyboard scrolling to be disabled. So we only diff --git a/gfx/layers/basic/X11BasicCompositor.cpp b/gfx/layers/basic/X11BasicCompositor.cpp index 74ecb427bea0a..d9cf164571f60 100644 --- a/gfx/layers/basic/X11BasicCompositor.cpp +++ b/gfx/layers/basic/X11BasicCompositor.cpp @@ -41,8 +41,8 @@ bool X11DataTextureSourceBasic::Update(gfx::DataSourceSurface* aSurface, surf = new gfxImageSurface(aSurface->GetSize(), imageFormat); } - mBufferDrawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface( - surf, aSurface->GetSize()); + mBufferDrawTarget = + gfxPlatform::CreateDrawTargetForSurface(surf, aSurface->GetSize()); } // Image contents have changed, upload to our DrawTarget diff --git a/gfx/layers/client/ContentClient.cpp b/gfx/layers/client/ContentClient.cpp index 084a87ab6e6fe..f2f873b02ce23 100644 --- a/gfx/layers/client/ContentClient.cpp +++ b/gfx/layers/client/ContentClient.cpp @@ -506,8 +506,7 @@ RefPtr ContentClientBasic::CreateBuffer(gfxContentType aType, RefPtr surf = new gfxWindowsSurface( size, aType == gfxContentType::COLOR ? gfxImageFormat::X8R8G8B8_UINT32 : gfxImageFormat::A8R8G8B8_UINT32); - drawTarget = - gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surf, size); + drawTarget = gfxPlatform::CreateDrawTargetForSurface(surf, size); } #endif diff --git a/gfx/layers/ipc/CompositorBridgeChild.cpp b/gfx/layers/ipc/CompositorBridgeChild.cpp index 445cc58921f10..66fbf2fffd462 100644 --- a/gfx/layers/ipc/CompositorBridgeChild.cpp +++ b/gfx/layers/ipc/CompositorBridgeChild.cpp @@ -53,7 +53,6 @@ #include "VsyncSource.h" using mozilla::Unused; -using mozilla::dom::BrowserChildBase; using mozilla::gfx::GPUProcessManager; using mozilla::layers::LayerTransactionChild; @@ -645,17 +644,15 @@ mozilla::ipc::IPCResult CompositorBridgeChild::RecvRemotePaintIsReady() { // do_QueryReference so I'm using static_cast<> MOZ_LAYERS_LOG( ("[RemoteGfx] CompositorBridgeChild received RemotePaintIsReady")); - RefPtr iBrowserChildBase(do_QueryReferent(mWeakBrowserChild)); - if (!iBrowserChildBase) { + RefPtr iBrowserChild(do_QueryReferent(mWeakBrowserChild)); + if (!iBrowserChild) { MOZ_LAYERS_LOG( ("[RemoteGfx] Note: BrowserChild was released before " "RemotePaintIsReady. " "MozAfterRemotePaint will not be sent to listener.")); return IPC_OK(); } - BrowserChildBase* browserChildBase = - static_cast(iBrowserChildBase.get()); - BrowserChild* browserChild = static_cast(browserChildBase); + BrowserChild* browserChild = static_cast(iBrowserChild.get()); MOZ_ASSERT(browserChild); Unused << browserChild->SendRemotePaintIsReady(); mWeakBrowserChild = nullptr; @@ -668,7 +665,7 @@ void CompositorBridgeChild::RequestNotifyAfterRemotePaint( "NULL BrowserChild not allowed in " "CompositorBridgeChild::RequestNotifyAfterRemotePaint"); mWeakBrowserChild = - do_GetWeakReference(static_cast(aBrowserChild)); + do_GetWeakReference(static_cast(aBrowserChild)); if (!mCanSend) { return; } @@ -677,13 +674,11 @@ void CompositorBridgeChild::RequestNotifyAfterRemotePaint( void CompositorBridgeChild::CancelNotifyAfterRemotePaint( BrowserChild* aBrowserChild) { - RefPtr iBrowserChildBase(do_QueryReferent(mWeakBrowserChild)); - if (!iBrowserChildBase) { + RefPtr iBrowserChild(do_QueryReferent(mWeakBrowserChild)); + if (!iBrowserChild) { return; } - BrowserChildBase* browserChildBase = - static_cast(iBrowserChildBase.get()); - BrowserChild* browserChild = static_cast(browserChildBase); + BrowserChild* browserChild = static_cast(iBrowserChild.get()); if (browserChild == aBrowserChild) { mWeakBrowserChild = nullptr; } diff --git a/gfx/thebes/PrintTargetThebes.cpp b/gfx/thebes/PrintTargetThebes.cpp index 50da0423fe5be..8a066d5690a38 100644 --- a/gfx/thebes/PrintTargetThebes.cpp +++ b/gfx/thebes/PrintTargetThebes.cpp @@ -36,8 +36,7 @@ already_AddRefed PrintTargetThebes::MakeDrawTarget( MOZ_ASSERT(mHasActivePage, "We can't guarantee a valid DrawTarget"); RefPtr dt = - gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mGfxSurface, - aSize); + gfxPlatform::CreateDrawTargetForSurface(mGfxSurface, aSize); if (!dt || !dt->IsValid()) { return nullptr; } @@ -55,8 +54,7 @@ already_AddRefed PrintTargetThebes::MakeDrawTarget( already_AddRefed PrintTargetThebes::GetReferenceDrawTarget() { if (!mRefDT) { RefPtr dt = - gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mGfxSurface, - mSize); + gfxPlatform::CreateDrawTargetForSurface(mGfxSurface, mSize); if (!dt || !dt->IsValid()) { return nullptr; } diff --git a/gfx/thebes/gfxASurface.cpp b/gfx/thebes/gfxASurface.cpp index d8c6cff84d1e8..3f4647e317b3d 100644 --- a/gfx/thebes/gfxASurface.cpp +++ b/gfx/thebes/gfxASurface.cpp @@ -280,11 +280,10 @@ already_AddRefed gfxASurface::CopyToARGB32ImageSurface() { RefPtr imgSurface = new gfxImageSurface(size, SurfaceFormat::A8R8G8B8_UINT32); - RefPtr dt = - gfxPlatform::GetPlatform()->CreateDrawTargetForSurface( - imgSurface, IntSize(size.width, size.height)); + RefPtr dt = gfxPlatform::CreateDrawTargetForSurface( + imgSurface, IntSize(size.width, size.height)); RefPtr source = - gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, this); + gfxPlatform::GetSourceSurfaceForSurface(dt, this); dt->CopySurface(source, IntRect(0, 0, size.width, size.height), IntPoint()); diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 05104e964e6bc..847fa52017fa3 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -25,6 +25,7 @@ #include "mozilla/TimeStamp.h" #include "mozilla/Unused.h" #include "mozilla/IntegerPrintfMacros.h" +#include "mozilla/Base64.h" #include "mozilla/Logging.h" #include "mozilla/Services.h" @@ -462,6 +463,7 @@ gfxPlatform::gfxPlatform() mApzSupportCollector(this, &gfxPlatform::GetApzSupportInfo), mTilesInfoCollector(this, &gfxPlatform::GetTilesSupportInfo), mFrameStatsCollector(this, &gfxPlatform::GetFrameStats), + mCMSInfoCollector(this, &gfxPlatform::GetCMSSupportInfo), mCompositorBackend(layers::LayersBackend::LAYERS_NONE), mScreenDepth(0) { mAllowDownloadableFonts = UNINITIALIZED_VALUE; @@ -3258,6 +3260,26 @@ void gfxPlatform::GetFrameStats(mozilla::widget::InfoObject& aObj) { } } +void gfxPlatform::GetCMSSupportInfo(mozilla::widget::InfoObject& aObj) { + void* profile = nullptr; + size_t size = 0; + + GetCMSOutputProfileData(profile, size); + if (!profile) { + return; + } + + char* encodedProfile = nullptr; + nsresult rv = + Base64Encode(reinterpret_cast(profile), size, &encodedProfile); + if (NS_SUCCEEDED(rv)) { + aObj.DefineProperty("CMSOutputProfile", encodedProfile); + free(encodedProfile); + } + + free(profile); +} + class FrameStatsComparator { public: bool Equals(const FrameStats& aA, const FrameStats& aB) const { diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index 94deaddb64231..d4da68c01af5c 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -281,6 +281,7 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener { void GetApzSupportInfo(mozilla::widget::InfoObject& aObj); void GetTilesSupportInfo(mozilla::widget::InfoObject& aObj); void GetFrameStats(mozilla::widget::InfoObject& aObj); + void GetCMSSupportInfo(mozilla::widget::InfoObject& aObj); // Get the default content backend that will be used with the default // compositor. If the compositor is known when calling this function, @@ -911,6 +912,7 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener { mozilla::widget::GfxInfoCollector mApzSupportCollector; mozilla::widget::GfxInfoCollector mTilesInfoCollector; mozilla::widget::GfxInfoCollector mFrameStatsCollector; + mozilla::widget::GfxInfoCollector mCMSInfoCollector; nsTArray mFrameStats; diff --git a/gfx/wr/webrender/src/renderer.rs b/gfx/wr/webrender/src/renderer.rs index 0f1a55a220e91..a49100c1c84d9 100644 --- a/gfx/wr/webrender/src/renderer.rs +++ b/gfx/wr/webrender/src/renderer.rs @@ -889,7 +889,7 @@ struct TextureResolver { /// Saved render targets from previous passes. This is used when a pass /// needs access to the result of a pass other than the immediately-preceding - /// one. In this case, the `RenderTask` will get a a non-`None` `saved_index`, + /// one. In this case, the `RenderTask` will get a non-`None` `saved_index`, /// which will cause the resulting render target to be persisted in this list /// (at that index) until the end of the frame. saved_targets: Vec, @@ -5253,7 +5253,7 @@ pub struct ExternalImage<'a> { /// The interfaces that an application can implement to support providing /// external image buffers. -/// When the the application passes an external image to WR, it should kepp that +/// When the application passes an external image to WR, it should keep that /// external image life time. People could check the epoch id in RenderNotifier /// at the client side to make sure that the external image is not used by WR. /// Then, do the clean up for that external image. diff --git a/gfx/wr/webrender_api/src/api.rs b/gfx/wr/webrender_api/src/api.rs index 19c9add8084a5..5ae64949c368b 100644 --- a/gfx/wr/webrender_api/src/api.rs +++ b/gfx/wr/webrender_api/src/api.rs @@ -710,10 +710,10 @@ pub enum DebugCommand { ClearCaches(ClearCache), /// Invalidate GPU cache, forcing the update from the CPU mirror. InvalidateGpuCache, - /// Causes the scene builder to pause for a given amount of miliseconds each time it + /// Causes the scene builder to pause for a given amount of milliseconds each time it /// processes a transaction. SimulateLongSceneBuild(u32), - /// Causes the low priority scene builder to pause for a given amount of miliseconds + /// Causes the low priority scene builder to pause for a given amount of milliseconds /// each time it processes a transaction. SimulateLongLowPrioritySceneBuild(u32), } @@ -997,9 +997,9 @@ impl RenderApiSender { // This is used to discover the underlying cause of https://github.com/servo/servo/issues/13480. let webrender_is_alive = self.api_sender.send(ApiMsg::WakeUp); if webrender_is_alive.is_err() { - panic!("Webrender was shut down before processing CloneApi: {}", e); + panic!("WebRender was shut down before processing CloneApi: {}", e); } else { - panic!("CloneApi message response was dropped while Webrender was still alive: {}", e); + panic!("CloneApi message response was dropped while WebRender was still alive: {}", e); } } }; diff --git a/gfx/wr/webrender_api/src/image.rs b/gfx/wr/webrender_api/src/image.rs index 080c9d9205373..193a25bc9fab0 100644 --- a/gfx/wr/webrender_api/src/image.rs +++ b/gfx/wr/webrender_api/src/image.rs @@ -60,7 +60,7 @@ pub enum TextureTarget { /// https://www.khronos.org/opengl/wiki/Array_Texture for background /// on Array textures. Array = 1, - /// Rectange texture. This maps to GL_TEXTURE_RECTANGLE in OpenGL. This + /// Rectangle texture. This maps to GL_TEXTURE_RECTANGLE in OpenGL. This /// is similar to a standard texture, with a few subtle differences /// (no mipmaps, non-power-of-two dimensions, different coordinate space) /// that make it useful for representing the kinds of textures we use diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp index 627be18e08a01..dcfdcffb48181 100644 --- a/js/src/builtin/ModuleObject.cpp +++ b/js/src/builtin/ModuleObject.cpp @@ -677,12 +677,13 @@ void ModuleNamespaceObject::ProxyHandler::trace(JSTracer* trc, } } -void ModuleNamespaceObject::ProxyHandler::finalize(JSFreeOp* fop, +void ModuleNamespaceObject::ProxyHandler::finalize(JSFreeOp* fopArg, JSObject* proxy) const { + FreeOp* fop = FreeOp::get(fopArg); auto& self = proxy->as(); if (self.hasBindings()) { - js_delete(&self.bindings()); + fop->delete_(&self.bindings()); } } diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp index 31f50f796b977..eedec2787afaa 100644 --- a/js/src/builtin/TypedObject.cpp +++ b/js/src/builtin/TypedObject.cpp @@ -2933,6 +2933,6 @@ static bool CreateTraceList(JSContext* cx, HandleTypeDescr descr) { void TypeDescr::finalize(FreeOp* fop, JSObject* obj) { TypeDescr& descr = obj->as(); if (descr.hasTraceList()) { - js_free(const_cast(descr.traceList())); + fop->free_(const_cast(descr.traceList())); } } diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp index 4bc61890fa570..a3affcae4254c 100644 --- a/js/src/gc/GC.cpp +++ b/js/src/gc/GC.cpp @@ -990,7 +990,7 @@ GCRuntime::GCRuntime(JSRuntime* rt) numArenasFreeCommitted(0), verifyPreData(nullptr), chunkAllocationSinceLastGC(false), - lastGCTime(ReallyNow()), + lastGCTime_(ReallyNow()), mode(TuningDefaults::Mode), numActiveZoneIters(0), cleanUpEverything(false), @@ -2208,13 +2208,20 @@ void MemoryCounter::recordTrigger(TriggerKind trigger) { /* Compacting GC */ +bool js::gc::IsCurrentlyAnimating(const TimeStamp& lastAnimationTime, + const TimeStamp& currentTime) { + // Assume that we're currently animating if js::NotifyAnimationActivity has + // been called in the last second. + static const auto oneSecond = TimeDuration::FromSeconds(1); + return !lastAnimationTime.IsNull() && + currentTime < (lastAnimationTime + oneSecond); +} + bool GCRuntime::shouldCompact() { // Compact on shrinking GC if enabled. Skip compacting in incremental GCs // if we are currently animating, unless the user is inactive or we're // responding to memory pressure. - static const auto oneSecond = TimeDuration::FromSeconds(1); - if (invocationKind != GC_SHRINK || !isCompactingGCEnabled()) { return false; } @@ -2224,9 +2231,8 @@ bool GCRuntime::shouldCompact() { return true; } - const auto& lastAnimationTime = rt->lastAnimationTime.ref(); - return !isIncremental || lastAnimationTime.IsNull() || - lastAnimationTime + oneSecond < TimeStamp::Now(); + return !isIncremental || + !IsCurrentlyAnimating(rt->lastAnimationTime, TimeStamp::Now()); } bool GCRuntime::isCompactingGCEnabled() const { @@ -4113,8 +4119,6 @@ bool GCRuntime::shouldPreserveJITCode(Realm* realm, const TimeStamp& currentTime, JS::GCReason reason, bool canAllocateMoreCode) { - static const auto oneSecond = TimeDuration::FromSeconds(1); - if (cleanUpEverything) { return false; } @@ -4129,9 +4133,7 @@ bool GCRuntime::shouldPreserveJITCode(Realm* realm, return true; } - const auto& lastAnimationTime = realm->lastAnimationTime.ref(); - if (!lastAnimationTime.IsNull() && - lastAnimationTime + oneSecond >= currentTime) { + if (IsCurrentlyAnimating(realm->lastAnimationTime, currentTime)) { return true; } @@ -6899,7 +6901,7 @@ void GCRuntime::finishCollection() { clearBufferedGrayRoots(); auto currentTime = ReallyNow(); - schedulingState.updateHighFrequencyMode(lastGCTime, currentTime, tunables); + schedulingState.updateHighFrequencyMode(lastGCTime_, currentTime, tunables); for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { if (zone->isCollecting()) { @@ -6916,7 +6918,7 @@ void GCRuntime::finishCollection() { MOZ_ASSERT(zonesToMaybeCompact.ref().isEmpty()); MOZ_ASSERT(cellsToAssertNotGray.ref().empty()); - lastGCTime = currentTime; + lastGCTime_ = currentTime; } static const char* HeapStateToLabel(JS::HeapState heapState) { diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 90d1a6bf6f0e4..7f353202a1058 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -432,6 +432,8 @@ class GCRuntime { bool areGrayBitsValid() const { return grayBitsValid; } void setGrayBitsInvalid() { grayBitsValid = false; } + mozilla::TimeStamp lastGCTime() const { return lastGCTime_; } + bool majorGCRequested() const { return majorGCTriggerReason != JS::GCReason::NO_REASON; } @@ -775,7 +777,7 @@ class GCRuntime { private: UnprotectedData chunkAllocationSinceLastGC; - MainThreadData lastGCTime; + MainThreadData lastGCTime_; /* * JSGC_MODE @@ -1130,6 +1132,9 @@ inline bool GCRuntime::needZealousGC() { return false; } inline bool GCRuntime::hasIncrementalTwoSliceZealMode() { return false; } #endif +bool IsCurrentlyAnimating(const mozilla::TimeStamp& lastAnimationTime, + const mozilla::TimeStamp& currentTime); + } /* namespace gc */ } /* namespace js */ diff --git a/js/src/gc/Statistics.cpp b/js/src/gc/Statistics.cpp index 3e23e6d9a46e4..b16884b662a4b 100644 --- a/js/src/gc/Statistics.cpp +++ b/js/src/gc/Statistics.cpp @@ -979,15 +979,20 @@ void Statistics::printStats() { fflush(gcTimerFile); } -void Statistics::beginGC(JSGCInvocationKind kind) { +void Statistics::beginGC(JSGCInvocationKind kind, + const TimeStamp& currentTime) { slices_.clearAndFree(); sccTimes.clearAndFree(); gckind = kind; nonincrementalReason_ = gc::AbortReason::None; - preHeapSize = runtime->gc.heapSize.gcBytes(); - startingMajorGCNumber = runtime->gc.majorGCCount(); - startingSliceNumber = runtime->gc.gcNumber(); + GCRuntime& gc = runtime->gc; + preHeapSize = gc.heapSize.gcBytes(); + startingMajorGCNumber = gc.majorGCCount(); + startingSliceNumber = gc.gcNumber(); + if (gc.lastGCTime()) { + timeSinceLastGC = currentTime - gc.lastGCTime(); + } } void Statistics::endGC() { @@ -1017,6 +1022,20 @@ void Statistics::endGC() { runtime->addTelemetry(JS_TELEMETRY_GC_NON_INCREMENTAL_REASON, uint32_t(nonincrementalReason_)); } + +#ifdef DEBUG + // Reset happens non-incrementally, so only the last slice can be reset. + for (size_t i = 0; i < slices_.length() - 1; i++) { + MOZ_ASSERT(!slices_[i].wasReset()); + } +#endif + const auto& lastSlice = slices_.back(); + runtime->addTelemetry(JS_TELEMETRY_GC_RESET, lastSlice.wasReset()); + if (lastSlice.wasReset()) { + runtime->addTelemetry(JS_TELEMETRY_GC_RESET_REASON, + uint32_t(lastSlice.resetReason)); + } + runtime->addTelemetry(JS_TELEMETRY_GC_INCREMENTAL_DISABLED, !runtime->gc.isIncrementalGCAllowed()); runtime->addTelemetry(JS_TELEMETRY_GC_SCC_SWEEP_TOTAL_MS, t(sccTotal)); @@ -1030,6 +1049,18 @@ void Statistics::endGC() { const double mmu50 = computeMMU(TimeDuration::FromMilliseconds(50)); runtime->addTelemetry(JS_TELEMETRY_GC_MMU_50, mmu50 * 100); + + // Record scheduling telemetry for the main runtime but not for workers, which + // are scheduled differently. + if (!runtime->parentRuntime && timeSinceLastGC) { + runtime->addTelemetry(JS_TELEMETRY_GC_TIME_BETWEEN_S, + timeSinceLastGC.ToSeconds()); + if (!nonincremental()) { + runtime->addTelemetry(JS_TELEMETRY_GC_SLICE_COUNT, + slices_.length()); + } + } + thresholdTriggered = false; } @@ -1061,12 +1092,20 @@ void Statistics::beginSlice(const ZoneGCStats& zoneStats, this->zoneStats = zoneStats; + TimeStamp currentTime = ReallyNow(); + bool first = !runtime->gc.isIncrementalGCInProgress(); if (first) { - beginGC(gckind); + beginGC(gckind, currentTime); } - if (!slices_.emplaceBack(budget, reason, ReallyNow(), GetPageFaultCount(), + if (!runtime->parentRuntime && !slices_.empty()) { + TimeDuration timeSinceLastSlice = currentTime - slices_.back().end; + runtime->addTelemetry(JS_TELEMETRY_GC_TIME_BETWEEN_SLICES_MS, + uint32_t(timeSinceLastSlice.ToMilliseconds())); + } + + if (!slices_.emplaceBack(budget, reason, currentTime, GetPageFaultCount(), runtime->gc.state())) { // If we are OOM, set a flag to indicate we have missing slice data. aborted = true; @@ -1102,16 +1141,11 @@ void Statistics::endSlice() { writeLogMessage("end slice"); TimeDuration sliceTime = slice.end - slice.start; runtime->addTelemetry(JS_TELEMETRY_GC_SLICE_MS, t(sliceTime)); - runtime->addTelemetry(JS_TELEMETRY_GC_RESET, slice.wasReset()); - if (slice.wasReset()) { - runtime->addTelemetry(JS_TELEMETRY_GC_RESET_REASON, - uint32_t(slice.resetReason)); - } if (slice.budget.isTimeBudget()) { int64_t budget_ms = slice.budget.timeBudget.budget; runtime->addTelemetry(JS_TELEMETRY_GC_BUDGET_MS, budget_ms); - if (budget_ms == runtime->gc.defaultSliceBudget()) { + if (IsCurrentlyAnimating(runtime->lastAnimationTime, slice.end)) { runtime->addTelemetry(JS_TELEMETRY_GC_ANIMATION_MS, t(sliceTime)); } diff --git a/js/src/gc/Statistics.h b/js/src/gc/Statistics.h index 2e834a3099e8f..5206c77de200b 100644 --- a/js/src/gc/Statistics.h +++ b/js/src/gc/Statistics.h @@ -372,7 +372,7 @@ struct Statistics { uint64_t startingMajorGCNumber; uint64_t startingSliceNumber; - /* Records the maximum GC pause in an API-controlled interval (in us). */ + /* Records the maximum GC pause in an API-controlled interval. */ mutable TimeDuration maxPauseInInterval; /* Phases that are currently on stack. */ @@ -390,6 +390,8 @@ struct Statistics { /* Sweep times for SCCs of compartments. */ Vector sccTimes; + TimeDuration timeSinceLastGC; + JS::GCSliceCallback sliceCallback; JS::GCNurseryCollectionCallback nurseryCollectionCallback; @@ -420,7 +422,7 @@ struct Statistics { Phase currentPhase() const; Phase lookupChildPhase(PhaseKind phaseKind) const; - void beginGC(JSGCInvocationKind kind); + void beginGC(JSGCInvocationKind kind, const TimeStamp& currentTime); void endGC(); void recordPhaseBegin(Phase phase); diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index cae590cdc4131..ebf8ff8f1074c 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -168,6 +168,9 @@ enum { JS_TELEMETRY_GC_PRETENURE_COUNT, JS_TELEMETRY_GC_NURSERY_PROMOTION_RATE, JS_TELEMETRY_GC_MARK_RATE, + JS_TELEMETRY_GC_TIME_BETWEEN_S, + JS_TELEMETRY_GC_TIME_BETWEEN_SLICES_MS, + JS_TELEMETRY_GC_SLICE_COUNT, JS_TELEMETRY_PRIVILEGED_PARSER_COMPILE_LAZY_AFTER_MS, JS_TELEMETRY_WEB_PARSER_COMPILE_LAZY_AFTER_MS, JS_TELEMETRY_DEPRECATED_ARRAY_GENERICS, diff --git a/js/src/proxy/Proxy.cpp b/js/src/proxy/Proxy.cpp index 78fb2dcef15fd..4f91dce2e9a26 100644 --- a/js/src/proxy/Proxy.cpp +++ b/js/src/proxy/Proxy.cpp @@ -724,7 +724,7 @@ static void proxy_Finalize(FreeOp* fop, JSObject* obj) { obj->as().handler()->finalize(fop, obj); if (!obj->as().usingInlineValueArray()) { - js_free(js::detail::GetProxyDataLayout(obj)->values()); + fop->free_(js::detail::GetProxyDataLayout(obj)->values()); } } diff --git a/js/src/vm/BytecodeUtil.cpp b/js/src/vm/BytecodeUtil.cpp index 8e2be20f9a330..3be6d0c43d8ed 100644 --- a/js/src/vm/BytecodeUtil.cpp +++ b/js/src/vm/BytecodeUtil.cpp @@ -2531,11 +2531,10 @@ extern bool js::IsValidBytecodeOffset(JSContext* cx, JSScript* script, * PurgePCCounts None None None */ -static void ReleaseScriptCounts(FreeOp* fop) { - JSRuntime* rt = fop->runtime(); +static void ReleaseScriptCounts(JSRuntime* rt) { MOZ_ASSERT(rt->scriptAndCountsVector); - fop->delete_(rt->scriptAndCountsVector.ref()); + js_delete(rt->scriptAndCountsVector.ref()); rt->scriptAndCountsVector = nullptr; } @@ -2547,7 +2546,7 @@ JS_FRIEND_API void js::StartPCCountProfiling(JSContext* cx) { } if (rt->scriptAndCountsVector) { - ReleaseScriptCounts(rt->defaultFreeOp()); + ReleaseScriptCounts(rt); } ReleaseAllJITCode(rt->defaultFreeOp()); @@ -2566,7 +2565,7 @@ JS_FRIEND_API void js::StopPCCountProfiling(JSContext* cx) { ReleaseAllJITCode(rt->defaultFreeOp()); auto* vec = cx->new_>( - cx, ScriptAndCountsVector(SystemAllocPolicy())); + cx, ScriptAndCountsVector()); if (!vec) { return; } @@ -2594,7 +2593,7 @@ JS_FRIEND_API void js::PurgePCCounts(JSContext* cx) { } MOZ_ASSERT(!rt->profilingScripts); - ReleaseScriptCounts(rt->defaultFreeOp()); + ReleaseScriptCounts(rt); } JS_FRIEND_API size_t js::GetPCCountScriptCount(JSContext* cx) { diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp index ad1a6b7fc4d40..65af4b76c5553 100644 --- a/js/src/vm/RegExpObject.cpp +++ b/js/src/vm/RegExpObject.cpp @@ -928,7 +928,7 @@ void RegExpShared::discardJitCode() { void RegExpShared::finalize(FreeOp* fop) { for (auto& comp : compilationArray) { - js_free(comp.byteCode); + fop->free_(comp.byteCode); } tables.~JitCodeTables(); } diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index 20e0f1a9c8510..0e0214381f89b 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -166,7 +166,7 @@ void TypedArrayObject::finalize(FreeOp* fop, JSObject* obj) { // Free the data slot pointer if it does not point into the old JSObject. if (!curObj->hasInlineElements()) { - js_free(curObj->elements()); + fop->free_(curObj->elements()); } } diff --git a/js/src/wasm/WasmJS.cpp b/js/src/wasm/WasmJS.cpp index 2f29bf72437c4..b248d6798c77e 100644 --- a/js/src/wasm/WasmJS.cpp +++ b/js/src/wasm/WasmJS.cpp @@ -2349,10 +2349,10 @@ void WasmGlobalObject::trace(JSTracer* trc, JSObject* obj) { } /* static */ -void WasmGlobalObject::finalize(FreeOp*, JSObject* obj) { +void WasmGlobalObject::finalize(FreeOp* fop, JSObject* obj) { WasmGlobalObject* global = reinterpret_cast(obj); if (!global->isNewborn()) { - js_delete(global->cell()); + fop->delete_(global->cell()); } } diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 00ea8a8d0dc4b..e1136499e2610 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -2734,6 +2734,21 @@ static void AccumulateTelemetryCallback(int id, uint32_t sample, case JS_TELEMETRY_GC_PRETENURE_COUNT: Telemetry::Accumulate(Telemetry::GC_PRETENURE_COUNT, sample); break; + case JS_TELEMETRY_GC_NURSERY_PROMOTION_RATE: + Telemetry::Accumulate(Telemetry::GC_NURSERY_PROMOTION_RATE, sample); + break; + case JS_TELEMETRY_GC_MARK_RATE: + Telemetry::Accumulate(Telemetry::GC_MARK_RATE, sample); + break; + case JS_TELEMETRY_GC_TIME_BETWEEN_S: + Telemetry::Accumulate(Telemetry::GC_TIME_BETWEEN_S, sample); + break; + case JS_TELEMETRY_GC_TIME_BETWEEN_SLICES_MS: + Telemetry::Accumulate(Telemetry::GC_TIME_BETWEEN_SLICES_MS, sample); + break; + case JS_TELEMETRY_GC_SLICE_COUNT: + Telemetry::Accumulate(Telemetry::GC_SLICE_COUNT, sample); + break; case JS_TELEMETRY_PRIVILEGED_PARSER_COMPILE_LAZY_AFTER_MS: Telemetry::Accumulate( Telemetry::JS_PRIVILEGED_PARSER_COMPILE_LAZY_AFTER_MS, sample); @@ -2742,12 +2757,6 @@ static void AccumulateTelemetryCallback(int id, uint32_t sample, Telemetry::Accumulate(Telemetry::JS_WEB_PARSER_COMPILE_LAZY_AFTER_MS, sample); break; - case JS_TELEMETRY_GC_NURSERY_PROMOTION_RATE: - Telemetry::Accumulate(Telemetry::GC_NURSERY_PROMOTION_RATE, sample); - break; - case JS_TELEMETRY_GC_MARK_RATE: - Telemetry::Accumulate(Telemetry::GC_MARK_RATE, sample); - break; case JS_TELEMETRY_DEPRECATED_ARRAY_GENERICS: Telemetry::Accumulate(Telemetry::JS_DEPRECATED_ARRAY_GENERICS, sample); break; diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp index 90edbf4479104..c30bfba3015ae 100644 --- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp @@ -67,7 +67,7 @@ #include "nsWindowSizes.h" #include "nsCOMPtr.h" #include "nsReadableUtils.h" -#include "nsIPageSequenceFrame.h" +#include "nsPageSequenceFrame.h" #include "nsIPermissionManager.h" #include "nsIMozBrowserFrame.h" #include "nsCaret.h" @@ -2440,9 +2440,8 @@ nsIScrollableFrame* PresShell::GetRootScrollFrameAsScrollable() const { return scrollableFrame; } -nsIPageSequenceFrame* PresShell::GetPageSequenceFrame() const { - nsIFrame* frame = mFrameConstructor->GetPageSequenceFrame(); - return do_QueryFrame(frame); +nsPageSequenceFrame* PresShell::GetPageSequenceFrame() const { + return mFrameConstructor->GetPageSequenceFrame(); } nsCanvasFrame* PresShell::GetCanvasFrame() const { diff --git a/layout/base/PresShell.h b/layout/base/PresShell.h index c83b3cc4d32ae..d4ea7fc70acbf 100644 --- a/layout/base/PresShell.h +++ b/layout/base/PresShell.h @@ -80,7 +80,7 @@ class nsIDocShell; class nsIFrame; class nsILayoutHistoryState; class nsINode; -class nsIPageSequenceFrame; +class nsPageSequenceFrame; class nsIReflowCallback; class nsIScrollableFrame; class nsITimer; @@ -453,7 +453,7 @@ class PresShell final : public nsStubDocumentObserver, * Returns the page sequence frame associated with the frame hierarchy. * Returns nullptr if not a paginated view. */ - nsIPageSequenceFrame* GetPageSequenceFrame() const; + nsPageSequenceFrame* GetPageSequenceFrame() const; /** * Returns the canvas frame associated with the frame hierarchy. diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 6ee53ade871d2..be39205afc39e 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -99,7 +99,7 @@ #include "nsFirstLetterFrame.h" #include "nsGfxScrollFrame.h" #include "nsPageFrame.h" -#include "nsSimplePageSequenceFrame.h" +#include "nsPageSequenceFrame.h" #include "nsTableWrapperFrame.h" #include "nsIScrollableFrame.h" #include "nsBackdropFrame.h" @@ -2517,7 +2517,7 @@ void nsCSSFrameConstructor::SetUpDocElementContainingBlock( Print presentation, non-XUL ViewportFrame - nsSimplePageSequenceFrame + nsPageSequenceFrame nsPageFrame nsPageContentFrame [fixed-cb] nsCanvasFrame [abs-cb] @@ -2528,7 +2528,7 @@ void nsCSSFrameConstructor::SetUpDocElementContainingBlock( ViewportFrame nsHTMLScrollFrame - nsSimplePageSequenceFrame + nsPageSequenceFrame nsPageFrame nsPageContentFrame [fixed-cb] nsCanvasFrame [abs-cb] @@ -2544,7 +2544,7 @@ void nsCSSFrameConstructor::SetUpDocElementContainingBlock( the root element. mDocElementContainingBlock is the parent of mRootElementFrame (i.e. nsCanvasFrame or nsRootBoxFrame) - mPageSequenceFrame is the nsSimplePageSequenceFrame, or null if there isn't + mPageSequenceFrame is the nsPageSequenceFrame, or null if there isn't one */ @@ -2584,8 +2584,8 @@ void nsCSSFrameConstructor::SetUpDocElementContainingBlock( mDocElementContainingBlock = rootFrame; } else { // Create a page sequence frame - rootFrame = NS_NewSimplePageSequenceFrame(mPresShell, viewportPseudoStyle); - mPageSequenceFrame = rootFrame; + rootFrame = mPageSequenceFrame = + NS_NewPageSequenceFrame(mPresShell, viewportPseudoStyle); rootPseudo = PseudoStyleType::pageSequence; rootFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES); } diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h index 6f44f8a5382df..fbb5816c496c4 100644 --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -34,6 +34,7 @@ class nsContainerFrame; class nsFirstLineFrame; class nsFirstLetterFrame; class nsCSSAnonBoxPseudoStaticAtom; +class nsPageSequenceFrame; class nsPageContentFrame; struct PendingBinding; @@ -342,7 +343,7 @@ class nsCSSFrameConstructor final : public nsFrameManager { // This returns the frame for the root element that does not // have a psuedo-element style nsIFrame* GetRootElementStyleFrame() { return mRootElementStyleFrame; } - nsIFrame* GetPageSequenceFrame() { return mPageSequenceFrame; } + nsPageSequenceFrame* GetPageSequenceFrame() { return mPageSequenceFrame; } // Get the frame that is the parent of the root element. nsContainerFrame* GetDocElementContainingBlock() { @@ -2125,7 +2126,7 @@ class nsCSSFrameConstructor final : public nsFrameManager { // This is the containing block that contains the root element --- // the real "initial containing block" according to CSS 2.1. nsContainerFrame* mDocElementContainingBlock; - nsIFrame* mPageSequenceFrame; + nsPageSequenceFrame* mPageSequenceFrame; // FrameConstructionItem arena + list of freed items available for re-use. mozilla::ArenaAllocator<4096, 8> mFCItemPool; diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index e88c878f1d78f..5d6954c57fdf7 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -49,7 +49,7 @@ #include "nsViewManager.h" #include "nsView.h" -#include "nsIPageSequenceFrame.h" +#include "nsPageSequenceFrame.h" #include "nsNetUtil.h" #include "nsIContentViewerEdit.h" #include "mozilla/css/Loader.h" @@ -2796,7 +2796,7 @@ nsDocumentViewer::SetFullZoom(float aFullZoom) { mPrintPreviewZoom = aFullZoom; pc->SetPrintPreviewScale(aFullZoom * mOriginalPrintPreviewScale); - nsIPageSequenceFrame* pf = presShell->GetPageSequenceFrame(); + nsPageSequenceFrame* pf = presShell->GetPageSequenceFrame(); if (pf) { nsIFrame* f = do_QueryFrame(pf); presShell->FrameNeedsReflow(f, IntrinsicDirty::Resize, NS_FRAME_IS_DIRTY); @@ -3644,7 +3644,6 @@ nsDocumentViewer::PrintPreviewNavigate(int16_t aType, int32_t aPageNum) { return NS_OK; } - // Finds the SimplePageSequencer frame // in PP mPrtPreview->mPrintObject->mSeqFrame is null nsIFrame* seqFrame = nullptr; int32_t pageCount = 0; @@ -3781,19 +3780,6 @@ nsDocumentViewer::EnumerateDocumentNames(uint32_t* aCount, # endif } -NS_IMETHODIMP -nsDocumentViewer::GetIsFramesetFrameSelected(bool* aIsFramesetFrameSelected) { -# ifdef NS_PRINTING - *aIsFramesetFrameSelected = false; - NS_ENSURE_TRUE(mPrintJob, NS_ERROR_FAILURE); - - *aIsFramesetFrameSelected = mPrintJob->IsFramesetFrameSelected(); - return NS_OK; -# else - return NS_ERROR_FAILURE; -# endif -} - NS_IMETHODIMP nsDocumentViewer::GetPrintPreviewNumPages(int32_t* aPrintPreviewNumPages) { # ifdef NS_PRINTING @@ -3807,19 +3793,6 @@ nsDocumentViewer::GetPrintPreviewNumPages(int32_t* aPrintPreviewNumPages) { # endif } -NS_IMETHODIMP -nsDocumentViewer::GetIsFramesetDocument(bool* aIsFramesetDocument) { -# ifdef NS_PRINTING - *aIsFramesetDocument = false; - NS_ENSURE_TRUE(mPrintJob, NS_ERROR_FAILURE); - - *aIsFramesetDocument = mPrintJob->IsFramesetDocument(); - return NS_OK; -# else - return NS_ERROR_FAILURE; -# endif -} - NS_IMETHODIMP nsDocumentViewer::GetIsIFrameSelected(bool* aIsIFrameSelected) { # ifdef NS_PRINTING diff --git a/layout/generic/FrameClasses.py b/layout/generic/FrameClasses.py index 2fa0c102412cc..c00dea5ab9c2c 100644 --- a/layout/generic/FrameClasses.py +++ b/layout/generic/FrameClasses.py @@ -95,7 +95,7 @@ Frame("nsScrollbarButtonFrame", "Box", NOT_LEAF), Frame("nsScrollbarFrame", "Scrollbar", NOT_LEAF), Frame("nsSelectsAreaFrame", "Block", NOT_LEAF), - Frame("nsSimplePageSequenceFrame", "Sequence", NOT_LEAF), + Frame("nsPageSequenceFrame", "Sequence", NOT_LEAF), Frame("nsSliderFrame", "Slider", NOT_LEAF), Frame("nsSplitterFrame", "Box", NOT_LEAF), Frame("nsStackFrame", "Box", NOT_LEAF), @@ -168,7 +168,6 @@ AbstractFrame("nsIMathMLFrame"), AbstractFrame("nsIMenuFrame"), AbstractFrame("nsIObjectFrame"), - AbstractFrame("nsIPageSequenceFrame"), AbstractFrame("nsIPercentBSizeObserver"), AbstractFrame("nsIPopupContainer"), AbstractFrame("nsIScrollableFrame"), diff --git a/layout/generic/FrameIdList.h b/layout/generic/FrameIdList.h index 8d82b4f335a73..1a392513a84fa 100644 --- a/layout/generic/FrameIdList.h +++ b/layout/generic/FrameIdList.h @@ -93,7 +93,7 @@ FRAME_ID(nsRubyTextFrame, RubyText, NotLeaf) FRAME_ID(nsScrollbarButtonFrame, Box, NotLeaf) FRAME_ID(nsScrollbarFrame, Scrollbar, NotLeaf) FRAME_ID(nsSelectsAreaFrame, Block, NotLeaf) -FRAME_ID(nsSimplePageSequenceFrame, Sequence, NotLeaf) +FRAME_ID(nsPageSequenceFrame, Sequence, NotLeaf) FRAME_ID(nsSliderFrame, Slider, NotLeaf) FRAME_ID(nsSplitterFrame, Box, NotLeaf) FRAME_ID(nsStackFrame, Box, NotLeaf) @@ -174,7 +174,6 @@ ABSTRACT_FRAME_ID(nsIListControlFrame) ABSTRACT_FRAME_ID(nsIMathMLFrame) ABSTRACT_FRAME_ID(nsIMenuFrame) ABSTRACT_FRAME_ID(nsIObjectFrame) -ABSTRACT_FRAME_ID(nsIPageSequenceFrame) ABSTRACT_FRAME_ID(nsIPercentBSizeObserver) ABSTRACT_FRAME_ID(nsIPopupContainer) ABSTRACT_FRAME_ID(nsIScrollableFrame) diff --git a/layout/generic/moz.build b/layout/generic/moz.build index 113d8669796ae..80b0297b4ca75 100644 --- a/layout/generic/moz.build +++ b/layout/generic/moz.build @@ -106,10 +106,10 @@ EXPORTS += [ 'nsIFrameInlines.h', 'nsILineIterator.h', 'nsIObjectFrame.h', - 'nsIPageSequenceFrame.h', 'nsIScrollableFrame.h', 'nsIScrollPositionListener.h', 'nsIStatefulFrame.h', + 'nsPageSequenceFrame.h', 'nsPluginFrame.h', 'nsQueryFrame.h', 'nsRubyBaseContainerFrame.h', @@ -189,6 +189,7 @@ UNIFIED_SOURCES += [ 'nsLineLayout.cpp', 'nsPageContentFrame.cpp', 'nsPageFrame.cpp', + 'nsPageSequenceFrame.cpp', 'nsPlaceholderFrame.cpp', 'nsRubyBaseContainerFrame.cpp', 'nsRubyBaseFrame.cpp', @@ -196,7 +197,6 @@ UNIFIED_SOURCES += [ 'nsRubyFrame.cpp', 'nsRubyTextContainerFrame.cpp', 'nsRubyTextFrame.cpp', - 'nsSimplePageSequenceFrame.cpp', 'nsSplittableFrame.cpp', 'nsSubDocumentFrame.cpp', 'nsTextFrame.cpp', diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 8c173851fb150..788d4fd713c48 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -745,7 +745,11 @@ nscoord nsBlockFrame::GetMinISize(gfxContext* aRenderingContext) { curFrame->LazyMarkLinesDirty(); } - if (GetStateBits() & NS_BLOCK_NEEDS_BIDI_RESOLUTION) ResolveBidi(); + if (GetStateBits() & NS_BLOCK_NEEDS_BIDI_RESOLUTION) { + ResolveBidi(); + } + + const bool whiteSpaceCanWrap = StyleText()->WhiteSpaceCanWrapStyle(); InlineMinISizeData data; for (nsBlockFrame* curFrame = this; curFrame; curFrame = static_cast(curFrame->GetNextContinuation())) { @@ -776,7 +780,7 @@ nscoord nsBlockFrame::GetMinISize(gfxContext* aRenderingContext) { for (int32_t i = 0, i_end = line->GetChildCount(); i != i_end; ++i, kid = kid->GetNextSibling()) { kid->AddInlineMinISize(aRenderingContext, &data); - if (data.mTrailingWhitespace) { + if (whiteSpaceCanWrap && data.mTrailingWhitespace) { data.OptionallyBreak(); } } diff --git a/layout/generic/nsHTMLParts.h b/layout/generic/nsHTMLParts.h index d4dd3fb1063c5..57edf9668248d 100644 --- a/layout/generic/nsHTMLParts.h +++ b/layout/generic/nsHTMLParts.h @@ -112,9 +112,9 @@ nsContainerFrame* NS_NewColumnSetFrame(mozilla::PresShell* aPresShell, mozilla::ComputedStyle* aStyle, nsFrameState aStateFlags); -class nsSimplePageSequenceFrame; -nsSimplePageSequenceFrame* NS_NewSimplePageSequenceFrame( - mozilla::PresShell* aPresShell, mozilla::ComputedStyle* aStyle); +class nsPageSequenceFrame; +nsPageSequenceFrame* NS_NewPageSequenceFrame(mozilla::PresShell* aPresShell, + mozilla::ComputedStyle* aStyle); class nsPageFrame; nsPageFrame* NS_NewPageFrame(mozilla::PresShell* aPresShell, mozilla::ComputedStyle* aStyle); diff --git a/layout/generic/nsIPageSequenceFrame.h b/layout/generic/nsIPageSequenceFrame.h deleted file mode 100644 index 3670a1481bb88..0000000000000 --- a/layout/generic/nsIPageSequenceFrame.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- 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 nsIPageSequenceFrame_h___ -#define nsIPageSequenceFrame_h___ - -#include "nsQueryFrame.h" -#include "nsCoord.h" - -class nsPresContext; -class nsIPrintSettings; -class nsITimerCallback; - -/** - * Interface for accessing special capabilities of the page sequence frame. - * - * Today all that exists are member functions for printing. - */ -class nsIPageSequenceFrame : public nsQueryFrame { - public: - NS_DECL_QUERYFRAME_TARGET(nsIPageSequenceFrame) - - /** - * Print the set of pages. - * - * @param aPrintOptions options for printing - * @param aStatusCallback interface that the client provides to receive - * progress notifications. Can be nullptr - * @return NS_OK if successful - * NS_ERROR_ABORT if the client cancels printing using the callback - * interface - * NS_ERROR_INVALID_ARG if printing a range of pages (not all pages) - * and the start page is greater than the total number of pages - * NS_ERROR_FAILURE if there is an error - */ - NS_IMETHOD StartPrint(nsPresContext* aPresContext, - nsIPrintSettings* aPrintOptions, - const nsAString& aDocTitle, - const nsAString& aDocURL) = 0; - - NS_IMETHOD PrePrintNextPage(nsITimerCallback* aCallback, bool* aDone) = 0; - NS_IMETHOD PrintNextPage() = 0; - NS_IMETHOD ResetPrintCanvasList() = 0; - NS_IMETHOD GetCurrentPageNum(int32_t* aPageNum) = 0; - NS_IMETHOD GetNumPages(int32_t* aNumPages) = 0; - NS_IMETHOD IsDoingPrintRange(bool* aDoing) = 0; - NS_IMETHOD GetPrintRange(int32_t* aFromPage, int32_t* aToPage) = 0; - - NS_IMETHOD DoPageEnd() = 0; - - // For Shrink To Fit - NS_IMETHOD GetSTFPercent(float& aSTFPercent) = 0; -}; - -#endif /* nsIPageSequenceFrame_h___ */ diff --git a/layout/generic/nsPageContentFrame.cpp b/layout/generic/nsPageContentFrame.cpp index a8937c72ad828..9b2623df21df2 100644 --- a/layout/generic/nsPageContentFrame.cpp +++ b/layout/generic/nsPageContentFrame.cpp @@ -10,7 +10,7 @@ #include "nsCSSFrameConstructor.h" #include "nsPresContext.h" #include "nsGkAtoms.h" -#include "nsSimplePageSequenceFrame.h" +#include "nsPageSequenceFrame.h" using namespace mozilla; diff --git a/layout/generic/nsPageFrame.cpp b/layout/generic/nsPageFrame.cpp index a7add79dd7672..e6aacca5cd069 100644 --- a/layout/generic/nsPageFrame.cpp +++ b/layout/generic/nsPageFrame.cpp @@ -16,8 +16,8 @@ #include "nsGkAtoms.h" #include "nsPageContentFrame.h" #include "nsDisplayList.h" -#include "nsSimplePageSequenceFrame.h" // for nsSharedPageData -#include "nsTextFormatter.h" // for page number localization formatting +#include "nsPageSequenceFrame.h" // for nsSharedPageData +#include "nsTextFormatter.h" // for page number localization formatting #include "nsBidiUtils.h" #include "nsIPrintSettings.h" diff --git a/layout/generic/nsSimplePageSequenceFrame.cpp b/layout/generic/nsPageSequenceFrame.cpp similarity index 85% rename from layout/generic/nsSimplePageSequenceFrame.cpp rename to layout/generic/nsPageSequenceFrame.cpp index 56c034c23c55d..7cfe9c17770b5 100644 --- a/layout/generic/nsSimplePageSequenceFrame.cpp +++ b/layout/generic/nsPageSequenceFrame.cpp @@ -4,7 +4,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "nsSimplePageSequenceFrame.h" +#include "nsPageSequenceFrame.h" #include "mozilla/PresShell.h" #include "mozilla/dom/HTMLCanvasElement.h" @@ -37,16 +37,16 @@ mozilla::LazyLogModule gLayoutPrintingLog("printing-layout"); #define PR_PL(_p1) MOZ_LOG(gLayoutPrintingLog, mozilla::LogLevel::Debug, _p1) -nsSimplePageSequenceFrame* NS_NewSimplePageSequenceFrame( - PresShell* aPresShell, ComputedStyle* aStyle) { +nsPageSequenceFrame* NS_NewPageSequenceFrame(PresShell* aPresShell, + ComputedStyle* aStyle) { return new (aPresShell) - nsSimplePageSequenceFrame(aStyle, aPresShell->GetPresContext()); + nsPageSequenceFrame(aStyle, aPresShell->GetPresContext()); } -NS_IMPL_FRAMEARENA_HELPERS(nsSimplePageSequenceFrame) +NS_IMPL_FRAMEARENA_HELPERS(nsPageSequenceFrame) -nsSimplePageSequenceFrame::nsSimplePageSequenceFrame( - ComputedStyle* aStyle, nsPresContext* aPresContext) +nsPageSequenceFrame::nsPageSequenceFrame(ComputedStyle* aStyle, + nsPresContext* aPresContext) : nsContainerFrame(aStyle, aPresContext, kClassID), mTotalPages(-1), mCalledBeginPage(false), @@ -67,21 +67,20 @@ nsSimplePageSequenceFrame::nsSimplePageSequenceFrame( SetPageNumberFormat("pageofpages", "%1$d of %2$d", false); } -nsSimplePageSequenceFrame::~nsSimplePageSequenceFrame() { +nsPageSequenceFrame::~nsPageSequenceFrame() { delete mPageData; ResetPrintCanvasList(); } -NS_QUERYFRAME_HEAD(nsSimplePageSequenceFrame) - NS_QUERYFRAME_ENTRY(nsIPageSequenceFrame) +NS_QUERYFRAME_HEAD(nsPageSequenceFrame) + NS_QUERYFRAME_ENTRY(nsPageSequenceFrame) NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame) //---------------------------------------------------------------------- -void nsSimplePageSequenceFrame::SetDesiredSize(ReflowOutput& aDesiredSize, - const ReflowInput& aReflowInput, - nscoord aWidth, - nscoord aHeight) { +void nsPageSequenceFrame::SetDesiredSize(ReflowOutput& aDesiredSize, + const ReflowInput& aReflowInput, + nscoord aWidth, nscoord aHeight) { // Aim to fill the whole size of the document, not only so we // can act as a background in print preview but also handle overflow // in child page frames correctly. @@ -99,7 +98,7 @@ void nsSimplePageSequenceFrame::SetDesiredSize(ReflowOutput& aDesiredSize, // Helper function to compute the offset needed to center a child // page-frame's margin-box inside our content-box. -nscoord nsSimplePageSequenceFrame::ComputeCenteringMargin( +nscoord nsPageSequenceFrame::ComputeCenteringMargin( nscoord aContainerContentBoxWidth, nscoord aChildPaddingBoxWidth, const nsMargin& aChildPhysicalMargin) { // We'll be centering our child's margin-box, so get the size of that: @@ -136,17 +135,17 @@ nscoord nsSimplePageSequenceFrame::ComputeCenteringMargin( * \*physical\* x/y/width/height values, because the print preview UI is always * arranged in the same orientation, regardless of writing mode. */ -void nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext, - ReflowOutput& aDesiredSize, - const ReflowInput& aReflowInput, - nsReflowStatus& aStatus) { +void nsPageSequenceFrame::Reflow(nsPresContext* aPresContext, + ReflowOutput& aDesiredSize, + const ReflowInput& aReflowInput, + nsReflowStatus& aStatus) { MarkInReflow(); MOZ_ASSERT(aPresContext->IsRootPaginatedDocument(), "A Page Sequence is only for real pages"); - DO_GLOBAL_REFLOW_COUNT("nsSimplePageSequenceFrame"); + DO_GLOBAL_REFLOW_COUNT("nsPageSequenceFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); - NS_FRAME_TRACE_REFLOW_IN("nsSimplePageSequenceFrame::Reflow"); + NS_FRAME_TRACE_REFLOW_IN("nsPageSequenceFrame::Reflow"); // Don't do incremental reflow until we've taught tables how to do // it right in paginated mode. @@ -317,59 +316,31 @@ void nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext, mSize.width = maxXMost; mSize.height = y; - NS_FRAME_TRACE_REFLOW_OUT("nsSimplePageSequeceFrame::Reflow", aStatus); + NS_FRAME_TRACE_REFLOW_OUT("nsPageSequenceFrame::Reflow", aStatus); NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize); } //---------------------------------------------------------------------- #ifdef DEBUG_FRAME_DUMP -nsresult nsSimplePageSequenceFrame::GetFrameName(nsAString& aResult) const { - return MakeFrameName(NS_LITERAL_STRING("SimplePageSequence"), aResult); +nsresult nsPageSequenceFrame::GetFrameName(nsAString& aResult) const { + return MakeFrameName(NS_LITERAL_STRING("PageSequence"), aResult); } #endif //==================================================================== //== Asynch Printing //==================================================================== -NS_IMETHODIMP -nsSimplePageSequenceFrame::GetCurrentPageNum(int32_t* aPageNum) { - NS_ENSURE_ARG_POINTER(aPageNum); - - *aPageNum = mPageNum; - return NS_OK; -} - -NS_IMETHODIMP -nsSimplePageSequenceFrame::GetNumPages(int32_t* aNumPages) { - NS_ENSURE_ARG_POINTER(aNumPages); - - *aNumPages = mTotalPages; - return NS_OK; -} - -NS_IMETHODIMP -nsSimplePageSequenceFrame::IsDoingPrintRange(bool* aDoing) { - NS_ENSURE_ARG_POINTER(aDoing); - - *aDoing = mDoingPageRange; - return NS_OK; -} - -NS_IMETHODIMP -nsSimplePageSequenceFrame::GetPrintRange(int32_t* aFromPage, int32_t* aToPage) { - NS_ENSURE_ARG_POINTER(aFromPage); - NS_ENSURE_ARG_POINTER(aToPage); - +void nsPageSequenceFrame::GetPrintRange(int32_t* aFromPage, + int32_t* aToPage) const { *aFromPage = mFromPageNum; *aToPage = mToPageNum; - return NS_OK; } // Helper Function -void nsSimplePageSequenceFrame::SetPageNumberFormat(const char* aPropName, - const char* aDefPropVal, - bool aPageNumOnly) { +void nsPageSequenceFrame::SetPageNumberFormat(const char* aPropName, + const char* aDefPropVal, + bool aPageNumOnly) { // Doing this here so we only have to go get these formats once nsAutoString pageNumberFormat; // Now go get the Localized Page Formating String @@ -382,11 +353,10 @@ void nsSimplePageSequenceFrame::SetPageNumberFormat(const char* aPropName, SetPageNumberFormat(pageNumberFormat, aPageNumOnly); } -NS_IMETHODIMP -nsSimplePageSequenceFrame::StartPrint(nsPresContext* aPresContext, - nsIPrintSettings* aPrintSettings, - const nsAString& aDocTitle, - const nsAString& aDocURL) { +nsresult nsPageSequenceFrame::StartPrint(nsPresContext* aPresContext, + nsIPrintSettings* aPrintSettings, + const nsAString& aDocTitle, + const nsAString& aDocURL) { NS_ENSURE_ARG_POINTER(aPresContext); NS_ENSURE_ARG_POINTER(aPrintSettings); @@ -466,7 +436,7 @@ static void GetPrintCanvasElementsInFrame( } } -void nsSimplePageSequenceFrame::DetermineWhetherToPrintPage() { +void nsPageSequenceFrame::DetermineWhetherToPrintPage() { // See whether we should print this page mPrintThisPage = true; bool printEvenPages, printOddPages; @@ -514,7 +484,7 @@ void nsSimplePageSequenceFrame::DetermineWhetherToPrintPage() { } } -nsIFrame* nsSimplePageSequenceFrame::GetCurrentPageFrame() { +nsIFrame* nsPageSequenceFrame::GetCurrentPageFrame() { int32_t i = 1; for (nsFrameList::Enumerator childFrames(mFrames); !childFrames.AtEnd(); childFrames.Next()) { @@ -526,9 +496,8 @@ nsIFrame* nsSimplePageSequenceFrame::GetCurrentPageFrame() { return nullptr; } -NS_IMETHODIMP -nsSimplePageSequenceFrame::PrePrintNextPage(nsITimerCallback* aCallback, - bool* aDone) { +nsresult nsPageSequenceFrame::PrePrintNextPage(nsITimerCallback* aCallback, + bool* aDone) { nsIFrame* currentPage = GetCurrentPageFrame(); if (!currentPage) { *aDone = true; @@ -609,8 +578,7 @@ nsSimplePageSequenceFrame::PrePrintNextPage(nsITimerCallback* aCallback, return NS_OK; } -NS_IMETHODIMP -nsSimplePageSequenceFrame::ResetPrintCanvasList() { +void nsPageSequenceFrame::ResetPrintCanvasList() { for (int32_t i = mCurrentCanvasList.Length() - 1; i >= 0; i--) { HTMLCanvasElement* canvas = mCurrentCanvasList[i]; canvas->ResetPrintCallback(); @@ -618,11 +586,9 @@ nsSimplePageSequenceFrame::ResetPrintCanvasList() { mCurrentCanvasList.Clear(); mCurrentCanvasListSetup = false; - return NS_OK; } -NS_IMETHODIMP -nsSimplePageSequenceFrame::PrintNextPage() { +nsresult nsPageSequenceFrame::PrintNextPage() { // Note: When print al the pages or a page range the printed page shows the // actual page number, when printing selection it prints the page number // starting with the first page of the selection. For example if the user has @@ -671,8 +637,7 @@ nsSimplePageSequenceFrame::PrintNextPage() { return rv; } -NS_IMETHODIMP -nsSimplePageSequenceFrame::DoPageEnd() { +nsresult nsPageSequenceFrame::DoPageEnd() { nsresult rv = NS_OK; if (PresContext()->IsRootPaginatedDocument() && mPrintThisPage) { PR_PL(("***************** End Page (DoPageEnd) *****************\n")); @@ -694,8 +659,8 @@ inline gfx::Matrix4x4 ComputePageSequenceTransform(nsIFrame* aFrame, return gfx::Matrix4x4::Scaling(scale, scale, 1); } -void nsSimplePageSequenceFrame::BuildDisplayList( - nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) { +void nsPageSequenceFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, + const nsDisplayListSet& aLists) { aBuilder->SetInPageSequence(true); aBuilder->SetDisablePartialUpdates(true); DisplayBorderBackgroundOutline(aBuilder, aLists); @@ -733,8 +698,8 @@ void nsSimplePageSequenceFrame::BuildDisplayList( } //------------------------------------------------------------------------------ -void nsSimplePageSequenceFrame::SetPageNumberFormat(const nsAString& aFormatStr, - bool aForPageNumOnly) { +void nsPageSequenceFrame::SetPageNumberFormat(const nsAString& aFormatStr, + bool aForPageNumOnly) { NS_ASSERTION(mPageData != nullptr, "mPageData string cannot be null!"); if (aForPageNumOnly) { @@ -745,25 +710,13 @@ void nsSimplePageSequenceFrame::SetPageNumberFormat(const nsAString& aFormatStr, } //------------------------------------------------------------------------------ -void nsSimplePageSequenceFrame::SetDateTimeStr(const nsAString& aDateTimeStr) { +void nsPageSequenceFrame::SetDateTimeStr(const nsAString& aDateTimeStr) { NS_ASSERTION(mPageData != nullptr, "mPageData string cannot be null!"); mPageData->mDateTimeStr = aDateTimeStr; } -//------------------------------------------------------------------------------ -// For Shrink To Fit -// -// Return the percentage that the page needs to shrink to -// -NS_IMETHODIMP -nsSimplePageSequenceFrame::GetSTFPercent(float& aSTFPercent) { - NS_ENSURE_TRUE(mPageData, NS_ERROR_UNEXPECTED); - aSTFPercent = mPageData->mShrinkToFitRatio; - return NS_OK; -} - -void nsSimplePageSequenceFrame::AppendDirectlyOwnedAnonBoxes( +void nsPageSequenceFrame::AppendDirectlyOwnedAnonBoxes( nsTArray& aResult) { if (mFrames.NotEmpty()) { aResult.AppendElement(mFrames.FirstChild()); diff --git a/layout/generic/nsSimplePageSequenceFrame.h b/layout/generic/nsPageSequenceFrame.h similarity index 74% rename from layout/generic/nsSimplePageSequenceFrame.h rename to layout/generic/nsPageSequenceFrame.h index 5e4d63d48f5f0..5dbb93497e95b 100644 --- a/layout/generic/nsSimplePageSequenceFrame.h +++ b/layout/generic/nsPageSequenceFrame.h @@ -3,11 +3,11 @@ /* 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 nsSimplePageSequenceFrame_h___ -#define nsSimplePageSequenceFrame_h___ +#ifndef nsPageSequenceFrame_h___ +#define nsPageSequenceFrame_h___ #include "mozilla/Attributes.h" -#include "nsIPageSequenceFrame.h" +#include "nsPageSequenceFrame.h" #include "nsContainerFrame.h" #include "nsIPrintSettings.h" @@ -25,11 +25,11 @@ class HTMLCanvasElement; //----------------------------------------------- // This class maintains all the data that // is used by all the page frame -// It lives while the nsSimplePageSequenceFrame lives +// It lives while the nsPageSequenceFrame lives class nsSharedPageData { public: // This object a shared by all the nsPageFrames - // parented to a SimplePageSequenceFrame + // parented to a nsPageSequenceFrame nsSharedPageData() : mShrinkToFitRatio(1.0f) {} nsString mDateTimeStr; @@ -55,14 +55,13 @@ class nsSharedPageData { }; // Simple page sequence frame class. Used when we're in paginated mode -class nsSimplePageSequenceFrame final : public nsContainerFrame, - public nsIPageSequenceFrame { +class nsPageSequenceFrame final : public nsContainerFrame { public: - friend nsSimplePageSequenceFrame* NS_NewSimplePageSequenceFrame( + friend nsPageSequenceFrame* NS_NewPageSequenceFrame( mozilla::PresShell* aPresShell, ComputedStyle* aStyle); NS_DECL_QUERYFRAME - NS_DECL_FRAMEARENA_HELPERS(nsSimplePageSequenceFrame) + NS_DECL_FRAMEARENA_HELPERS(nsPageSequenceFrame) // nsIFrame void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize, @@ -73,22 +72,20 @@ class nsSimplePageSequenceFrame final : public nsContainerFrame, const nsDisplayListSet& aLists) override; // For Shrink To Fit - NS_IMETHOD GetSTFPercent(float& aSTFPercent) override; + float GetSTFPercent() const { return mPageData->mShrinkToFitRatio; } // Async Printing - NS_IMETHOD StartPrint(nsPresContext* aPresContext, - nsIPrintSettings* aPrintSettings, - const nsAString& aDocTitle, - const nsAString& aDocURL) override; - NS_IMETHOD PrePrintNextPage(nsITimerCallback* aCallback, - bool* aDone) override; - NS_IMETHOD PrintNextPage() override; - NS_IMETHOD ResetPrintCanvasList() override; - NS_IMETHOD GetCurrentPageNum(int32_t* aPageNum) override; - NS_IMETHOD GetNumPages(int32_t* aNumPages) override; - NS_IMETHOD IsDoingPrintRange(bool* aDoing) override; - NS_IMETHOD GetPrintRange(int32_t* aFromPage, int32_t* aToPage) override; - NS_IMETHOD DoPageEnd() override; + nsresult StartPrint(nsPresContext* aPresContext, + nsIPrintSettings* aPrintSettings, + const nsAString& aDocTitle, const nsAString& aDocURL); + nsresult PrePrintNextPage(nsITimerCallback* aCallback, bool* aDone); + nsresult PrintNextPage(); + void ResetPrintCanvasList(); + int32_t GetCurrentPageNum() const { return mPageNum; } + int32_t GetNumPages() const { return mTotalPages; } + bool IsDoingPrintRange() const { return mDoingPageRange; } + void GetPrintRange(int32_t* aFromPage, int32_t* aToPage) const; + nsresult DoPageEnd(); // We must allow Print Preview UI to have a background, no matter what the // user's settings @@ -106,8 +103,8 @@ class nsSimplePageSequenceFrame final : public nsContainerFrame, #endif protected: - nsSimplePageSequenceFrame(ComputedStyle*, nsPresContext*); - virtual ~nsSimplePageSequenceFrame(); + nsPageSequenceFrame(ComputedStyle*, nsPresContext*); + virtual ~nsPageSequenceFrame(); void SetPageNumberFormat(const char* aPropName, const char* aDefPropVal, bool aPageNumOnly); @@ -154,4 +151,4 @@ class nsSimplePageSequenceFrame final : public nsContainerFrame, bool mCurrentCanvasListSetup; }; -#endif /* nsSimplePageSequenceFrame_h___ */ +#endif /* nsPageSequenceFrame_h___ */ diff --git a/layout/generic/nsSubDocumentFrame.cpp b/layout/generic/nsSubDocumentFrame.cpp index 3fe5f59c896e6..19a185ee7f5fc 100644 --- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -16,7 +16,7 @@ #include "mozilla/StaticPrefs.h" #include "mozilla/dom/Document.h" #include "mozilla/dom/HTMLFrameElement.h" -#include "mozilla/layout/RenderFrame.h" +#include "mozilla/dom/BrowserParent.h" #include "nsCOMPtr.h" #include "nsGenericHTMLElement.h" @@ -45,9 +45,15 @@ #include "nsQueryObject.h" #include "RetainedDisplayListBuilder.h" +#include "Layers.h" +#include "BasicLayers.h" +#include "mozilla/layers/WebRenderUserData.h" +#include "mozilla/layers/WebRenderScrollData.h" +#include "mozilla/layers/RenderRootStateManager.h" + using namespace mozilla; +using namespace mozilla::layers; using mozilla::dom::Document; -using mozilla::layout::RenderFrame; static bool sShowPreviousPage = true; @@ -1337,3 +1343,195 @@ nsIFrame* nsSubDocumentFrame::ObtainIntrinsicSizeFrame() { } return nullptr; } + +/** + * Gets the layer-pixel offset of aContainerFrame's content rect top-left + * from the nearest display item reference frame (which we assume will be + * inducing a ContainerLayer). + */ +static mozilla::LayoutDeviceIntPoint GetContentRectLayerOffset( + nsIFrame* aContainerFrame, nsDisplayListBuilder* aBuilder) { + nscoord auPerDevPixel = aContainerFrame->PresContext()->AppUnitsPerDevPixel(); + + // Offset to the content rect in case we have borders or padding + // Note that aContainerFrame could be a reference frame itself, so + // we need to be careful here to ensure that we call ToReferenceFrame + // on aContainerFrame and not its parent. + nsPoint frameOffset = + aBuilder->ToReferenceFrame(aContainerFrame) + + aContainerFrame->GetContentRectRelativeToSelf().TopLeft(); + + return mozilla::LayoutDeviceIntPoint::FromAppUnitsToNearest(frameOffset, + auPerDevPixel); +} + +// Return true iff |aManager| is a "temporary layer manager". They're +// used for small software rendering tasks, like drawWindow. That's +// currently implemented by a BasicLayerManager without a backing +// widget, and hence in non-retained mode. +inline static bool IsTempLayerManager(LayerManager* aManager) { + return (LayersBackend::LAYERS_BASIC == aManager->GetBackendType() && + !static_cast(aManager)->IsRetained()); +} + +nsDisplayRemote::nsDisplayRemote(nsDisplayListBuilder* aBuilder, + nsSubDocumentFrame* aFrame) + : nsPaintedDisplayItem(aBuilder, aFrame), + mTabId{0}, + mEventRegionsOverride(EventRegionsOverride::NoOverride) { + bool frameIsPointerEventsNone = aFrame->StyleUI()->GetEffectivePointerEvents( + aFrame) == NS_STYLE_POINTER_EVENTS_NONE; + if (aBuilder->IsInsidePointerEventsNoneDoc() || frameIsPointerEventsNone) { + mEventRegionsOverride |= EventRegionsOverride::ForceEmptyHitRegion; + } + if (nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents( + aFrame->PresShell())) { + mEventRegionsOverride |= EventRegionsOverride::ForceDispatchToContent; + } + + nsFrameLoader* frameLoader = GetFrameLoader(); + MOZ_ASSERT(frameLoader && frameLoader->IsRemoteFrame()); + if (frameLoader->GetRemoteBrowser()) { + mLayersId = frameLoader->GetLayersId(); + mTabId = frameLoader->GetRemoteBrowser()->GetTabId(); + } +} + +mozilla::LayerState nsDisplayRemote::GetLayerState( + nsDisplayListBuilder* aBuilder, LayerManager* aManager, + const ContainerLayerParameters& aParameters) { + if (IsTempLayerManager(aManager)) { + return mozilla::LayerState::LAYER_NONE; + } + return mozilla::LayerState::LAYER_ACTIVE_FORCE; +} + +already_AddRefed nsDisplayRemote::BuildLayer( + nsDisplayListBuilder* aBuilder, LayerManager* aManager, + const ContainerLayerParameters& aContainerParameters) { + MOZ_ASSERT(mFrame, "Makes no sense to have a shadow tree without a frame"); + + if (IsTempLayerManager(aManager)) { + // This can happen if aManager is a "temporary" manager, or if the + // widget's layer manager changed out from under us. We need to + // FIXME handle the former case somehow, probably with an API to + // draw a manager's subtree. The latter is bad bad bad, but the the + // MOZ_ASSERT() above will flag it. Returning nullptr here will just + // cause the shadow subtree not to be rendered. + NS_WARNING("Remote iframe not rendered"); + return nullptr; + } + + if (!mLayersId.IsValid()) { + return nullptr; + } + + if (RefPtr remoteBrowser = + GetFrameLoader()->GetRemoteBrowser()) { + // Generate an effects update notifying the browser it is visible + aBuilder->AddEffectUpdate(remoteBrowser, EffectsInfo::FullyVisible()); + // FrameLayerBuilder will take care of notifying the browser when it is no + // longer visible + } + + RefPtr layer = + aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this); + + if (!layer) { + layer = aManager->CreateRefLayer(); + } + if (!layer || !layer->AsRefLayer()) { + // Probably a temporary layer manager that doesn't know how to + // use ref layers. + return nullptr; + } + RefLayer* refLayer = layer->AsRefLayer(); + + LayoutDeviceIntPoint offset = GetContentRectLayerOffset(Frame(), aBuilder); + // We can only have an offset if we're a child of an inactive + // container, but our display item is LAYER_ACTIVE_FORCE which + // forces all layers above to be active. + MOZ_ASSERT(aContainerParameters.mOffset == nsIntPoint()); + Matrix4x4 m = Matrix4x4::Translation(offset.x, offset.y, 0.0); + // Remote content can't be repainted by us, so we multiply down + // the resolution that our container expects onto our container. + m.PreScale(aContainerParameters.mXScale, aContainerParameters.mYScale, 1.0); + refLayer->SetBaseTransform(m); + refLayer->SetEventRegionsOverride(mEventRegionsOverride); + refLayer->SetReferentId(mLayersId); + + return layer.forget(); +} + +void nsDisplayRemote::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) { + DrawTarget* target = aCtx->GetDrawTarget(); + if (!target->IsRecording() || mTabId == 0) { + NS_WARNING("Remote iframe not rendered"); + return; + } + + int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel(); + Rect destRect = mozilla::NSRectToSnappedRect(GetContentRect(), + appUnitsPerDevPixel, *target); + target->DrawDependentSurface(mTabId, destRect); +} + +bool nsDisplayRemote::CreateWebRenderCommands( + mozilla::wr::DisplayListBuilder& aBuilder, + mozilla::wr::IpcResourceUpdateQueue& aResources, + const StackingContextHelper& aSc, + mozilla::layers::RenderRootStateManager* aManager, + nsDisplayListBuilder* aDisplayListBuilder) { + if (!mLayersId.IsValid()) { + return true; + } + + if (RefPtr remoteBrowser = + GetFrameLoader()->GetRemoteBrowser()) { + // Generate an effects update notifying the browser it is visible + aDisplayListBuilder->AddEffectUpdate(remoteBrowser, + EffectsInfo::FullyVisible()); + + // Create a WebRenderRemoteData to notify the RemoteBrowser when it is no + // longer visible + RefPtr userData = + aManager->CommandBuilder() + .CreateOrRecycleWebRenderUserData( + this, aBuilder.GetRenderRoot(), nullptr); + userData->SetRemoteBrowser(remoteBrowser); + } + + mOffset = GetContentRectLayerOffset(mFrame, aDisplayListBuilder); + + LayoutDeviceRect rect = LayoutDeviceRect::FromAppUnits( + mFrame->GetContentRectRelativeToSelf(), + mFrame->PresContext()->AppUnitsPerDevPixel()); + rect += mOffset; + + aBuilder.PushIFrame(mozilla::wr::ToRoundedLayoutRect(rect), + !BackfaceIsHidden(), mozilla::wr::AsPipelineId(mLayersId), + /*ignoreMissingPipelines*/ true); + + return true; +} + +bool nsDisplayRemote::UpdateScrollData( + mozilla::layers::WebRenderScrollData* aData, + mozilla::layers::WebRenderLayerScrollData* aLayerData) { + if (!mLayersId.IsValid()) { + return true; + } + + if (aLayerData) { + aLayerData->SetReferentId(mLayersId); + aLayerData->SetTransform( + mozilla::gfx::Matrix4x4::Translation(mOffset.x, mOffset.y, 0.0)); + aLayerData->SetEventRegionsOverride(mEventRegionsOverride); + } + return true; +} + +nsFrameLoader* nsDisplayRemote::GetFrameLoader() const { + return mFrame ? static_cast(mFrame)->FrameLoader() + : nullptr; +} diff --git a/layout/generic/nsSubDocumentFrame.h b/layout/generic/nsSubDocumentFrame.h index e2a296d588af9..2b4d4a26c374e 100644 --- a/layout/generic/nsSubDocumentFrame.h +++ b/layout/generic/nsSubDocumentFrame.h @@ -7,7 +7,11 @@ #ifndef NSSUBDOCUMENTFRAME_H_ #define NSSUBDOCUMENTFRAME_H_ +#include "Layers.h" +#include "LayerState.h" #include "mozilla/Attributes.h" +#include "mozilla/layers/WebRenderScrollData.h" +#include "nsDisplayList.h" #include "nsAtomicContainerFrame.h" #include "nsIReflowCallback.h" #include "nsFrameLoader.h" @@ -15,9 +19,6 @@ namespace mozilla { class PresShell; -namespace layout { -class RenderFrame; -} } // namespace mozilla /****************************************************************************** @@ -164,4 +165,56 @@ class nsSubDocumentFrame final : public nsAtomicContainerFrame, WeakFrame mPreviousCaret; }; +/** + * A nsDisplayRemote will graft a remote frame's shadow layer tree (for a given + * nsFrameLoader) into its parent frame's layer tree. + */ +class nsDisplayRemote final : public nsPaintedDisplayItem { + typedef mozilla::ContainerLayerParameters ContainerLayerParameters; + typedef mozilla::dom::TabId TabId; + typedef mozilla::gfx::Matrix4x4 Matrix4x4; + typedef mozilla::layers::EventRegionsOverride EventRegionsOverride; + typedef mozilla::layers::Layer Layer; + typedef mozilla::layers::LayersId LayersId; + typedef mozilla::layers::RefLayer RefLayer; + typedef mozilla::layers::StackingContextHelper StackingContextHelper; + typedef mozilla::LayerState LayerState; + typedef mozilla::LayoutDeviceRect LayoutDeviceRect; + typedef mozilla::LayoutDeviceIntPoint LayoutDeviceIntPoint; + + public: + nsDisplayRemote(nsDisplayListBuilder* aBuilder, nsSubDocumentFrame* aFrame); + + LayerState GetLayerState( + nsDisplayListBuilder* aBuilder, LayerManager* aManager, + const ContainerLayerParameters& aParameters) override; + + already_AddRefed BuildLayer( + nsDisplayListBuilder* aBuilder, LayerManager* aManager, + const ContainerLayerParameters& aContainerParameters) override; + + void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override; + + bool CreateWebRenderCommands( + mozilla::wr::DisplayListBuilder& aBuilder, + mozilla::wr::IpcResourceUpdateQueue& aResources, + const StackingContextHelper& aSc, + mozilla::layers::RenderRootStateManager* aManager, + nsDisplayListBuilder* aDisplayListBuilder) override; + bool UpdateScrollData( + mozilla::layers::WebRenderScrollData* aData, + mozilla::layers::WebRenderLayerScrollData* aLayerData) override; + + NS_DISPLAY_DECL_NAME("Remote", TYPE_REMOTE) + + private: + friend class nsDisplayItemBase; + nsFrameLoader* GetFrameLoader() const; + + TabId mTabId; + LayersId mLayersId; + LayoutDeviceIntPoint mOffset; + EventRegionsOverride mEventRegionsOverride; +}; + #endif /* NSSUBDOCUMENTFRAME_H_ */ diff --git a/layout/ipc/RemoteLayerTreeOwner.cpp b/layout/ipc/RemoteLayerTreeOwner.cpp new file mode 100644 index 0000000000000..e724f23353143 --- /dev/null +++ b/layout/ipc/RemoteLayerTreeOwner.cpp @@ -0,0 +1,134 @@ +/* -*- 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/. */ + +#include "base/basictypes.h" + +#include "mozilla/PresShell.h" +#include "mozilla/dom/ContentParent.h" +#include "mozilla/dom/BrowserParent.h" +#include "mozilla/layers/CompositorBridgeParent.h" +#include "mozilla/layers/CompositorTypes.h" +#include "mozilla/layers/LayerTransactionParent.h" +#include "nsFrameLoader.h" +#include "nsStyleStructInlines.h" +#include "nsSubDocumentFrame.h" +#include "RemoteLayerTreeOwner.h" +#include "mozilla/gfx/GPUProcessManager.h" +#include "mozilla/layers/CompositorBridgeChild.h" +#include "mozilla/layers/WebRenderLayerManager.h" +#include "mozilla/layers/WebRenderScrollData.h" +#include "mozilla/webrender/WebRenderAPI.h" +#include "mozilla/dom/EffectsInfo.h" + +using namespace mozilla::dom; +using namespace mozilla::gfx; +using namespace mozilla::layers; + +namespace mozilla { +namespace layout { + +static already_AddRefed GetLayerManager( + BrowserParent* aBrowserParent) { + if (Element* element = aBrowserParent->GetOwnerElement()) { + if (RefPtr lm = + nsContentUtils::LayerManagerForContent(element)) { + return lm.forget(); + } + return nsContentUtils::LayerManagerForDocument(element->OwnerDoc()); + } + return nullptr; +} + +RemoteLayerTreeOwner::RemoteLayerTreeOwner() + : mLayersId{0}, + mBrowserParent(nullptr), + mLayerManager(nullptr), + mInitialized(false), + mLayersConnected(false) {} + +RemoteLayerTreeOwner::~RemoteLayerTreeOwner() {} + +bool RemoteLayerTreeOwner::Initialize(BrowserParent* aBrowserParent) { + if (mInitialized || !aBrowserParent) { + return false; + } + + mBrowserParent = aBrowserParent; + RefPtr lm = GetLayerManager(mBrowserParent); + PCompositorBridgeChild* compositor = + lm ? lm->GetCompositorBridgeChild() : nullptr; + mTabProcessId = mBrowserParent->Manager()->OtherPid(); + + // Our remote frame will push layers updates to the compositor, + // and we'll keep an indirect reference to that tree. + GPUProcessManager* gpm = GPUProcessManager::Get(); + mLayersConnected = gpm->AllocateAndConnectLayerTreeId( + compositor, mTabProcessId, &mLayersId, &mCompositorOptions); + + mInitialized = true; + return true; +} + +void RemoteLayerTreeOwner::Destroy() { + if (mLayersId.IsValid()) { + GPUProcessManager::Get()->UnmapLayerTreeId(mLayersId, mTabProcessId); + } + + mBrowserParent = nullptr; + mLayerManager = nullptr; +} + +void RemoteLayerTreeOwner::EnsureLayersConnected( + CompositorOptions* aCompositorOptions) { + RefPtr lm = GetLayerManager(mBrowserParent); + if (!lm) { + return; + } + + if (!lm->GetCompositorBridgeChild()) { + return; + } + + mLayersConnected = lm->GetCompositorBridgeChild()->SendNotifyChildRecreated( + mLayersId, &mCompositorOptions); + *aCompositorOptions = mCompositorOptions; +} + +LayerManager* RemoteLayerTreeOwner::AttachLayerManager() { + RefPtr lm; + if (mBrowserParent) { + lm = GetLayerManager(mBrowserParent); + } + + // Perhaps the document containing this frame currently has no presentation? + if (lm && lm->GetCompositorBridgeChild() && lm != mLayerManager) { + mLayersConnected = + lm->GetCompositorBridgeChild()->SendAdoptChild(mLayersId); + FrameLayerBuilder::InvalidateAllLayers(lm); + } + + mLayerManager = lm.forget(); + return mLayerManager; +} + +void RemoteLayerTreeOwner::OwnerContentChanged() { + Unused << AttachLayerManager(); +} + +void RemoteLayerTreeOwner::GetTextureFactoryIdentifier( + TextureFactoryIdentifier* aTextureFactoryIdentifier) const { + RefPtr lm = + mBrowserParent ? GetLayerManager(mBrowserParent) : nullptr; + // Perhaps the document containing this frame currently has no presentation? + if (lm) { + *aTextureFactoryIdentifier = lm->GetTextureFactoryIdentifier(); + } else { + *aTextureFactoryIdentifier = TextureFactoryIdentifier(); + } +} + +} // namespace layout +} // namespace mozilla diff --git a/layout/ipc/RenderFrame.h b/layout/ipc/RemoteLayerTreeOwner.h similarity index 51% rename from layout/ipc/RenderFrame.h rename to layout/ipc/RemoteLayerTreeOwner.h index 89a79f229e62f..4d23ba8c54383 100644 --- a/layout/ipc/RenderFrame.h +++ b/layout/ipc/RemoteLayerTreeOwner.h @@ -4,8 +4,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef mozilla_layout_RenderFrame_h -#define mozilla_layout_RenderFrame_h +#ifndef mozilla_layout_RemoteLayerTreeOwner_h +#define mozilla_layout_RemoteLayerTreeOwner_h #include "base/process.h" @@ -32,18 +32,18 @@ struct TextureFactoryIdentifier; namespace layout { /** - * RenderFrame connects and manages layer trees for remote frames. It is - * directly owned by a BrowserParent and always lives in the parent process. + * RemoteLayerTreeOwner connects and manages layer trees for remote frames. It + * is directly owned by a BrowserParent and always lives in the parent process. */ -class RenderFrame final { +class RemoteLayerTreeOwner final { typedef mozilla::layers::CompositorOptions CompositorOptions; typedef mozilla::layers::LayerManager LayerManager; typedef mozilla::layers::LayersId LayersId; typedef mozilla::layers::TextureFactoryIdentifier TextureFactoryIdentifier; public: - RenderFrame(); - virtual ~RenderFrame(); + RemoteLayerTreeOwner(); + virtual ~RemoteLayerTreeOwner(); bool Initialize(dom::BrowserParent* aBrowserParent); void Destroy(); @@ -77,7 +77,7 @@ class RenderFrame final { bool mInitialized; // A flag that indicates whether or not the compositor knows about the - // layers id. In some cases this RenderFrame is not connected to the + // layers id. In some cases this RemoteLayerTreeOwner is not connected to the // compositor and so this flag is false. bool mLayersConnected; }; @@ -85,54 +85,4 @@ class RenderFrame final { } // namespace layout } // namespace mozilla -/** - * A nsDisplayRemote will graft a remote frame's shadow layer tree (for a given - * nsFrameLoader) into its parent frame's layer tree. - */ -class nsDisplayRemote final : public nsPaintedDisplayItem { - typedef mozilla::dom::TabId TabId; - typedef mozilla::gfx::Matrix4x4 Matrix4x4; - typedef mozilla::layers::EventRegionsOverride EventRegionsOverride; - typedef mozilla::layers::Layer Layer; - typedef mozilla::layers::LayersId LayersId; - typedef mozilla::layers::RefLayer RefLayer; - typedef mozilla::layout::RenderFrame RenderFrame; - typedef mozilla::LayoutDeviceRect LayoutDeviceRect; - typedef mozilla::LayoutDeviceIntPoint LayoutDeviceIntPoint; - - public: - nsDisplayRemote(nsDisplayListBuilder* aBuilder, nsSubDocumentFrame* aFrame); - - LayerState GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) override; - - already_AddRefed BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) override; - - void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override; - - bool CreateWebRenderCommands( - mozilla::wr::DisplayListBuilder& aBuilder, - mozilla::wr::IpcResourceUpdateQueue& aResources, - const StackingContextHelper& aSc, - mozilla::layers::RenderRootStateManager* aManager, - nsDisplayListBuilder* aDisplayListBuilder) override; - bool UpdateScrollData( - mozilla::layers::WebRenderScrollData* aData, - mozilla::layers::WebRenderLayerScrollData* aLayerData) override; - - NS_DISPLAY_DECL_NAME("Remote", TYPE_REMOTE) - - private: - friend class nsDisplayItemBase; - nsFrameLoader* GetFrameLoader() const; - - TabId mTabId; - LayersId mLayersId; - LayoutDeviceIntPoint mOffset; - EventRegionsOverride mEventRegionsOverride; -}; - -#endif // mozilla_layout_RenderFrame_h +#endif // mozilla_layout_RemoteLayerTreeOwner_h diff --git a/layout/ipc/RenderFrame.cpp b/layout/ipc/RenderFrame.cpp deleted file mode 100644 index 1ab0b8b948982..0000000000000 --- a/layout/ipc/RenderFrame.cpp +++ /dev/null @@ -1,329 +0,0 @@ -/* -*- 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/. */ - -#include "base/basictypes.h" - -#include "mozilla/PresShell.h" -#include "mozilla/dom/ContentParent.h" -#include "mozilla/dom/BrowserParent.h" -#include "mozilla/layers/CompositorBridgeParent.h" -#include "mozilla/layers/CompositorTypes.h" -#include "mozilla/layers/LayerTransactionParent.h" -#include "nsFrameLoader.h" -#include "nsStyleStructInlines.h" -#include "nsSubDocumentFrame.h" -#include "RenderFrame.h" -#include "mozilla/gfx/GPUProcessManager.h" -#include "mozilla/layers/CompositorBridgeChild.h" -#include "mozilla/layers/WebRenderLayerManager.h" -#include "mozilla/layers/WebRenderScrollData.h" -#include "mozilla/webrender/WebRenderAPI.h" -#include "mozilla/dom/EffectsInfo.h" - -using namespace mozilla::dom; -using namespace mozilla::gfx; -using namespace mozilla::layers; - -namespace mozilla { -namespace layout { - -static already_AddRefed GetLayerManager( - BrowserParent* aBrowserParent) { - if (Element* element = aBrowserParent->GetOwnerElement()) { - if (RefPtr lm = - nsContentUtils::LayerManagerForContent(element)) { - return lm.forget(); - } - return nsContentUtils::LayerManagerForDocument(element->OwnerDoc()); - } - return nullptr; -} - -RenderFrame::RenderFrame() - : mLayersId{0}, - mBrowserParent(nullptr), - mLayerManager(nullptr), - mInitialized(false), - mLayersConnected(false) {} - -RenderFrame::~RenderFrame() {} - -bool RenderFrame::Initialize(BrowserParent* aBrowserParent) { - if (mInitialized || !aBrowserParent) { - return false; - } - - mBrowserParent = aBrowserParent; - RefPtr lm = GetLayerManager(mBrowserParent); - PCompositorBridgeChild* compositor = - lm ? lm->GetCompositorBridgeChild() : nullptr; - mTabProcessId = mBrowserParent->Manager()->OtherPid(); - - // Our remote frame will push layers updates to the compositor, - // and we'll keep an indirect reference to that tree. - GPUProcessManager* gpm = GPUProcessManager::Get(); - mLayersConnected = gpm->AllocateAndConnectLayerTreeId( - compositor, mTabProcessId, &mLayersId, &mCompositorOptions); - - mInitialized = true; - return true; -} - -void RenderFrame::Destroy() { - if (mLayersId.IsValid()) { - GPUProcessManager::Get()->UnmapLayerTreeId(mLayersId, mTabProcessId); - } - - mBrowserParent = nullptr; - mLayerManager = nullptr; -} - -void RenderFrame::EnsureLayersConnected(CompositorOptions* aCompositorOptions) { - RefPtr lm = GetLayerManager(mBrowserParent); - if (!lm) { - return; - } - - if (!lm->GetCompositorBridgeChild()) { - return; - } - - mLayersConnected = lm->GetCompositorBridgeChild()->SendNotifyChildRecreated( - mLayersId, &mCompositorOptions); - *aCompositorOptions = mCompositorOptions; -} - -LayerManager* RenderFrame::AttachLayerManager() { - RefPtr lm; - if (mBrowserParent) { - lm = GetLayerManager(mBrowserParent); - } - - // Perhaps the document containing this frame currently has no presentation? - if (lm && lm->GetCompositorBridgeChild() && lm != mLayerManager) { - mLayersConnected = - lm->GetCompositorBridgeChild()->SendAdoptChild(mLayersId); - FrameLayerBuilder::InvalidateAllLayers(lm); - } - - mLayerManager = lm.forget(); - return mLayerManager; -} - -void RenderFrame::OwnerContentChanged() { Unused << AttachLayerManager(); } - -void RenderFrame::GetTextureFactoryIdentifier( - TextureFactoryIdentifier* aTextureFactoryIdentifier) const { - RefPtr lm = - mBrowserParent ? GetLayerManager(mBrowserParent) : nullptr; - // Perhaps the document containing this frame currently has no presentation? - if (lm) { - *aTextureFactoryIdentifier = lm->GetTextureFactoryIdentifier(); - } else { - *aTextureFactoryIdentifier = TextureFactoryIdentifier(); - } -} - -} // namespace layout -} // namespace mozilla - -/** - * Gets the layer-pixel offset of aContainerFrame's content rect top-left - * from the nearest display item reference frame (which we assume will be - * inducing a ContainerLayer). - */ -static mozilla::LayoutDeviceIntPoint GetContentRectLayerOffset( - nsIFrame* aContainerFrame, nsDisplayListBuilder* aBuilder) { - nscoord auPerDevPixel = aContainerFrame->PresContext()->AppUnitsPerDevPixel(); - - // Offset to the content rect in case we have borders or padding - // Note that aContainerFrame could be a reference frame itself, so - // we need to be careful here to ensure that we call ToReferenceFrame - // on aContainerFrame and not its parent. - nsPoint frameOffset = - aBuilder->ToReferenceFrame(aContainerFrame) + - aContainerFrame->GetContentRectRelativeToSelf().TopLeft(); - - return mozilla::LayoutDeviceIntPoint::FromAppUnitsToNearest(frameOffset, - auPerDevPixel); -} - -// Return true iff |aManager| is a "temporary layer manager". They're -// used for small software rendering tasks, like drawWindow. That's -// currently implemented by a BasicLayerManager without a backing -// widget, and hence in non-retained mode. -inline static bool IsTempLayerManager(mozilla::layers::LayerManager* aManager) { - return (mozilla::layers::LayersBackend::LAYERS_BASIC == - aManager->GetBackendType() && - !static_cast(aManager)->IsRetained()); -} - -nsDisplayRemote::nsDisplayRemote(nsDisplayListBuilder* aBuilder, - nsSubDocumentFrame* aFrame) - : nsPaintedDisplayItem(aBuilder, aFrame), - mTabId{0}, - mEventRegionsOverride(EventRegionsOverride::NoOverride) { - bool frameIsPointerEventsNone = aFrame->StyleUI()->GetEffectivePointerEvents( - aFrame) == NS_STYLE_POINTER_EVENTS_NONE; - if (aBuilder->IsInsidePointerEventsNoneDoc() || frameIsPointerEventsNone) { - mEventRegionsOverride |= EventRegionsOverride::ForceEmptyHitRegion; - } - if (nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents( - aFrame->PresShell())) { - mEventRegionsOverride |= EventRegionsOverride::ForceDispatchToContent; - } - - nsFrameLoader* frameLoader = GetFrameLoader(); - MOZ_ASSERT(frameLoader && frameLoader->IsRemoteFrame()); - mLayersId = frameLoader->GetLayersId(); - - if (nsFrameLoader* frameLoader = GetFrameLoader()) { - // TODO: We need to handle acquiring a TabId in the remote sub-frame case - // for fission. - if (BrowserParent* browser = BrowserParent::GetFrom(frameLoader)) { - mTabId = browser->GetTabId(); - } - } -} - -mozilla::LayerState nsDisplayRemote::GetLayerState( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) { - if (IsTempLayerManager(aManager)) { - return mozilla::LayerState::LAYER_NONE; - } - return mozilla::LayerState::LAYER_ACTIVE_FORCE; -} - -already_AddRefed nsDisplayRemote::BuildLayer( - nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) { - MOZ_ASSERT(mFrame, "Makes no sense to have a shadow tree without a frame"); - - if (IsTempLayerManager(aManager)) { - // This can happen if aManager is a "temporary" manager, or if the - // widget's layer manager changed out from under us. We need to - // FIXME handle the former case somehow, probably with an API to - // draw a manager's subtree. The latter is bad bad bad, but the the - // MOZ_ASSERT() above will flag it. Returning nullptr here will just - // cause the shadow subtree not to be rendered. - NS_WARNING("Remote iframe not rendered"); - return nullptr; - } - - if (!mLayersId.IsValid()) { - return nullptr; - } - - if (RefPtr remoteBrowser = - GetFrameLoader()->GetRemoteBrowser()) { - // Generate an effects update notifying the browser it is visible - aBuilder->AddEffectUpdate(remoteBrowser, EffectsInfo::FullyVisible()); - // FrameLayerBuilder will take care of notifying the browser when it is no - // longer visible - } - - RefPtr layer = - aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this); - - if (!layer) { - layer = aManager->CreateRefLayer(); - } - if (!layer || !layer->AsRefLayer()) { - // Probably a temporary layer manager that doesn't know how to - // use ref layers. - return nullptr; - } - RefLayer* refLayer = layer->AsRefLayer(); - - LayoutDeviceIntPoint offset = GetContentRectLayerOffset(Frame(), aBuilder); - // We can only have an offset if we're a child of an inactive - // container, but our display item is LAYER_ACTIVE_FORCE which - // forces all layers above to be active. - MOZ_ASSERT(aContainerParameters.mOffset == nsIntPoint()); - Matrix4x4 m = Matrix4x4::Translation(offset.x, offset.y, 0.0); - // Remote content can't be repainted by us, so we multiply down - // the resolution that our container expects onto our container. - m.PreScale(aContainerParameters.mXScale, aContainerParameters.mYScale, 1.0); - refLayer->SetBaseTransform(m); - refLayer->SetEventRegionsOverride(mEventRegionsOverride); - refLayer->SetReferentId(mLayersId); - - return layer.forget(); -} - -void nsDisplayRemote::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) { - DrawTarget* target = aCtx->GetDrawTarget(); - if (!target->IsRecording() || mTabId == 0) { - NS_WARNING("Remote iframe not rendered"); - return; - } - - int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel(); - Rect destRect = mozilla::NSRectToSnappedRect(GetContentRect(), - appUnitsPerDevPixel, *target); - target->DrawDependentSurface(mTabId, destRect); -} - -bool nsDisplayRemote::CreateWebRenderCommands( - mozilla::wr::DisplayListBuilder& aBuilder, - mozilla::wr::IpcResourceUpdateQueue& aResources, - const StackingContextHelper& aSc, - mozilla::layers::RenderRootStateManager* aManager, - nsDisplayListBuilder* aDisplayListBuilder) { - if (!mLayersId.IsValid()) { - return true; - } - - if (RefPtr remoteBrowser = - GetFrameLoader()->GetRemoteBrowser()) { - // Generate an effects update notifying the browser it is visible - aDisplayListBuilder->AddEffectUpdate(remoteBrowser, - EffectsInfo::FullyVisible()); - - // Create a WebRenderRemoteData to notify the RemoteBrowser when it is no - // longer visible - RefPtr userData = - aManager->CommandBuilder() - .CreateOrRecycleWebRenderUserData( - this, aBuilder.GetRenderRoot(), nullptr); - userData->SetRemoteBrowser(remoteBrowser); - } - - mOffset = GetContentRectLayerOffset(mFrame, aDisplayListBuilder); - - LayoutDeviceRect rect = LayoutDeviceRect::FromAppUnits( - mFrame->GetContentRectRelativeToSelf(), - mFrame->PresContext()->AppUnitsPerDevPixel()); - rect += mOffset; - - aBuilder.PushIFrame(mozilla::wr::ToRoundedLayoutRect(rect), - !BackfaceIsHidden(), mozilla::wr::AsPipelineId(mLayersId), - /*ignoreMissingPipelines*/ true); - - return true; -} - -bool nsDisplayRemote::UpdateScrollData( - mozilla::layers::WebRenderScrollData* aData, - mozilla::layers::WebRenderLayerScrollData* aLayerData) { - if (!mLayersId.IsValid()) { - return true; - } - - if (aLayerData) { - aLayerData->SetReferentId(mLayersId); - aLayerData->SetTransform( - mozilla::gfx::Matrix4x4::Translation(mOffset.x, mOffset.y, 0.0)); - aLayerData->SetEventRegionsOverride(mEventRegionsOverride); - } - return true; -} - -nsFrameLoader* nsDisplayRemote::GetFrameLoader() const { - return mFrame ? static_cast(mFrame)->FrameLoader() - : nullptr; -} diff --git a/layout/ipc/moz.build b/layout/ipc/moz.build index e495c27519f5e..9018329caa099 100644 --- a/layout/ipc/moz.build +++ b/layout/ipc/moz.build @@ -8,13 +8,13 @@ with Files('**'): BUG_COMPONENT = ('Core', 'Web Painting') EXPORTS.mozilla.layout += [ - 'RenderFrame.h', + 'RemoteLayerTreeOwner.h', 'VsyncChild.h', 'VsyncParent.h', ] UNIFIED_SOURCES += [ - 'RenderFrame.cpp', + 'RemoteLayerTreeOwner.cpp', ] SOURCES += [ diff --git a/layout/painting/nsDisplayList.cpp b/layout/painting/nsDisplayList.cpp index 7d31a0cc8b136..9f05510f2c033 100644 --- a/layout/painting/nsDisplayList.cpp +++ b/layout/painting/nsDisplayList.cpp @@ -61,6 +61,7 @@ #include "ImageLayers.h" #include "ImageContainer.h" #include "nsCanvasFrame.h" +#include "nsSubDocumentFrame.h" #include "StickyScrollContainer.h" #include "mozilla/AnimationPerformanceWarning.h" #include "mozilla/AnimationUtils.h" @@ -102,7 +103,6 @@ #include "mozilla/layers/WebRenderLayerManager.h" #include "mozilla/layers/WebRenderMessages.h" #include "mozilla/layers/WebRenderScrollData.h" -#include "mozilla/layout/RenderFrame.h" using namespace mozilla; using namespace mozilla::layers; diff --git a/layout/printing/nsPrintData.cpp b/layout/printing/nsPrintData.cpp index e0ac4e9421ab7..4b19405d8e2e2 100644 --- a/layout/printing/nsPrintData.cpp +++ b/layout/printing/nsPrintData.cpp @@ -35,7 +35,6 @@ nsPrintData::nsPrintData(ePrintDataType aType) mPreparingForPrint(false), mDocWasToBeDestroyed(false), mShrinkToFit(false), - mPrintFrameType(nsIPrintSettings::kFramesAsIs), mNumPrintablePages(0), mNumPagesPrinted(0), mShrinkRatio(1.0) { diff --git a/layout/printing/nsPrintData.h b/layout/printing/nsPrintData.h index c3c599e71905b..17738dd5c1e9d 100644 --- a/layout/printing/nsPrintData.h +++ b/layout/printing/nsPrintData.h @@ -81,7 +81,6 @@ class nsPrintData { bool mPreparingForPrint; // see comments above bool mDocWasToBeDestroyed; // see comments above bool mShrinkToFit; - int16_t mPrintFrameType; int32_t mNumPrintablePages; int32_t mNumPagesPrinted; float mShrinkRatio; diff --git a/layout/printing/nsPrintJob.cpp b/layout/printing/nsPrintJob.cpp index db4ef8f5dd487..5640904fb18eb 100644 --- a/layout/printing/nsPrintJob.cpp +++ b/layout/printing/nsPrintJob.cpp @@ -92,7 +92,7 @@ static const char kPrintingPromptService[] = #include "nsDeviceContextSpecProxy.h" #include "nsViewManager.h" -#include "nsIPageSequenceFrame.h" +#include "nsPageSequenceFrame.h" #include "nsIURL.h" #include "nsIContentViewerEdit.h" #include "nsIInterfaceRequestor.h" @@ -149,10 +149,6 @@ static uint32_t gDumpLOFileNameCnt = 0; #define PRT_YESNO(_p) ((_p) ? "YES" : "NO") static const char* gFrameTypesStr[] = {"eDoc", "eFrame", "eIFrame", "eFrameSet"}; -static const char* gPrintFrameTypeStr[] = {"kNoFrames", "kFramesAsIs", - "kSelectedFrame", "kEachFrameSep"}; -static const char* gFrameHowToEnableStr[] = { - "kFrameEnableNone", "kFrameEnableAll", "kFrameEnableAsIsAndEach"}; static const char* gPrintRangeStr[] = { "kRangeAllPages", "kRangeSpecifiedPageRange", "kRangeSelection"}; @@ -329,9 +325,7 @@ static nsresult GetSeqFrameAndCountPagesInternal( return NS_ERROR_FAILURE; } - // Finds the SimplePageSequencer frame - nsIPageSequenceFrame* seqFrame = aPO->mPresShell->GetPageSequenceFrame(); - aSeqFrame = do_QueryFrame(seqFrame); + aSeqFrame = aPO->mPresShell->GetPageSequenceFrame(); if (!aSeqFrame) { return NS_ERROR_FAILURE; } @@ -850,19 +844,6 @@ nsresult nsPrintJob::DoCommonPrint(bool aIsPrintPreview, printData->mIsIFrameSelected = IsThereAnIFrameSelected( docShell, printData->mCurrentFocusWin, printData->mIsParentAFrameSet); - // Setup print options for UI - if (printData->mIsParentAFrameSet) { - if (printData->mCurrentFocusWin) { - printData->mPrintSettings->SetHowToEnableFrameUI( - nsIPrintSettings::kFrameEnableAll); - } else { - printData->mPrintSettings->SetHowToEnableFrameUI( - nsIPrintSettings::kFrameEnableAsIsAndEach); - } - } else { - printData->mPrintSettings->SetHowToEnableFrameUI( - nsIPrintSettings::kFrameEnableNone); - } // Now determine how to set up the Frame print UI printData->mPrintSettings->SetPrintOptions( nsIPrintSettings::kEnableSelectionRB, @@ -980,17 +961,9 @@ nsresult nsPrintJob::DoCommonPrint(bool aIsPrintPreview, } if (aIsPrintPreview) { - printData->mPrintSettings->SetPrintFrameType(nsIPrintSettings::kFramesAsIs); - // override any UI that wants to PrintPreview any selection or page range // we want to view every page in PrintPreview each time printData->mPrintSettings->SetPrintRange(nsIPrintSettings::kRangeAllPages); - } else { - printData->mPrintSettings->GetPrintFrameType(&printData->mPrintFrameType); - } - - if (printData->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { - CheckForChildFrameSets(printData->mPrintObject); } if (NS_FAILED(EnablePOsForPrinting())) { @@ -1069,12 +1042,6 @@ nsresult nsPrintJob::PrintPreview( return CommonPrint(true, aPrintSettings, aWebProgressListener, aSourceDoc); } -//---------------------------------------------------------------------------------- -bool nsPrintJob::IsFramesetDocument() const { - nsCOMPtr docShell(do_QueryReferent(mDocShell)); - return IsParentAFrameSet(docShell); -} - //---------------------------------------------------------------------------------- bool nsPrintJob::IsIFrameSelected() { // Get the docshell for this documentviewer @@ -1098,13 +1065,6 @@ bool nsPrintJob::IsRangeSelection() { return IsThereARangeSelection(currentFocusWin); } -//---------------------------------------------------------------------------------- -bool nsPrintJob::IsFramesetFrameSelected() const { - // Get the currently focused window - nsCOMPtr currentFocusWin = FindFocusedDOMWindow(); - return currentFocusWin != nullptr; -} - //---------------------------------------------------------------------------------- int32_t nsPrintJob::GetPrintPreviewNumPages() { // When calling this function, the FinishPrintPreview() function might not @@ -1315,37 +1275,6 @@ void nsPrintJob::BuildDocTree(nsIDocShell* aParentNode, } } -//------------------------------------------------------- -// A Frame's sub-doc may contain content or a FrameSet -// When it contains a FrameSet the mFrameType for the PrintObject -// is always set to an eFrame. Which is fine when printing "AsIs" -// but is incorrect when when printing "Each Frame Separately". -// When printing "Each Frame Separately" the Frame really acts like -// a frameset. -// -// This method walks the PO tree and checks to see if the PrintObject is -// an eFrame and has children that are eFrames (meaning it's a Frame containing -// a FrameSet) If so, then the mFrameType need to be changed to eFrameSet -// -// Also note: We only want to call this we are printing "Each Frame Separately" -// when printing "As Is" leave it as an eFrame -void nsPrintJob::CheckForChildFrameSets(const UniquePtr& aPO) { - NS_ASSERTION(aPO, "Pointer is null!"); - - // Continue recursively walking the chilren of this PO - bool hasChildFrames = false; - for (const UniquePtr& po : aPO->mKids) { - if (po->mFrameType == eFrame) { - hasChildFrames = true; - CheckForChildFrameSets(po); - } - } - - if (hasChildFrames && aPO->mFrameType == eFrame) { - aPO->mFrameType = eFrameSet; - } -} - //--------------------------------------------------------------------- bool nsPrintJob::IsThereAnIFrameSelected(nsIDocShell* aDocShell, nsPIDOMWindowOuter* aDOMWin, @@ -1438,16 +1367,7 @@ void nsPrintJob::GetDisplayTitleAndURL(const UniquePtr& aPO, //--------------------------------------------------------------------- nsresult nsPrintJob::DocumentReadyForPrinting() { - if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { - // Guarantee that mPrt->mPrintObject won't be deleted during a call of - // CheckForChildFrameSets(). - RefPtr printData = mPrt; - CheckForChildFrameSets(printData->mPrintObject); - } - - // // Send the document to the printer... - // nsresult rv = SetupToPrintContent(); if (NS_FAILED(rv)) { // The print job was canceled or there was a problem @@ -1802,7 +1722,7 @@ nsresult nsPrintJob::SetupToPrintContent() { if (mIsCreatingPrintPreview) { // Copy docTitleStr and docURLStr to the pageSequenceFrame, to be displayed // in the header - nsIPageSequenceFrame* seqFrame = + nsPageSequenceFrame* seqFrame = printData->mPrintObject->mPresShell->GetPageSequenceFrame(); if (seqFrame) { seqFrame->StartPrint(printData->mPrintObject->mPresContext, @@ -1995,9 +1915,11 @@ void nsPrintJob::UpdateZoomRatio(nsPrintObject* aPO, bool aSetPixelScale) { // Here is where we set the shrinkage value into the DC // and this is what actually makes it shrink if (aSetPixelScale && aPO->mFrameType != eIFrame) { + int16_t printRangeType = nsIPrintSettings::kRangeAllPages; + mPrt->mPrintSettings->GetPrintRange(&printRangeType); + float ratio; - if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs || - mPrt->mPrintFrameType == nsIPrintSettings::kNoFrames) { + if (printRangeType != nsIPrintSettings::kRangeSelection) { ratio = mPrt->mShrinkRatio - 0.005f; // round down } else { ratio = aPO->mShrinkRatio - 0.005f; // round down @@ -2040,10 +1962,9 @@ nsresult nsPrintJob::UpdateSelectionAndShrinkPrintObject( // this is the frame where the right-hand side of the frame extends // the furthest if (mPrt->mShrinkToFit && aDocumentIsTopLevel) { - nsIPageSequenceFrame* pageSequence = - aPO->mPresShell->GetPageSequenceFrame(); - NS_ENSURE_STATE(pageSequence); - pageSequence->GetSTFPercent(aPO->mShrinkRatio); + nsPageSequenceFrame* pageSeqFrame = aPO->mPresShell->GetPageSequenceFrame(); + NS_ENSURE_STATE(pageSeqFrame); + aPO->mShrinkRatio = pageSeqFrame->GetSTFPercent(); // Limit the shrink-to-fit scaling for some text-ish type of documents. nsAutoString contentType; aPO->mPresShell->GetDocument()->GetContentType(contentType); @@ -2311,9 +2232,7 @@ void nsPrintJob::CalcNumPrintablePages(int32_t& aNumPages) { // IsPrintable() returns false, ReflowPrintObject bails before setting // mPresContext) if (po->mPresContext && po->mPresContext->IsRootPaginatedDocument()) { - nsIPageSequenceFrame* pageSequence = - po->mPresShell->GetPageSequenceFrame(); - nsIFrame* seqFrame = do_QueryFrame(pageSequence); + nsPageSequenceFrame* seqFrame = po->mPresShell->GetPageSequenceFrame(); if (seqFrame) { aNumPages += seqFrame->PrincipalChildList().GetLength(); } @@ -2490,8 +2409,8 @@ nsresult nsPrintJob::DoPrint(const UniquePtr& aPO) { { // Ask the page sequence frame to print all the pages - nsIPageSequenceFrame* pageSequence = poPresShell->GetPageSequenceFrame(); - NS_ASSERTION(nullptr != pageSequence, "no page sequence frame"); + nsPageSequenceFrame* seqFrame = poPresShell->GetPageSequenceFrame(); + MOZ_ASSERT(seqFrame, "no page sequence frame"); // We are done preparing for printing, so we can turn this off printData->mPreparingForPrint = false; @@ -2517,15 +2436,14 @@ nsresult nsPrintJob::DoPrint(const UniquePtr& aPO) { nsAutoString docURLStr; GetDisplayTitleAndURL(aPO, docTitleStr, docURLStr, eDocTitleDefBlank); - nsIFrame* seqFrame = do_QueryFrame(pageSequence); if (!seqFrame) { SetIsPrinting(false); return NS_ERROR_FAILURE; } mPageSeqFrame = seqFrame; - pageSequence->StartPrint(poPresContext, printData->mPrintSettings, - docTitleStr, docURLStr); + seqFrame->StartPrint(poPresContext, printData->mPrintSettings, docTitleStr, + docURLStr); // Schedule Page to Print PR_PL(("Scheduling Print of PO: %p (%s) \n", aPO.get(), @@ -2599,7 +2517,7 @@ bool nsPrintJob::PrePrintPage() { // Ask mPageSeqFrame if the page is ready to be printed. // If the page doesn't get printed at all, the |done| will be |true|. bool done = false; - nsIPageSequenceFrame* pageSeqFrame = do_QueryFrame(mPageSeqFrame.GetFrame()); + nsPageSequenceFrame* pageSeqFrame = do_QueryFrame(mPageSeqFrame.GetFrame()); nsresult rv = pageSeqFrame->PrePrintNextPage(mPagePrintTimer, &done); if (NS_FAILED(rv)) { // ??? ::PrintPage doesn't set |printData->mIsAborted = true| if @@ -2644,13 +2562,12 @@ bool nsPrintJob::PrintPage(nsPrintObject* aPO, bool& aInRange) { } int32_t pageNum, numPages, endPage; - nsIPageSequenceFrame* pageSeqFrame = do_QueryFrame(mPageSeqFrame.GetFrame()); - pageSeqFrame->GetCurrentPageNum(&pageNum); - pageSeqFrame->GetNumPages(&numPages); + nsPageSequenceFrame* pageSeqFrame = do_QueryFrame(mPageSeqFrame.GetFrame()); + pageNum = pageSeqFrame->GetCurrentPageNum(); + numPages = pageSeqFrame->GetNumPages(); bool donePrinting; - bool isDoingPrintRange; - pageSeqFrame->IsDoingPrintRange(&isDoingPrintRange); + bool isDoingPrintRange = pageSeqFrame->IsDoingPrintRange(); if (isDoingPrintRange) { int32_t fromPage; int32_t toPage; @@ -2677,12 +2594,6 @@ bool nsPrintJob::PrintPage(nsPrintObject* aPO, bool& aInRange) { aInRange = true; } - // XXX This is wrong, but the actual behavior in the presence of a print - // range sucks. - if (printData->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { - endPage = printData->mNumPrintablePages; - } - printData->DoOnProgressChange(++printData->mNumPagesPrinted, endPage, false, 0); if (NS_WARN_IF(mPrt != printData)) { @@ -2831,8 +2742,7 @@ bool nsPrintJob::DonePrintingPages(nsPrintObject* aPO, nsresult aResult) { // that might call |Notify| on the pagePrintTimer after things are cleaned up // and printing was marked as being done. if (mPageSeqFrame.IsAlive()) { - nsIPageSequenceFrame* pageSeqFrame = - do_QueryFrame(mPageSeqFrame.GetFrame()); + nsPageSequenceFrame* pageSeqFrame = do_QueryFrame(mPageSeqFrame.GetFrame()); pageSeqFrame->ResetPrintCanvasList(); } @@ -2884,114 +2794,37 @@ nsresult nsPrintJob::EnablePOsForPrinting() { return NS_ERROR_FAILURE; } - printData->mPrintFrameType = nsIPrintSettings::kNoFrames; - printData->mPrintSettings->GetPrintFrameType(&printData->mPrintFrameType); - - int16_t printHowEnable = nsIPrintSettings::kFrameEnableNone; - printData->mPrintSettings->GetHowToEnableFrameUI(&printHowEnable); - int16_t printRangeType = nsIPrintSettings::kRangeAllPages; printData->mPrintSettings->GetPrintRange(&printRangeType); PR_PL(("\n")); PR_PL(("********* nsPrintJob::EnablePOsForPrinting *********\n")); - PR_PL(("PrintFrameType: %s \n", - gPrintFrameTypeStr[printData->mPrintFrameType])); - PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); PR_PL(("----\n")); - // ***** This is the ultimate override ***** - // if we are printing the selection (either an IFrame or selection range) - // then set the mPrintFrameType as if it were the selected frame - if (printRangeType == nsIPrintSettings::kRangeSelection) { - printData->mPrintFrameType = nsIPrintSettings::kSelectedFrame; - printHowEnable = nsIPrintSettings::kFrameEnableNone; - } - - // This tells us that the "Frame" UI has turned off, - // so therefore there are no FrameSets/Frames/IFrames to be printed - // - // This means there are not FrameSets, - // but the document could contain an IFrame - if (printHowEnable == nsIPrintSettings::kFrameEnableNone) { - // Print all the pages or a sub range of pages - if (printRangeType == nsIPrintSettings::kRangeAllPages || - printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) { - SetPrintPO(printData->mPrintObject.get(), true); - - // Set the children so they are PrinAsIs - // In this case, the children are probably IFrames - if (printData->mPrintObject->mKids.Length() > 0) { - for (const UniquePtr& po : - printData->mPrintObject->mKids) { - NS_ASSERTION(po, "nsPrintObject can't be null!"); - SetPrintAsIs(po.get()); - } + bool treatAsNonFrameset = !printData->mIsParentAFrameSet || + printRangeType == nsIPrintSettings::kRangeSelection; - // ***** Another override ***** - printData->mPrintFrameType = nsIPrintSettings::kFramesAsIs; - } - PR_PL(("PrintFrameType: %s \n", - gPrintFrameTypeStr[printData->mPrintFrameType])); - PR_PL( - ("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); - PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); - return NS_OK; - } - - // This means we are either printed a selected IFrame or - // we are printing the current selection - if (printRangeType == nsIPrintSettings::kRangeSelection) { - // If the currentFocusDOMWin can'r be null if something is selected - if (printData->mCurrentFocusWin) { - // Find the selected IFrame - nsPrintObject* po = FindPrintObjectByDOMWin( - printData->mPrintObject.get(), printData->mCurrentFocusWin); - if (po) { - // Makes sure all of its children are be printed "AsIs" - SetPrintAsIs(po); - - // Now, only enable this POs (the selected PO) and all of its children - SetPrintPO(po, true); + if (treatAsNonFrameset && + (printRangeType == nsIPrintSettings::kRangeAllPages || + printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange)) { + SetPrintPO(printData->mPrintObject.get(), true); - // check to see if we have a range selection, - // as oppose to a insert selection - // this means if the user just clicked on the IFrame then - // there will not be a selection so we want the entire page to print - // - // XXX this is sort of a hack right here to make the page - // not try to reposition itself when printing selection - nsPIDOMWindowOuter* domWin = - po->mDocument->GetOriginalDocument()->GetWindow(); - if (!IsThereARangeSelection(domWin)) { - printRangeType = nsIPrintSettings::kRangeAllPages; - printData->mPrintSettings->SetPrintRange(printRangeType); - } - PR_PL(("PrintFrameType: %s \n", - gPrintFrameTypeStr[printData->mPrintFrameType])); - PR_PL(("HowToEnableFrameUI: %s \n", - gFrameHowToEnableStr[printHowEnable])); - PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); - return NS_OK; - } - } else { - for (uint32_t i = 0; i < printData->mPrintDocList.Length(); i++) { - nsPrintObject* po = printData->mPrintDocList.ElementAt(i); - NS_ASSERTION(po, "nsPrintObject can't be null!"); - nsCOMPtr domWin = po->mDocShell->GetWindow(); - if (IsThereARangeSelection(domWin)) { - printData->mCurrentFocusWin = domWin.forget(); - SetPrintPO(po, true); - break; - } - } - return NS_OK; + // Set the children so they are PrinAsIs + // In this case, the children are probably IFrames + if (printData->mPrintObject->mKids.Length() > 0) { + for (const UniquePtr& po : + printData->mPrintObject->mKids) { + NS_ASSERTION(po, "nsPrintObject can't be null!"); + SetPrintAsIs(po.get()); } } + PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); + return NS_OK; } - // check to see if there is a selection when a FrameSet is present + // This means we are either printed a selected IFrame or + // we are printing the current selection if (printRangeType == nsIPrintSettings::kRangeSelection) { // If the currentFocusDOMWin can'r be null if something is selected if (printData->mCurrentFocusWin) { @@ -3012,64 +2845,51 @@ nsresult nsPrintJob::EnablePOsForPrinting() { // // XXX this is sort of a hack right here to make the page // not try to reposition itself when printing selection - nsCOMPtr domWin = + nsPIDOMWindowOuter* domWin = po->mDocument->GetOriginalDocument()->GetWindow(); if (!IsThereARangeSelection(domWin)) { printRangeType = nsIPrintSettings::kRangeAllPages; printData->mPrintSettings->SetPrintRange(printRangeType); } - PR_PL(("PrintFrameType: %s \n", - gPrintFrameTypeStr[printData->mPrintFrameType])); - PR_PL(("HowToEnableFrameUI: %s \n", - gFrameHowToEnableStr[printHowEnable])); PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); return NS_OK; } + } else if (treatAsNonFrameset) { + for (uint32_t i = 0; i < printData->mPrintDocList.Length(); i++) { + nsPrintObject* po = printData->mPrintDocList.ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + nsCOMPtr domWin = po->mDocShell->GetWindow(); + if (IsThereARangeSelection(domWin)) { + printData->mCurrentFocusWin = domWin.forget(); + SetPrintPO(po, true); + break; + } + } + return NS_OK; } } - // If we are printing "AsIs" then sets all the POs to be printed as is - if (printData->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { + if (printRangeType != nsIPrintSettings::kRangeSelection) { SetPrintAsIs(printData->mPrintObject.get()); SetPrintPO(printData->mPrintObject.get(), true); return NS_OK; } - // If we are printing the selected Frame then - // find that PO for that selected DOMWin and set it all of its - // children to be printed - if (printData->mPrintFrameType == nsIPrintSettings::kSelectedFrame) { - if ((printData->mIsParentAFrameSet && printData->mCurrentFocusWin) || - printData->mIsIFrameSelected) { - nsPrintObject* po = FindPrintObjectByDOMWin(printData->mPrintObject.get(), - printData->mCurrentFocusWin); - if (po) { - // NOTE: Calling this sets the "po" and - // we don't want to do this for documents that have no children, - // because then the "DoEndPage" gets called and it shouldn't - if (po->mKids.Length() > 0) { - // Makes sure that itself, and all of its children are printed "AsIs" - SetPrintAsIs(po); - } - - // Now, only enable this POs (the selected PO) and all of its children - SetPrintPO(po, true); + if ((printData->mIsParentAFrameSet && printData->mCurrentFocusWin) || + printData->mIsIFrameSelected) { + nsPrintObject* po = FindPrintObjectByDOMWin(printData->mPrintObject.get(), + printData->mCurrentFocusWin); + if (po) { + // NOTE: Calling this sets the "po" and + // we don't want to do this for documents that have no children, + // because then the "DoEndPage" gets called and it shouldn't + if (po->mKids.Length() > 0) { + // Makes sure that itself, and all of its children are printed "AsIs" + SetPrintAsIs(po); } - } - return NS_OK; - } - // If we are print each subdoc separately, - // then don't print any of the FraneSet Docs - if (printData->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { - SetPrintPO(printData->mPrintObject.get(), true); - int32_t cnt = printData->mPrintDocList.Length(); - for (int32_t i = 0; i < cnt; i++) { - nsPrintObject* po = printData->mPrintDocList.ElementAt(i); - NS_ASSERTION(po, "nsPrintObject can't be null!"); - if (po->mFrameType == eFrameSet) { - po->mDontPrint = true; - } + // Now, only enable this POs (the selected PO) and all of its children + SetPrintPO(po, true); } } @@ -3549,7 +3369,7 @@ static void DumpPrintObjectsList(const nsTArray& aDocList) { if (po->mPresShell) { rootFrame = po->mPresShell->GetRootFrame(); while (rootFrame != nullptr) { - nsIPageSequenceFrame* sqf = do_QueryFrame(rootFrame); + nsPageSequenceFrame* sqf = do_QueryFrame(rootFrame); if (sqf) { break; } @@ -3557,9 +3377,8 @@ static void DumpPrintObjectsList(const nsTArray& aDocList) { } } - PR_PL(("%s %d %d %d %p %p %p\n", types[po->mFrameType], po->IsPrintable(), - po->mPrintAsIs, po->mHasBeenPrinted, po, po->mDocShell.get(), - rootFrame)); + PR_PL(("%s %d %d %p %p %p\n", types[po->mFrameType], po->IsPrintable(), + po->mHasBeenPrinted, po, po->mDocShell.get(), rootFrame)); } } diff --git a/layout/printing/nsPrintJob.h b/layout/printing/nsPrintJob.h index eb332995a6858..5484bb2b54b07 100644 --- a/layout/printing/nsPrintJob.h +++ b/layout/printing/nsPrintJob.h @@ -29,7 +29,7 @@ class nsIDocShell; class nsIDocumentViewerPrint; class nsPrintObject; class nsIDocShell; -class nsIPageSequenceFrame; +class nsPageSequenceFrame; namespace mozilla { class PresShell; @@ -113,10 +113,8 @@ class nsPrintJob final : public nsIObserver, bool IsDoingPrint() const { return mIsDoingPrinting; } bool IsDoingPrintPreview() const { return mIsDoingPrintPreview; } - bool IsFramesetDocument() const; bool IsIFrameSelected(); bool IsRangeSelection(); - bool IsFramesetFrameSelected() const; /// If the returned value is not greater than zero, an error occurred. int32_t GetPrintPreviewNumPages(); /// Callers are responsible for free'ing aResult. @@ -181,8 +179,6 @@ class nsPrintJob final : public nsIObserver, MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult ReflowPrintObject(const mozilla::UniquePtr& aPO); - void CheckForChildFrameSets(const mozilla::UniquePtr& aPO); - void CalcNumPrintablePages(int32_t& aNumPages); void ShowPrintProgress(bool aIsForPrinting, bool& aDoNotify); nsresult CleanupOnFailure(nsresult aResult, bool aIsPrinting); diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 48491362bd067..4ac98790c04f3 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -1745,8 +1745,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay { mozilla::StyleDisplay::RubyBase == mDisplay || mozilla::StyleDisplay::RubyBaseContainer == mDisplay || mozilla::StyleDisplay::RubyText == mDisplay || - mozilla::StyleDisplay::RubyTextContainer == mDisplay || - mozilla::StyleDisplay::Contents == mDisplay; + mozilla::StyleDisplay::RubyTextContainer == mDisplay; } bool IsBlockOutsideStyle() const { @@ -1773,8 +1772,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay { mozilla::StyleDisplay::RubyBase == aDisplay || mozilla::StyleDisplay::RubyBaseContainer == aDisplay || mozilla::StyleDisplay::RubyText == aDisplay || - mozilla::StyleDisplay::RubyTextContainer == aDisplay || - mozilla::StyleDisplay::Contents == aDisplay; + mozilla::StyleDisplay::RubyTextContainer == aDisplay; } bool IsInlineOutsideStyle() const { diff --git a/layout/svg/SVGGeometryFrame.cpp b/layout/svg/SVGGeometryFrame.cpp index faad162d106d2..5ebd8b8c2934e 100644 --- a/layout/svg/SVGGeometryFrame.cpp +++ b/layout/svg/SVGGeometryFrame.cpp @@ -500,8 +500,7 @@ SVGBBox SVGGeometryFrame::GetBBoxContribution(const Matrix& aToBBoxUserspace, // wrap the cached cairo_surface_t from ScreenReferenceSurface(): RefPtr refSurf = gfxPlatform::GetPlatform()->ScreenReferenceSurface(); - tmpDT = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface( - refSurf, IntSize(1, 1)); + tmpDT = gfxPlatform::CreateDrawTargetForSurface(refSurf, IntSize(1, 1)); #else tmpDT = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget(); #endif diff --git a/layout/tools/reftest/reftest-content.js b/layout/tools/reftest/reftest-content.js index b12f212a3d715..2f2a628fa76cf 100644 --- a/layout/tools/reftest/reftest-content.js +++ b/layout/tools/reftest/reftest-content.js @@ -256,7 +256,6 @@ function printToPdf(callback) { ps.printBGColors = true; ps.printToFile = true; ps.toFileName = file.path; - ps.printFrameType = Ci.nsIPrintSettings.kFramesAsIs; ps.outputFormat = Ci.nsIPrintSettings.kOutputFormatPDF; if (isPrintSelection) { diff --git a/mobile/android/chrome/content/PrintHelper.js b/mobile/android/chrome/content/PrintHelper.js index 7ac989230faed..5beabe9fa7342 100644 --- a/mobile/android/chrome/content/PrintHelper.js +++ b/mobile/android/chrome/content/PrintHelper.js @@ -34,7 +34,6 @@ var PrintHelper = { printSettings.printBGColors = false; printSettings.printToFile = true; printSettings.toFileName = file.path; - printSettings.printFrameType = Ci.nsIPrintSettings.kFramesAsIs; printSettings.outputFormat = Ci.nsIPrintSettings.kOutputFormatPDF; let webBrowserPrint = aBrowser.contentWindow.getInterface(Ci.nsIWebBrowserPrint); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 8dd4d2486235d..eeb586cab9dd0 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -3865,9 +3865,6 @@ pref("layout.word_select.eat_space_to_next_word", true); // scrollbar snapping region pref("slider.snapMultiplier", 6); -// Whether to extend the native dialog with information on printing frames. -pref("print.extend_native_print_dialog", true); - // Locate plugins by the directories specified in the Windows registry for PLIDs // Which is currently HKLM\Software\MozillaPlugins\xxxPLIDxxx\Path pref("plugin.scan.plid.all", true); diff --git a/security/nss/TAG-INFO b/security/nss/TAG-INFO index ff30ac5d8e95f..c87d07b2306df 100644 --- a/security/nss/TAG-INFO +++ b/security/nss/TAG-INFO @@ -1 +1 @@ -29a48b604602 +8082be3a6363 diff --git a/security/nss/automation/abi-check/expected-report-libnss3.so.txt b/security/nss/automation/abi-check/expected-report-libnss3.so.txt index e69de29bb2d1d..76d0de68876c4 100644 --- a/security/nss/automation/abi-check/expected-report-libnss3.so.txt +++ b/security/nss/automation/abi-check/expected-report-libnss3.so.txt @@ -0,0 +1,4 @@ + +1 Added function: + + 'function SECStatus PK11_FindRawCertsWithSubject(PK11SlotInfo*, SECItem*, CERTCertificateList**)' {PK11_FindRawCertsWithSubject@@NSS_3.45} diff --git a/security/nss/coreconf/coreconf.dep b/security/nss/coreconf/coreconf.dep index 5182f75552c81..590d1bfaeee3f 100644 --- a/security/nss/coreconf/coreconf.dep +++ b/security/nss/coreconf/coreconf.dep @@ -10,3 +10,4 @@ */ #error "Do not include this header file." + diff --git a/security/nss/cpputil/nss_scoped_ptrs.h b/security/nss/cpputil/nss_scoped_ptrs.h index 450e787af53f5..9b1fbb47f019e 100644 --- a/security/nss/cpputil/nss_scoped_ptrs.h +++ b/security/nss/cpputil/nss_scoped_ptrs.h @@ -14,6 +14,7 @@ #include "pk11pqg.h" #include "pk11pub.h" #include "pkcs11uri.h" +#include "secmod.h" struct ScopedDelete { void operator()(CERTCertificate* cert) { CERT_DestroyCertificate(cert); } @@ -47,6 +48,7 @@ struct ScopedDelete { SEC_PKCS12DecoderFinish(dcx); } void operator()(CERTDistNames* names) { CERT_FreeDistNames(names); } + void operator()(SECMODModule* module) { SECMOD_DestroyModule(module); } }; template @@ -82,6 +84,7 @@ SCOPED(PK11Context); SCOPED(PK11GenericObject); SCOPED(SEC_PKCS12DecoderContext); SCOPED(CERTDistNames); +SCOPED(SECMODModule); #undef SCOPED diff --git a/security/nss/gtests/common/util.h b/security/nss/gtests/common/util.h index 7ed1fd7991b53..9a4c8da10623d 100644 --- a/security/nss/gtests/common/util.h +++ b/security/nss/gtests/common/util.h @@ -8,7 +8,21 @@ #define util_h__ #include +#include +#include +#include +#include +#include #include +#if defined(_WIN32) +#include +#include +#include +#else +#include +#endif + +#include "nspr.h" static inline std::vector hex_string_to_bytes(std::string s) { std::vector bytes; @@ -18,4 +32,81 @@ static inline std::vector hex_string_to_bytes(std::string s) { return bytes; } +// Given a prefix, attempts to create a unique directory that the user can do +// work in without impacting other tests. For example, if given the prefix +// "scratch", a directory like "scratch05c17b25" will be created in the current +// working directory (or the location specified by NSS_GTEST_WORKDIR, if +// defined). +// Upon destruction, the implementation will attempt to delete the directory. +// However, no attempt is made to first remove files in the directory - the +// user is responsible for this. If the directory is not empty, deleting it will +// fail. +// Statistically, it is technically possible to fail to create a unique +// directory name, but this is extremely unlikely given the expected workload of +// this implementation. +class ScopedUniqueDirectory { + public: + explicit ScopedUniqueDirectory(const std::string &prefix) { + std::string path; + const char *workingDirectory = PR_GetEnvSecure("NSS_GTEST_WORKDIR"); + if (workingDirectory) { + path.assign(workingDirectory); + } + path.append(prefix); + for (int i = 0; i < RETRY_LIMIT; i++) { + std::string pathCopy(path); + // TryMakingDirectory will modify its input. If it fails, we want to throw + // away the modified result. + if (TryMakingDirectory(pathCopy)) { + mPath.assign(pathCopy); + break; + } + } + assert(mPath.length() > 0); +#if defined(_WIN32) + // sqldb always uses UTF-8 regardless of the current system locale. + DWORD len = + MultiByteToWideChar(CP_ACP, 0, mPath.data(), mPath.size(), nullptr, 0); + std::vector buf(len, L'\0'); + MultiByteToWideChar(CP_ACP, 0, mPath.data(), mPath.size(), buf.data(), + buf.size()); + std::wstring_convert> converter; + mUTF8Path = converter.to_bytes(std::wstring(buf.begin(), buf.end())); +#else + mUTF8Path = mPath; +#endif + } + + // NB: the directory must be empty upon destruction + ~ScopedUniqueDirectory() { assert(rmdir(mPath.c_str()) == 0); } + + const std::string &GetPath() { return mPath; } + const std::string &GetUTF8Path() { return mUTF8Path; } + + private: + static const int RETRY_LIMIT = 5; + + static void GenerateRandomName(/*in/out*/ std::string &prefix) { + std::stringstream ss; + ss << prefix; + // RAND_MAX is at least 32767. + ss << std::setfill('0') << std::setw(4) << std::hex << rand() << rand(); + // This will overwrite the value of prefix. This is a little inefficient, + // but at least it makes the code simple. + ss >> prefix; + } + + static bool TryMakingDirectory(/*in/out*/ std::string &prefix) { + GenerateRandomName(prefix); +#if defined(_WIN32) + return _mkdir(prefix.c_str()) == 0; +#else + return mkdir(prefix.c_str(), 0777) == 0; +#endif + } + + std::string mPath; + std::string mUTF8Path; +}; + #endif // util_h__ diff --git a/security/nss/gtests/pk11_gtest/manifest.mn b/security/nss/gtests/pk11_gtest/manifest.mn index 1e5c2bbad80fb..b774f1d00690c 100644 --- a/security/nss/gtests/pk11_gtest/manifest.mn +++ b/security/nss/gtests/pk11_gtest/manifest.mn @@ -7,6 +7,7 @@ DEPTH = ../.. MODULE = nss CPPSRCS = \ + pk11_aes_gcm_unittest.cc \ pk11_aeskeywrap_unittest.cc \ pk11_cbc_unittest.cc \ pk11_chacha20poly1305_unittest.cc \ @@ -14,6 +15,7 @@ CPPSRCS = \ pk11_ecdsa_unittest.cc \ pk11_encrypt_derive_unittest.cc \ pk11_export_unittest.cc \ + pk11_find_certs_unittest.cc \ pk11_import_unittest.cc \ pk11_pbkdf2_unittest.cc \ pk11_prf_unittest.cc \ diff --git a/security/nss/gtests/pk11_gtest/pk11_find_certs_unittest.cc b/security/nss/gtests/pk11_gtest/pk11_find_certs_unittest.cc new file mode 100644 index 0000000000000..bf7000b016a4f --- /dev/null +++ b/security/nss/gtests/pk11_gtest/pk11_find_certs_unittest.cc @@ -0,0 +1,347 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=4 et sw=4 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/. */ + +#include + +#include "nss.h" +#include "pk11pub.h" +#include "prenv.h" +#include "prerror.h" +#include "secmod.h" + +#include "gtest/gtest.h" +#include "nss_scoped_ptrs.h" +#include "util.h" + +namespace nss_test { + +// These test certificates were generated using pycert/pykey from +// mozilla-central (https://hg.mozilla.org/mozilla-central/file/ ... +// 9968319230a74eb8c1953444a0e6973c7500a9f8/security/manager/ssl/ ... +// tests/unit/pycert.py). + +// issuer:test cert +// subject:test cert +// issuerKey:secp256r1 +// subjectKey:secp256r1 +// serialNumber:1 +std::vector kTestCert1DER = { + 0x30, 0x82, 0x01, 0x1D, 0x30, 0x81, 0xC2, 0xA0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, + 0x63, 0x65, 0x72, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37, + 0x31, 0x31, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x18, + 0x0F, 0x32, 0x30, 0x32, 0x30, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x5A, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x65, + 0x72, 0x74, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, + 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, + 0x07, 0x03, 0x42, 0x00, 0x04, 0x4F, 0xBF, 0xBB, 0xBB, 0x61, 0xE0, 0xF8, + 0xF9, 0xB1, 0xA6, 0x0A, 0x59, 0xAC, 0x87, 0x04, 0xE2, 0xEC, 0x05, 0x0B, + 0x42, 0x3E, 0x3C, 0xF7, 0x2E, 0x92, 0x3F, 0x2C, 0x4F, 0x79, 0x4B, 0x45, + 0x5C, 0x2A, 0x69, 0xD2, 0x33, 0x45, 0x6C, 0x36, 0xC4, 0x11, 0x9D, 0x07, + 0x06, 0xE0, 0x0E, 0xED, 0xC8, 0xD1, 0x93, 0x90, 0xD7, 0x99, 0x1B, 0x7B, + 0x2D, 0x07, 0xA3, 0x04, 0xEA, 0xA0, 0x4A, 0xA6, 0xC0, 0x30, 0x0D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, + 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x5C, 0x75, 0x51, 0x9F, 0x13, + 0x11, 0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, 0xA3, 0xBC, 0x06, 0x30, 0x91, + 0xFF, 0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, 0xEC, 0xFD, 0xCB, 0x42, 0x80, + 0x0A, 0x70, 0xE6, 0x02, 0x20, 0x11, 0xFA, 0xA2, 0xCA, 0x06, 0xF3, 0xBC, + 0x5F, 0x8A, 0xCA, 0x17, 0x63, 0x36, 0x87, 0xCF, 0x8D, 0x5C, 0xA0, 0x56, + 0x84, 0x44, 0x61, 0xB2, 0x33, 0x42, 0x07, 0x58, 0x9F, 0x0C, 0x9E, 0x49, + 0x83, +}; + +// issuer:test cert +// subject:test cert +// issuerKey:secp256r1 +// subjectKey:secp256r1 +// serialNumber:2 +std::vector kTestCert2DER = { + 0x30, 0x82, 0x01, 0x1E, 0x30, 0x81, 0xC2, 0xA0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x01, 0x02, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, + 0x63, 0x65, 0x72, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37, + 0x31, 0x31, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x18, + 0x0F, 0x32, 0x30, 0x32, 0x30, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x5A, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x65, + 0x72, 0x74, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, + 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, + 0x07, 0x03, 0x42, 0x00, 0x04, 0x4F, 0xBF, 0xBB, 0xBB, 0x61, 0xE0, 0xF8, + 0xF9, 0xB1, 0xA6, 0x0A, 0x59, 0xAC, 0x87, 0x04, 0xE2, 0xEC, 0x05, 0x0B, + 0x42, 0x3E, 0x3C, 0xF7, 0x2E, 0x92, 0x3F, 0x2C, 0x4F, 0x79, 0x4B, 0x45, + 0x5C, 0x2A, 0x69, 0xD2, 0x33, 0x45, 0x6C, 0x36, 0xC4, 0x11, 0x9D, 0x07, + 0x06, 0xE0, 0x0E, 0xED, 0xC8, 0xD1, 0x93, 0x90, 0xD7, 0x99, 0x1B, 0x7B, + 0x2D, 0x07, 0xA3, 0x04, 0xEA, 0xA0, 0x4A, 0xA6, 0xC0, 0x30, 0x0D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, + 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5C, 0x75, 0x51, 0x9F, 0x13, + 0x11, 0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, 0xA3, 0xBC, 0x06, 0x30, 0x91, + 0xFF, 0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, 0xEC, 0xFD, 0xCB, 0x42, 0x80, + 0x0A, 0x70, 0xE6, 0x02, 0x21, 0x00, 0xF6, 0x5E, 0x42, 0xC7, 0x54, 0x40, + 0x81, 0xE9, 0x4C, 0x16, 0x48, 0xB1, 0x39, 0x0A, 0xA0, 0xE2, 0x8C, 0x23, + 0xAA, 0xC5, 0xBB, 0xAC, 0xEB, 0x9B, 0x15, 0x0B, 0x2F, 0xB7, 0xF5, 0x85, + 0xB2, 0x54, +}; + +std::vector kTestCertSubjectDER = { + 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x65, 0x72, 0x74, +}; + +// issuer:test cert +// subject:unrelated subject DN +// issuerKey:secp256r1 +// subjectKey:secp256r1 +// serialNumber:3 +std::vector kUnrelatedTestCertDER = { + 0x30, 0x82, 0x01, 0x28, 0x30, 0x81, 0xCD, 0xA0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x01, 0x03, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, + 0x63, 0x65, 0x72, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37, + 0x31, 0x31, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x18, + 0x0F, 0x32, 0x30, 0x32, 0x30, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x5A, 0x30, 0x1F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x14, 0x75, 0x6E, 0x72, 0x65, 0x6C, 0x61, 0x74, + 0x65, 0x64, 0x20, 0x73, 0x75, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x20, 0x44, + 0x4E, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, + 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, + 0x03, 0x42, 0x00, 0x04, 0x4F, 0xBF, 0xBB, 0xBB, 0x61, 0xE0, 0xF8, 0xF9, + 0xB1, 0xA6, 0x0A, 0x59, 0xAC, 0x87, 0x04, 0xE2, 0xEC, 0x05, 0x0B, 0x42, + 0x3E, 0x3C, 0xF7, 0x2E, 0x92, 0x3F, 0x2C, 0x4F, 0x79, 0x4B, 0x45, 0x5C, + 0x2A, 0x69, 0xD2, 0x33, 0x45, 0x6C, 0x36, 0xC4, 0x11, 0x9D, 0x07, 0x06, + 0xE0, 0x0E, 0xED, 0xC8, 0xD1, 0x93, 0x90, 0xD7, 0x99, 0x1B, 0x7B, 0x2D, + 0x07, 0xA3, 0x04, 0xEA, 0xA0, 0x4A, 0xA6, 0xC0, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, + 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x5C, 0x75, 0x51, 0x9F, 0x13, 0x11, + 0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, 0xA3, 0xBC, 0x06, 0x30, 0x91, 0xFF, + 0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, 0xEC, 0xFD, 0xCB, 0x42, 0x80, 0x0A, + 0x70, 0xE6, 0x02, 0x20, 0x0F, 0x1A, 0x04, 0xC2, 0xF8, 0xBA, 0xC2, 0x94, + 0x26, 0x6E, 0xBC, 0x91, 0x7D, 0xDB, 0x75, 0x7B, 0xE8, 0xA3, 0x4F, 0x69, + 0x1B, 0xF3, 0x1F, 0x2C, 0xCE, 0x82, 0x67, 0xC9, 0x5B, 0xBB, 0xBA, 0x0A, +}; + +class PK11FindRawCertsBySubjectTest : public ::testing::Test { + protected: + PK11FindRawCertsBySubjectTest() + : mSlot(nullptr), mTestCertDBDir("PK11FindRawCertsBySubjectTest-") {} + + virtual void SetUp() { + std::string testCertDBPath(mTestCertDBDir.GetPath()); + const char* testName = + ::testing::UnitTest::GetInstance()->current_test_info()->name(); + std::string modspec = "configDir='sql:"; + modspec.append(testCertDBPath); + modspec.append("' tokenDescription='"); + modspec.append(testName); + modspec.append("'"); + mSlot = SECMOD_OpenUserDB(modspec.c_str()); + ASSERT_NE(mSlot, nullptr); + } + + virtual void TearDown() { + ASSERT_EQ(SECMOD_CloseUserDB(mSlot), SECSuccess); + PK11_FreeSlot(mSlot); + std::string testCertDBPath(mTestCertDBDir.GetPath()); + ASSERT_EQ(0, unlink((testCertDBPath + "/cert9.db").c_str())); + ASSERT_EQ(0, unlink((testCertDBPath + "/key4.db").c_str())); + } + + PK11SlotInfo* mSlot; + ScopedUniqueDirectory mTestCertDBDir; +}; + +// If we don't have any certificates, we shouldn't get any when we search for +// them. +TEST_F(PK11FindRawCertsBySubjectTest, TestNoCertsImportedNoCertsFound) { + SECItem subjectItem = {siBuffer, + const_cast(kTestCertSubjectDER.data()), + (unsigned int)kTestCertSubjectDER.size()}; + CERTCertificateList* certificates = nullptr; + SECStatus rv = + PK11_FindRawCertsWithSubject(mSlot, &subjectItem, &certificates); + EXPECT_EQ(rv, SECSuccess); + EXPECT_EQ(certificates, nullptr); +} + +// If we have one certificate but it has an unrelated subject DN, we shouldn't +// get it when we search. +TEST_F(PK11FindRawCertsBySubjectTest, TestOneCertImportedNoCertsFound) { + char certNickname[] = "Unrelated Cert"; + SECItem certItem = {siBuffer, + const_cast(kUnrelatedTestCertDER.data()), + (unsigned int)kUnrelatedTestCertDER.size()}; + ASSERT_EQ(PK11_ImportDERCert(mSlot, &certItem, CK_INVALID_HANDLE, + certNickname, false), + SECSuccess); + + SECItem subjectItem = {siBuffer, + const_cast(kTestCertSubjectDER.data()), + (unsigned int)kTestCertSubjectDER.size()}; + CERTCertificateList* certificates = nullptr; + SECStatus rv = + PK11_FindRawCertsWithSubject(mSlot, &subjectItem, &certificates); + EXPECT_EQ(rv, SECSuccess); + EXPECT_EQ(certificates, nullptr); +} + +TEST_F(PK11FindRawCertsBySubjectTest, TestMultipleMatchingCertsFound) { + char cert1Nickname[] = "Test Cert 1"; + SECItem cert1Item = {siBuffer, + const_cast(kTestCert1DER.data()), + (unsigned int)kTestCert1DER.size()}; + ASSERT_EQ(PK11_ImportDERCert(mSlot, &cert1Item, CK_INVALID_HANDLE, + cert1Nickname, false), + SECSuccess); + char cert2Nickname[] = "Test Cert 2"; + SECItem cert2Item = {siBuffer, + const_cast(kTestCert2DER.data()), + (unsigned int)kTestCert2DER.size()}; + ASSERT_EQ(PK11_ImportDERCert(mSlot, &cert2Item, CK_INVALID_HANDLE, + cert2Nickname, false), + SECSuccess); + char unrelatedCertNickname[] = "Unrelated Test Cert"; + SECItem unrelatedCertItem = { + siBuffer, const_cast(kUnrelatedTestCertDER.data()), + (unsigned int)kUnrelatedTestCertDER.size()}; + ASSERT_EQ(PK11_ImportDERCert(mSlot, &unrelatedCertItem, CK_INVALID_HANDLE, + unrelatedCertNickname, false), + SECSuccess); + + CERTCertificateList* certificates = nullptr; + SECItem subjectItem = {siBuffer, + const_cast(kTestCertSubjectDER.data()), + (unsigned int)kTestCertSubjectDER.size()}; + SECStatus rv = + PK11_FindRawCertsWithSubject(mSlot, &subjectItem, &certificates); + EXPECT_EQ(rv, SECSuccess); + ASSERT_NE(certificates, nullptr); + ScopedCERTCertificateList scopedCertificates(certificates); + ASSERT_EQ(scopedCertificates->len, 2); + + std::vector foundCert1( + scopedCertificates->certs[0].data, + scopedCertificates->certs[0].data + scopedCertificates->certs[0].len); + std::vector foundCert2( + scopedCertificates->certs[1].data, + scopedCertificates->certs[1].data + scopedCertificates->certs[1].len); + EXPECT_TRUE(foundCert1 == kTestCert1DER || foundCert1 == kTestCert2DER); + EXPECT_TRUE(foundCert2 == kTestCert1DER || foundCert2 == kTestCert2DER); + EXPECT_TRUE(foundCert1 != foundCert2); +} + +// If we try to search the internal slots, we won't find the certificate we just +// imported (because it's on a different slot). +TEST_F(PK11FindRawCertsBySubjectTest, TestNoCertsOnInternalSlots) { + char cert1Nickname[] = "Test Cert 1"; + SECItem cert1Item = {siBuffer, + const_cast(kTestCert1DER.data()), + (unsigned int)kTestCert1DER.size()}; + ASSERT_EQ(PK11_ImportDERCert(mSlot, &cert1Item, CK_INVALID_HANDLE, + cert1Nickname, false), + SECSuccess); + + SECItem subjectItem = {siBuffer, + const_cast(kTestCertSubjectDER.data()), + (unsigned int)kTestCertSubjectDER.size()}; + CERTCertificateList* internalKeySlotCertificates = nullptr; + ScopedPK11SlotInfo internalKeySlot(PK11_GetInternalKeySlot()); + SECStatus rv = PK11_FindRawCertsWithSubject( + internalKeySlot.get(), &subjectItem, &internalKeySlotCertificates); + EXPECT_EQ(rv, SECSuccess); + EXPECT_EQ(internalKeySlotCertificates, nullptr); + + CERTCertificateList* internalSlotCertificates = nullptr; + ScopedPK11SlotInfo internalSlot(PK11_GetInternalSlot()); + rv = PK11_FindRawCertsWithSubject(internalSlot.get(), &subjectItem, + &internalSlotCertificates); + EXPECT_EQ(rv, SECSuccess); + EXPECT_EQ(internalSlotCertificates, nullptr); +} + +// issuer:test cert +// subject:(empty - this had to be done by hand as pycert doesn't support this) +// issuerKey:secp256r1 +// subjectKey:secp256r1 +// serialNumber:4 +std::vector kEmptySubjectCertDER = { + 0x30, 0x82, 0x01, 0x09, 0x30, 0x81, 0xAE, 0xA0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x01, 0x04, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, + 0x63, 0x65, 0x72, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37, + 0x31, 0x31, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x18, + 0x0F, 0x32, 0x30, 0x32, 0x30, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x5A, 0x30, 0x00, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, + 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, + 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4F, 0xBF, 0xBB, + 0xBB, 0x61, 0xE0, 0xF8, 0xF9, 0xB1, 0xA6, 0x0A, 0x59, 0xAC, 0x87, 0x04, + 0xE2, 0xEC, 0x05, 0x0B, 0x42, 0x3E, 0x3C, 0xF7, 0x2E, 0x92, 0x3F, 0x2C, + 0x4F, 0x79, 0x4B, 0x45, 0x5C, 0x2A, 0x69, 0xD2, 0x33, 0x45, 0x6C, 0x36, + 0xC4, 0x11, 0x9D, 0x07, 0x06, 0xE0, 0x0E, 0xED, 0xC8, 0xD1, 0x93, 0x90, + 0xD7, 0x99, 0x1B, 0x7B, 0x2D, 0x07, 0xA3, 0x04, 0xEA, 0xA0, 0x4A, 0xA6, + 0xC0, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x01, 0x0B, 0x05, 0x00, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x5C, + 0x75, 0x51, 0x9F, 0x13, 0x11, 0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, 0xA3, + 0xBC, 0x06, 0x30, 0x91, 0xFF, 0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, 0xEC, + 0xFD, 0xCB, 0x42, 0x80, 0x0A, 0x70, 0xE6, 0x02, 0x20, 0x31, 0x1B, 0x92, + 0xAA, 0xA8, 0xB7, 0x51, 0x52, 0x7B, 0x64, 0xD6, 0xF7, 0x2F, 0x0C, 0xFB, + 0xBB, 0xD5, 0xDF, 0x86, 0xA3, 0x97, 0x96, 0x60, 0x42, 0xDA, 0xD4, 0xA8, + 0x5F, 0x2F, 0xA4, 0xDE, 0x7C}; + +std::vector kEmptySubjectDER = {0x30, 0x00}; + +// This certificate has the smallest possible subject. Finding it should work. +TEST_F(PK11FindRawCertsBySubjectTest, TestFindEmptySubject) { + char emptySubjectCertNickname[] = "Empty Subject Cert"; + SECItem emptySubjectCertItem = { + siBuffer, const_cast(kEmptySubjectCertDER.data()), + (unsigned int)kEmptySubjectCertDER.size()}; + ASSERT_EQ(PK11_ImportDERCert(mSlot, &emptySubjectCertItem, CK_INVALID_HANDLE, + emptySubjectCertNickname, false), + SECSuccess); + + SECItem subjectItem = {siBuffer, + const_cast(kEmptySubjectDER.data()), + (unsigned int)kEmptySubjectDER.size()}; + CERTCertificateList* certificates = nullptr; + SECStatus rv = + PK11_FindRawCertsWithSubject(mSlot, &subjectItem, &certificates); + EXPECT_EQ(rv, SECSuccess); + ASSERT_NE(certificates, nullptr); + ScopedCERTCertificateList scopedCertificates(certificates); + ASSERT_EQ(scopedCertificates->len, 1); + + std::vector foundCert( + scopedCertificates->certs[0].data, + scopedCertificates->certs[0].data + scopedCertificates->certs[0].len); + EXPECT_EQ(foundCert, kEmptySubjectCertDER); +} + +// Searching for a zero-length subject doesn't make sense (the minimum subject +// is the SEQUENCE tag followed by a length byte of 0), but it shouldn't cause +// problems. +TEST_F(PK11FindRawCertsBySubjectTest, TestSearchForNullSubject) { + char cert1Nickname[] = "Test Cert 1"; + SECItem cert1Item = {siBuffer, + const_cast(kTestCert1DER.data()), + (unsigned int)kTestCert1DER.size()}; + ASSERT_EQ(PK11_ImportDERCert(mSlot, &cert1Item, CK_INVALID_HANDLE, + cert1Nickname, false), + SECSuccess); + + SECItem subjectItem = {siBuffer, nullptr, 0}; + CERTCertificateList* certificates = nullptr; + SECStatus rv = + PK11_FindRawCertsWithSubject(mSlot, &subjectItem, &certificates); + EXPECT_EQ(rv, SECSuccess); + EXPECT_EQ(certificates, nullptr); +} + +} // namespace nss_test diff --git a/security/nss/gtests/pk11_gtest/pk11_gtest.gyp b/security/nss/gtests/pk11_gtest/pk11_gtest.gyp index 0ffed1f9c3940..8d7bf7e8e023e 100644 --- a/security/nss/gtests/pk11_gtest/pk11_gtest.gyp +++ b/security/nss/gtests/pk11_gtest/pk11_gtest.gyp @@ -19,6 +19,7 @@ 'pk11_curve25519_unittest.cc', 'pk11_ecdsa_unittest.cc', 'pk11_encrypt_derive_unittest.cc', + 'pk11_find_certs_unittest.cc', 'pk11_import_unittest.cc', 'pk11_pbkdf2_unittest.cc', 'pk11_prf_unittest.cc', diff --git a/security/nss/gtests/softoken_gtest/manifest.mn b/security/nss/gtests/softoken_gtest/manifest.mn index 4b34c099f5761..0e998adf4c15b 100644 --- a/security/nss/gtests/softoken_gtest/manifest.mn +++ b/security/nss/gtests/softoken_gtest/manifest.mn @@ -12,6 +12,7 @@ CPPSRCS = \ INCLUDES += \ -I$(CORE_DEPTH)/gtests/google_test/gtest/include \ + -I$(CORE_DEPTH)/gtests/common \ -I$(CORE_DEPTH)/cpputil \ $(NULL) diff --git a/security/nss/gtests/softoken_gtest/softoken_gtest.cc b/security/nss/gtests/softoken_gtest/softoken_gtest.cc index 5e2a497b8b0a2..c6cd32afdb63e 100644 --- a/security/nss/gtests/softoken_gtest/softoken_gtest.cc +++ b/security/nss/gtests/softoken_gtest/softoken_gtest.cc @@ -1,9 +1,3 @@ -#include -#if defined(_WIN32) -#include -#include -#endif - #include "cert.h" #include "certdb.h" #include "nspr.h" @@ -12,93 +6,13 @@ #include "secerr.h" #include "nss_scoped_ptrs.h" +#include "util.h" #define GTEST_HAS_RTTI 0 #include "gtest/gtest.h" namespace nss_test { -// Given a prefix, attempts to create a unique directory that the user can do -// work in without impacting other tests. For example, if given the prefix -// "scratch", a directory like "scratch05c17b25" will be created in the current -// working directory (or the location specified by NSS_GTEST_WORKDIR, if -// defined). -// Upon destruction, the implementation will attempt to delete the directory. -// However, no attempt is made to first remove files in the directory - the -// user is responsible for this. If the directory is not empty, deleting it will -// fail. -// Statistically, it is technically possible to fail to create a unique -// directory name, but this is extremely unlikely given the expected workload of -// this implementation. -class ScopedUniqueDirectory { - public: - explicit ScopedUniqueDirectory(const std::string &prefix); - - // NB: the directory must be empty upon destruction - ~ScopedUniqueDirectory() { assert(rmdir(mPath.c_str()) == 0); } - - const std::string &GetPath() { return mPath; } - const std::string &GetUTF8Path() { return mUTF8Path; } - - private: - static const int RETRY_LIMIT = 5; - static void GenerateRandomName(/*in/out*/ std::string &prefix); - static bool TryMakingDirectory(/*in/out*/ std::string &prefix); - - std::string mPath; - std::string mUTF8Path; -}; - -ScopedUniqueDirectory::ScopedUniqueDirectory(const std::string &prefix) { - std::string path; - const char *workingDirectory = PR_GetEnvSecure("NSS_GTEST_WORKDIR"); - if (workingDirectory) { - path.assign(workingDirectory); - } - path.append(prefix); - for (int i = 0; i < RETRY_LIMIT; i++) { - std::string pathCopy(path); - // TryMakingDirectory will modify its input. If it fails, we want to throw - // away the modified result. - if (TryMakingDirectory(pathCopy)) { - mPath.assign(pathCopy); - break; - } - } - assert(mPath.length() > 0); -#if defined(_WIN32) - // sqldb always uses UTF-8 regardless of the current system locale. - DWORD len = - MultiByteToWideChar(CP_ACP, 0, mPath.data(), mPath.size(), nullptr, 0); - std::vector buf(len, L'\0'); - MultiByteToWideChar(CP_ACP, 0, mPath.data(), mPath.size(), buf.data(), - buf.size()); - std::wstring_convert> converter; - mUTF8Path = converter.to_bytes(std::wstring(buf.begin(), buf.end())); -#else - mUTF8Path = mPath; -#endif -} - -void ScopedUniqueDirectory::GenerateRandomName(std::string &prefix) { - std::stringstream ss; - ss << prefix; - // RAND_MAX is at least 32767. - ss << std::setfill('0') << std::setw(4) << std::hex << rand() << rand(); - // This will overwrite the value of prefix. This is a little inefficient, but - // at least it makes the code simple. - ss >> prefix; -} - -bool ScopedUniqueDirectory::TryMakingDirectory(std::string &prefix) { - GenerateRandomName(prefix); -#if defined(_WIN32) - return _mkdir(prefix.c_str()) == 0; -#else - return mkdir(prefix.c_str(), 0777) == 0; -#endif -} - class SoftokenTest : public ::testing::Test { protected: SoftokenTest() : mNSSDBDir("SoftokenTest.d-") {} diff --git a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp index 304e8da176264..c0f6c1cd22b9a 100644 --- a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp +++ b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp @@ -93,7 +93,7 @@ '<(DEPTH)/lib/dbm/src/src.gyp:dbm', ], }], - [ 'enable_sslkeylogfile==1', { + [ 'enable_sslkeylogfile==1 and sanitizer_flags==0', { 'sources': [ 'ssl_keylog_unittest.cc', ], diff --git a/security/nss/lib/ckfw/builtins/certdata.txt b/security/nss/lib/ckfw/builtins/certdata.txt index 61ce1dee63db3..3466f6ee40ed9 100644 --- a/security/nss/lib/ckfw/builtins/certdata.txt +++ b/security/nss/lib/ckfw/builtins/certdata.txt @@ -17745,172 +17745,6 @@ CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE -# -# Certificate "Certinomis - Root CA" -# -# Issuer: CN=Certinomis - Root CA,OU=0002 433998903,O=Certinomis,C=FR -# Serial Number: 1 (0x1) -# Subject: CN=Certinomis - Root CA,OU=0002 433998903,O=Certinomis,C=FR -# Not Valid Before: Mon Oct 21 09:17:18 2013 -# Not Valid After : Fri Oct 21 09:17:18 2033 -# Fingerprint (SHA-256): 2A:99:F5:BC:11:74:B7:3C:BB:1D:62:08:84:E0:1C:34:E5:1C:CB:39:78:DA:12:5F:0E:33:26:88:83:BF:41:58 -# Fingerprint (SHA1): 9D:70:BB:01:A5:A4:A0:18:11:2E:F7:1C:01:B9:32:C5:34:E7:88:A8 -CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE -CKA_TOKEN CK_BBOOL CK_TRUE -CKA_PRIVATE CK_BBOOL CK_FALSE -CKA_MODIFIABLE CK_BBOOL CK_FALSE -CKA_LABEL UTF8 "Certinomis - Root CA" -CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 -CKA_SUBJECT MULTILINE_OCTAL -\060\132\061\013\060\011\006\003\125\004\006\023\002\106\122\061 -\023\060\021\006\003\125\004\012\023\012\103\145\162\164\151\156 -\157\155\151\163\061\027\060\025\006\003\125\004\013\023\016\060 -\060\060\062\040\064\063\063\071\071\070\071\060\063\061\035\060 -\033\006\003\125\004\003\023\024\103\145\162\164\151\156\157\155 -\151\163\040\055\040\122\157\157\164\040\103\101 -END -CKA_ID UTF8 "0" -CKA_ISSUER MULTILINE_OCTAL -\060\132\061\013\060\011\006\003\125\004\006\023\002\106\122\061 -\023\060\021\006\003\125\004\012\023\012\103\145\162\164\151\156 -\157\155\151\163\061\027\060\025\006\003\125\004\013\023\016\060 -\060\060\062\040\064\063\063\071\071\070\071\060\063\061\035\060 -\033\006\003\125\004\003\023\024\103\145\162\164\151\156\157\155 -\151\163\040\055\040\122\157\157\164\040\103\101 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\001\001 -END -CKA_VALUE MULTILINE_OCTAL -\060\202\005\222\060\202\003\172\240\003\002\001\002\002\001\001 -\060\015\006\011\052\206\110\206\367\015\001\001\013\005\000\060 -\132\061\013\060\011\006\003\125\004\006\023\002\106\122\061\023 -\060\021\006\003\125\004\012\023\012\103\145\162\164\151\156\157 -\155\151\163\061\027\060\025\006\003\125\004\013\023\016\060\060 -\060\062\040\064\063\063\071\071\070\071\060\063\061\035\060\033 -\006\003\125\004\003\023\024\103\145\162\164\151\156\157\155\151 -\163\040\055\040\122\157\157\164\040\103\101\060\036\027\015\061 -\063\061\060\062\061\060\071\061\067\061\070\132\027\015\063\063 -\061\060\062\061\060\071\061\067\061\070\132\060\132\061\013\060 -\011\006\003\125\004\006\023\002\106\122\061\023\060\021\006\003 -\125\004\012\023\012\103\145\162\164\151\156\157\155\151\163\061 -\027\060\025\006\003\125\004\013\023\016\060\060\060\062\040\064 -\063\063\071\071\070\071\060\063\061\035\060\033\006\003\125\004 -\003\023\024\103\145\162\164\151\156\157\155\151\163\040\055\040 -\122\157\157\164\040\103\101\060\202\002\042\060\015\006\011\052 -\206\110\206\367\015\001\001\001\005\000\003\202\002\017\000\060 -\202\002\012\002\202\002\001\000\324\314\011\012\054\077\222\366 -\177\024\236\013\234\232\152\035\100\060\144\375\252\337\016\036 -\006\133\237\120\205\352\315\215\253\103\147\336\260\372\176\200 -\226\236\204\170\222\110\326\343\071\356\316\344\131\130\227\345 -\056\047\230\352\223\250\167\233\112\360\357\164\200\055\353\060 -\037\265\331\307\200\234\142\047\221\210\360\112\211\335\334\210 -\346\024\371\325\003\057\377\225\333\275\237\354\054\372\024\025 -\131\225\012\306\107\174\151\030\271\247\003\371\312\166\251\317 -\307\157\264\136\005\376\356\301\122\262\165\062\207\354\355\051 -\146\073\363\112\026\202\366\326\232\333\162\230\351\336\360\305 -\114\245\253\265\352\001\342\214\056\144\177\144\157\375\243\045 -\223\213\310\242\016\111\215\064\360\037\354\130\105\056\064\252 -\204\120\275\347\262\112\023\270\260\017\256\070\135\260\251\033 -\346\163\311\132\241\331\146\100\252\251\115\246\064\002\255\204 -\176\262\043\301\373\052\306\147\364\064\266\260\225\152\063\117 -\161\104\265\255\300\171\063\210\340\277\355\243\240\024\264\234 -\011\260\012\343\140\276\370\370\146\210\315\133\361\167\005\340 -\265\163\156\301\175\106\056\216\113\047\246\315\065\012\375\345 -\115\175\252\052\243\051\307\132\150\004\350\345\326\223\244\142 -\302\305\346\364\117\306\371\237\032\215\202\111\031\212\312\131 -\103\072\350\015\062\301\364\114\023\003\157\156\246\077\221\163 -\313\312\163\157\022\040\213\356\300\202\170\336\113\056\302\111 -\303\035\355\026\366\044\364\047\033\134\127\061\334\125\356\250 -\036\157\154\254\342\105\314\127\127\212\165\127\031\340\265\130 -\231\111\066\061\074\063\001\155\026\112\315\270\052\203\204\206 -\233\371\140\322\037\155\221\003\323\140\246\325\075\232\335\167 -\220\075\065\244\237\017\136\365\122\104\151\271\300\272\334\317 -\175\337\174\331\304\254\206\042\062\274\173\153\221\357\172\370 -\027\150\260\342\123\125\140\055\257\076\302\203\330\331\011\053 -\360\300\144\333\207\213\221\314\221\353\004\375\166\264\225\232 -\346\024\006\033\325\064\035\276\330\377\164\034\123\205\231\340 -\131\122\112\141\355\210\236\153\111\211\106\176\040\132\331\347 -\112\345\152\356\322\145\021\103\002\003\001\000\001\243\143\060 -\141\060\016\006\003\125\035\017\001\001\377\004\004\003\002\001 -\006\060\017\006\003\125\035\023\001\001\377\004\005\060\003\001 -\001\377\060\035\006\003\125\035\016\004\026\004\024\357\221\114 -\365\245\303\060\350\057\010\352\323\161\042\244\222\150\170\164 -\331\060\037\006\003\125\035\043\004\030\060\026\200\024\357\221 -\114\365\245\303\060\350\057\010\352\323\161\042\244\222\150\170 -\164\331\060\015\006\011\052\206\110\206\367\015\001\001\013\005 -\000\003\202\002\001\000\176\075\124\332\042\135\032\130\076\073 -\124\047\272\272\314\310\343\032\152\352\076\371\022\353\126\137 -\075\120\316\340\352\110\046\046\317\171\126\176\221\034\231\077 -\320\241\221\034\054\017\117\230\225\131\123\275\320\042\330\210 -\135\234\067\374\373\144\301\170\214\213\232\140\011\352\325\372 -\041\137\320\164\145\347\120\305\277\056\271\013\013\255\265\260 -\027\246\022\214\324\142\170\352\126\152\354\012\322\100\303\074 -\005\060\076\115\224\267\237\112\003\323\175\047\113\266\376\104 -\316\372\031\063\032\155\244\102\321\335\314\310\310\327\026\122 -\203\117\065\224\263\022\125\175\345\342\102\353\344\234\223\011 -\300\114\133\007\253\307\155\021\240\120\027\224\043\250\265\012 -\222\017\262\172\301\140\054\070\314\032\246\133\377\362\014\343 -\252\037\034\334\270\240\223\047\336\143\343\177\041\237\072\345 -\236\372\340\023\152\165\353\226\134\142\221\224\216\147\123\266 -\211\370\022\011\313\157\122\133\003\162\206\120\225\010\324\215 -\207\206\025\037\225\044\330\244\157\232\316\244\235\233\155\322 -\262\166\006\206\306\126\010\305\353\011\332\066\302\033\133\101 -\276\141\052\343\160\346\270\246\370\266\132\304\275\041\367\377 -\252\137\241\154\166\071\146\326\352\114\125\341\000\063\233\023 -\230\143\311\157\320\001\040\011\067\122\347\014\117\076\315\274 -\365\137\226\047\247\040\002\225\340\056\350\007\101\005\037\025 -\156\326\260\344\031\340\017\002\223\000\047\162\305\213\321\124 -\037\135\112\303\100\227\176\125\246\174\301\063\004\024\001\035 -\111\040\151\013\031\223\235\156\130\042\367\100\014\106\014\043 -\143\363\071\322\177\166\121\247\364\310\241\361\014\166\042\043 -\106\122\051\055\342\243\101\007\126\151\230\322\005\011\274\151 -\307\132\141\315\217\201\140\025\115\200\335\220\342\175\304\120 -\362\214\073\156\112\307\306\346\200\053\074\201\274\021\200\026 -\020\047\327\360\315\077\171\314\163\052\303\176\123\221\326\156 -\370\365\363\307\320\121\115\216\113\245\133\346\031\027\073\326 -\201\011\334\042\334\356\216\271\304\217\123\341\147\273\063\270 -\210\025\106\317\355\151\065\377\165\015\106\363\316\161\341\305 -\153\206\102\006\271\101 -END -CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE - -# Trust for "Certinomis - Root CA" -# Issuer: CN=Certinomis - Root CA,OU=0002 433998903,O=Certinomis,C=FR -# Serial Number: 1 (0x1) -# Subject: CN=Certinomis - Root CA,OU=0002 433998903,O=Certinomis,C=FR -# Not Valid Before: Mon Oct 21 09:17:18 2013 -# Not Valid After : Fri Oct 21 09:17:18 2033 -# Fingerprint (SHA-256): 2A:99:F5:BC:11:74:B7:3C:BB:1D:62:08:84:E0:1C:34:E5:1C:CB:39:78:DA:12:5F:0E:33:26:88:83:BF:41:58 -# Fingerprint (SHA1): 9D:70:BB:01:A5:A4:A0:18:11:2E:F7:1C:01:B9:32:C5:34:E7:88:A8 -CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST -CKA_TOKEN CK_BBOOL CK_TRUE -CKA_PRIVATE CK_BBOOL CK_FALSE -CKA_MODIFIABLE CK_BBOOL CK_FALSE -CKA_LABEL UTF8 "Certinomis - Root CA" -CKA_CERT_SHA1_HASH MULTILINE_OCTAL -\235\160\273\001\245\244\240\030\021\056\367\034\001\271\062\305 -\064\347\210\250 -END -CKA_CERT_MD5_HASH MULTILINE_OCTAL -\024\012\375\215\250\050\265\070\151\333\126\176\141\042\003\077 -END -CKA_ISSUER MULTILINE_OCTAL -\060\132\061\013\060\011\006\003\125\004\006\023\002\106\122\061 -\023\060\021\006\003\125\004\012\023\012\103\145\162\164\151\156 -\157\155\151\163\061\027\060\025\006\003\125\004\013\023\016\060 -\060\060\062\040\064\063\063\071\071\070\071\060\063\061\035\060 -\033\006\003\125\004\003\023\024\103\145\162\164\151\156\157\155 -\151\163\040\055\040\122\157\157\164\040\103\101 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\001\001 -END -CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE - # # Certificate "OISTE WISeKey Global Root GB CA" # diff --git a/security/nss/lib/ckfw/builtins/nssckbi.h b/security/nss/lib/ckfw/builtins/nssckbi.h index 953c15b0a93d5..d46217eb46fc9 100644 --- a/security/nss/lib/ckfw/builtins/nssckbi.h +++ b/security/nss/lib/ckfw/builtins/nssckbi.h @@ -46,8 +46,8 @@ * It's recommend to switch back to 0 after having reached version 98/99. */ #define NSS_BUILTINS_LIBRARY_VERSION_MAJOR 2 -#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 32 -#define NSS_BUILTINS_LIBRARY_VERSION "2.32" +#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 34 +#define NSS_BUILTINS_LIBRARY_VERSION "2.34" /* These version numbers detail the semantic changes to the ckfw engine. */ #define NSS_BUILTINS_HARDWARE_VERSION_MAJOR 1 diff --git a/security/nss/lib/freebl/fipsfreebl.c b/security/nss/lib/freebl/fipsfreebl.c index 2328a677f48eb..93a9a0de72b5a 100644 --- a/security/nss/lib/freebl/fipsfreebl.c +++ b/security/nss/lib/freebl/fipsfreebl.c @@ -15,8 +15,10 @@ #include "seccomon.h" /* Required for RSA and DSA. */ #include "secerr.h" #include "prtypes.h" +#include "secitem.h" +#include "pkcs11t.h" -#include "ec.h" /* Required for ECDSA */ +#include "ec.h" /* Required for EC */ /* * different platforms have different ways of calling and initial entry point @@ -288,6 +290,8 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size) /* AES Known Plaintext (128-bits). (blocksize is 128-bits) */ static const PRUint8 aes_known_plaintext[] = { "NetscapeepacsteN" }; + static const PRUint8 aes_gcm_known_aad[] = { "MozillaallizoM" }; + /* AES Known Ciphertext (128-bit key). */ static const PRUint8 aes_ecb128_known_ciphertext[] = { 0x3c, 0xa5, 0x96, 0xf3, 0x34, 0x6a, 0x96, 0xc1, @@ -299,6 +303,13 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size) 0x15, 0x54, 0x14, 0x1d, 0x4e, 0xd8, 0xd5, 0xea }; + static const PRUint8 aes_gcm128_known_ciphertext[] = { + 0x63, 0xf4, 0x95, 0x28, 0xe6, 0x78, 0xee, 0x6e, + 0x4f, 0xe0, 0xfc, 0x8d, 0xd7, 0xa2, 0xb1, 0xff, + 0x0c, 0x97, 0x1b, 0x0a, 0xdd, 0x97, 0x75, 0xed, + 0x8b, 0xde, 0xbf, 0x16, 0x5e, 0x57, 0x6b, 0x4f + }; + /* AES Known Ciphertext (192-bit key). */ static const PRUint8 aes_ecb192_known_ciphertext[] = { 0xa0, 0x18, 0x62, 0xed, 0x88, 0x19, 0xcb, 0x62, @@ -310,6 +321,13 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size) 0x07, 0xbc, 0x43, 0x2f, 0x6d, 0xad, 0x29, 0xe1 }; + static const PRUint8 aes_gcm192_known_ciphertext[] = { + 0xc1, 0x0b, 0x92, 0x1d, 0x68, 0x21, 0xf4, 0x25, + 0x41, 0x61, 0x20, 0x2d, 0x59, 0x7f, 0x53, 0xde, + 0x93, 0x39, 0xab, 0x09, 0x76, 0x41, 0x57, 0x2b, + 0x90, 0x2e, 0x44, 0xbb, 0x52, 0x03, 0xe9, 0x07 + }; + /* AES Known Ciphertext (256-bit key). */ static const PRUint8 aes_ecb256_known_ciphertext[] = { 0xdb, 0xa6, 0x52, 0x01, 0x8a, 0x70, 0xae, 0x66, @@ -321,18 +339,29 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size) 0xc5, 0xc5, 0x68, 0x71, 0x6e, 0x34, 0x40, 0x16 }; + static const PRUint8 aes_gcm256_known_ciphertext[] = { + 0x5d, 0x9e, 0xd2, 0xa2, 0x74, 0x9c, 0xd9, 0x1c, + 0xd1, 0xc9, 0xee, 0x5d, 0xb6, 0xf2, 0xc9, 0xb6, + 0x79, 0x27, 0x53, 0x02, 0xa3, 0xdc, 0x22, 0xce, + 0xf4, 0xb0, 0xc1, 0x8c, 0x86, 0x51, 0xf5, 0xa1 + }; + const PRUint8 *aes_ecb_known_ciphertext = (aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_ecb128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_ecb192_known_ciphertext : aes_ecb256_known_ciphertext; const PRUint8 *aes_cbc_known_ciphertext = (aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_cbc128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_cbc192_known_ciphertext : aes_cbc256_known_ciphertext; + const PRUint8 *aes_gcm_known_ciphertext = + (aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_gcm128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_gcm192_known_ciphertext : aes_gcm256_known_ciphertext; + /* AES variables. */ - PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH]; - PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH]; + PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH * 2]; + PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH * 2]; AESContext *aes_context; unsigned int aes_bytes_encrypted; unsigned int aes_bytes_decrypted; + CK_GCM_PARAMS gcmParams; SECStatus aes_status; /*check if aes_key_size is 128, 192, or 256 bits */ @@ -455,6 +484,69 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size) return (SECFailure); } + /******************************************************/ + /* AES-GCM Single-Round Known Answer Encryption Test. */ + /******************************************************/ + + gcmParams.pIv = (PRUint8 *)aes_cbc_known_initialization_vector; + gcmParams.ulIvLen = FIPS_AES_BLOCK_SIZE; + gcmParams.pAAD = (PRUint8 *)aes_gcm_known_aad; + gcmParams.ulAADLen = sizeof(aes_gcm_known_aad); + gcmParams.ulTagBits = FIPS_AES_BLOCK_SIZE * 8; + aes_context = AES_CreateContext(aes_known_key, + (PRUint8 *)&gcmParams, + NSS_AES_GCM, PR_TRUE, aes_key_size, + FIPS_AES_BLOCK_SIZE); + + if (aes_context == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return (SECFailure); + } + + aes_status = AES_Encrypt(aes_context, aes_computed_ciphertext, + &aes_bytes_encrypted, FIPS_AES_ENCRYPT_LENGTH * 2, + aes_known_plaintext, + FIPS_AES_DECRYPT_LENGTH); + + AES_DestroyContext(aes_context, PR_TRUE); + + if ((aes_status != SECSuccess) || + (aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH * 2) || + (PORT_Memcmp(aes_computed_ciphertext, aes_gcm_known_ciphertext, + FIPS_AES_ENCRYPT_LENGTH * 2) != 0)) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return (SECFailure); + } + + /******************************************************/ + /* AES-GCM Single-Round Known Answer Decryption Test. */ + /******************************************************/ + + aes_context = AES_CreateContext(aes_known_key, + (PRUint8 *)&gcmParams, + NSS_AES_GCM, PR_FALSE, aes_key_size, + FIPS_AES_BLOCK_SIZE); + + if (aes_context == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return (SECFailure); + } + + aes_status = AES_Decrypt(aes_context, aes_computed_plaintext, + &aes_bytes_decrypted, FIPS_AES_DECRYPT_LENGTH * 2, + aes_gcm_known_ciphertext, + FIPS_AES_ENCRYPT_LENGTH * 2); + + AES_DestroyContext(aes_context, PR_TRUE); + + if ((aes_status != SECSuccess) || + (aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) || + (PORT_Memcmp(aes_computed_plaintext, aes_known_plaintext, + FIPS_AES_DECRYPT_LENGTH) != 0)) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return (SECFailure); + } + return (SECSuccess); } @@ -1094,7 +1186,7 @@ freebl_fips_ECDSA_Test(ECParams *ecparams, "Firefox and ThunderBird are awesome!" }; - unsigned char sha1[SHA1_LENGTH]; /* SHA-1 hash (160 bits) */ + unsigned char sha256[SHA256_LENGTH]; /* SHA-256 hash (256 bits) */ unsigned char sig[2 * MAX_ECKEY_LEN]; SECItem signature, digest; ECPrivateKey *ecdsa_private_key = NULL; @@ -1136,13 +1228,13 @@ freebl_fips_ECDSA_Test(ECParams *ecparams, /* ECDSA Single-Round Known Answer Signature Test. */ /***************************************************/ - ecdsaStatus = SHA1_HashBuf(sha1, msg, sizeof msg); + ecdsaStatus = SHA256_HashBuf(sha256, msg, sizeof msg); if (ecdsaStatus != SECSuccess) { goto loser; } digest.type = siBuffer; - digest.data = sha1; - digest.len = SHA1_LENGTH; + digest.data = sha256; + digest.len = SHA256_LENGTH; memset(sig, 0, sizeof sig); signature.type = siBuffer; @@ -1181,10 +1273,83 @@ freebl_fips_ECDSA_Test(ECParams *ecparams, } static SECStatus -freebl_fips_ECDSA_PowerUpSelfTest() +freebl_fips_ECDH_Test(ECParams *ecparams) { - /* ECDSA Known curve nistp256 == ECCCurve_X9_62_PRIME_256V1 params */ + /* ECDH Known result (reused old CAVS vector) */ + static const PRUint8 ecdh_known_pub_key_1[] = { + EC_POINT_FORM_UNCOMPRESSED, + /* pubX */ + 0x16, 0x81, 0x32, 0x86, 0xc8, 0xe4, 0x3a, 0x1f, + 0x5d, 0xe3, 0x06, 0x22, 0x8b, 0x99, 0x14, 0x25, + 0xf7, 0x9c, 0x5b, 0x1e, 0x96, 0x84, 0x85, 0x3b, + 0x17, 0xfe, 0xf3, 0x1c, 0x0e, 0xed, 0xc4, 0xce, + /* pubY */ + 0x7a, 0x44, 0xfe, 0xbd, 0x91, 0x71, 0x7d, 0x73, + 0xd9, 0x45, 0xea, 0xae, 0x66, 0x78, 0xfa, 0x6e, + 0x46, 0xcd, 0xfa, 0x95, 0x15, 0x47, 0x62, 0x5d, + 0xbb, 0x1b, 0x9f, 0xe6, 0x39, 0xfc, 0xfd, 0x47 + }; + static const PRUint8 ecdh_known_priv_key_2[] = { + 0xb4, 0x2a, 0xe3, 0x69, 0x19, 0xec, 0xf0, 0x42, + 0x6d, 0x45, 0x8c, 0x94, 0x4a, 0x26, 0xa7, 0x5c, + 0xea, 0x9d, 0xd9, 0x0f, 0x59, 0xe0, 0x1a, 0x9d, + 0x7c, 0xb7, 0x1c, 0x04, 0x53, 0xb8, 0x98, 0x5a + }; + static const PRUint8 ecdh_known_hash_result[] = { + 0x16, 0xf3, 0x85, 0xa2, 0x41, 0xf3, 0x7f, 0xc4, + 0x0b, 0x56, 0x47, 0xee, 0xa7, 0x74, 0xb9, 0xdb, + 0xe1, 0xfa, 0x22, 0xe9, 0x04, 0xf1, 0xb6, 0x12, + 0x4b, 0x44, 0x8a, 0xbb, 0xbc, 0x08, 0x2b, 0xa7, + }; + + SECItem ecdh_priv_2, ecdh_pub_1; + SECItem ZZ = { 0, 0, 0 }; + SECStatus ecdhStatus = SECSuccess; + PRUint8 computed_hash_result[HASH_LENGTH_MAX]; + + ecdh_priv_2.data = (PRUint8 *)ecdh_known_priv_key_2; + ecdh_priv_2.len = sizeof(ecdh_known_priv_key_2); + ecdh_pub_1.data = (PRUint8 *)ecdh_known_pub_key_1; + ecdh_pub_1.len = sizeof(ecdh_known_pub_key_1); + + /* Generates a new EC key pair. The private key is a supplied + * random value (in seed) and the public key is the result of + * performing a scalar point multiplication of that value with + * the curve's base point. + */ + ecdhStatus = ECDH_Derive(&ecdh_pub_1, ecparams, &ecdh_priv_2, PR_FALSE, &ZZ); + if (ecdhStatus != SECSuccess) { + goto loser; + } + ecdhStatus = SHA256_HashBuf(computed_hash_result, ZZ.data, ZZ.len); + if (ecdhStatus != SECSuccess) { + goto loser; + } + + if (PORT_Memcmp(computed_hash_result, ecdh_known_hash_result, + sizeof(ecdh_known_hash_result)) != 0) { + ecdhStatus = SECFailure; + goto loser; + } + +loser: + if (ZZ.data) { + SECITEM_FreeItem(&ZZ, PR_FALSE); + } + + if (ecdhStatus != SECSuccess) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return (SECFailure); + } + return (SECSuccess); +} + +static SECStatus +freebl_fips_EC_PowerUpSelfTest() +{ + + /* EC Known curve nistp256 == ECCCurve_X9_62_PRIME_256V1 params */ static const unsigned char p256_prime[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, @@ -1217,7 +1382,7 @@ freebl_fips_ECDSA_PowerUpSelfTest() static const unsigned char p256_encoding[] = { 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 }; - static const ECParams ecdsa_known_P256_Params = { + static const ECParams ec_known_P256_Params = { NULL, ec_params_named, /* arena, type */ /* fieldID */ { 256, ec_field_GFp, /* size and type */ @@ -1250,10 +1415,10 @@ freebl_fips_ECDSA_PowerUpSelfTest() 0x9d, 0x37, 0x4b, 0x1c, 0xdc, 0x35, 0x90, 0xff, 0x1a, 0x2d, 0x98, 0x95, 0x1b, 0x2f, 0xeb, 0x7f, 0xbb, 0x81, 0xca, 0xc0, 0x69, 0x75, 0xea, 0xc5, - 0x59, 0x6a, 0x62, 0x49, 0x3d, 0x50, 0xc9, 0xe1, - 0x27, 0x3b, 0xff, 0x9b, 0x13, 0x66, 0x67, 0xdd, - 0x7d, 0xd1, 0x0d, 0x2d, 0x7c, 0x44, 0x04, 0x1b, - 0x16, 0x21, 0x12, 0xc5, 0xcb, 0xbd, 0x9e, 0x75 + 0xa7, 0xd2, 0x20, 0xdd, 0x45, 0xf9, 0x2b, 0xdd, + 0xda, 0x98, 0x99, 0x5b, 0x1c, 0x02, 0x3a, 0x27, + 0x8b, 0x7d, 0xb6, 0xed, 0x0e, 0xe0, 0xa7, 0xac, + 0xaa, 0x36, 0x2c, 0xfa, 0x1a, 0xdf, 0x0d, 0xe1, }; ECParams ecparams; @@ -1261,13 +1426,18 @@ freebl_fips_ECDSA_PowerUpSelfTest() SECStatus rv; /* ECDSA GF(p) prime field curve test */ - ecparams = ecdsa_known_P256_Params; + ecparams = ec_known_P256_Params; rv = freebl_fips_ECDSA_Test(&ecparams, ecdsa_known_P256_signature, sizeof ecdsa_known_P256_signature); if (rv != SECSuccess) { return (SECFailure); } + /* ECDH GF(p) prime field curve test */ + rv = freebl_fips_ECDH_Test(&ecparams); + if (rv != SECSuccess) { + return (SECFailure); + } return (SECSuccess); } @@ -1417,6 +1587,138 @@ freebl_fips_DSA_PowerUpSelfTest(void) return (SECSuccess); } +static SECStatus +freebl_fips_DH_PowerUpSelfTest(void) +{ + /* DH Known P (2048-bits) */ + static const PRUint8 dh_known_P[] = { + 0xc2, 0x79, 0xbb, 0x76, 0x32, 0x0d, 0x43, 0xfd, + 0x1b, 0x8c, 0xa2, 0x3c, 0x00, 0xdd, 0x6d, 0xef, + 0xf8, 0x1a, 0xd9, 0xc1, 0xa2, 0xf5, 0x73, 0x2b, + 0xdb, 0x1a, 0x3e, 0x84, 0x90, 0xeb, 0xe7, 0x8e, + 0x5f, 0x5c, 0x6b, 0xb6, 0x61, 0x89, 0xd1, 0x03, + 0xb0, 0x5f, 0x91, 0xe4, 0xd2, 0x82, 0x90, 0xfc, + 0x3c, 0x49, 0x69, 0x59, 0xc1, 0x51, 0x6a, 0x85, + 0x71, 0xe7, 0x5d, 0x72, 0x5a, 0x45, 0xad, 0x01, + 0x6f, 0x82, 0xae, 0xec, 0x91, 0x08, 0x2e, 0x7c, + 0x64, 0x93, 0x46, 0x1c, 0x68, 0xef, 0xc2, 0x03, + 0x28, 0x1d, 0x75, 0x3a, 0xeb, 0x9c, 0x46, 0xf0, + 0xc9, 0xdb, 0x99, 0x95, 0x13, 0x66, 0x4d, 0xd5, + 0x1a, 0x78, 0x92, 0x51, 0x89, 0x72, 0x28, 0x7f, + 0x20, 0x70, 0x41, 0x49, 0xa2, 0x86, 0xe9, 0xf9, + 0x78, 0x5f, 0x8d, 0x2e, 0x5d, 0xfa, 0xdb, 0x57, + 0xd4, 0x71, 0xdf, 0x66, 0xe3, 0x9e, 0x88, 0x70, + 0xa4, 0x21, 0x44, 0x6a, 0xc7, 0xae, 0x30, 0x2c, + 0x9c, 0x1f, 0x91, 0x57, 0xc8, 0x24, 0x34, 0x2d, + 0x7a, 0x4a, 0x43, 0xc2, 0x5f, 0xab, 0x64, 0x2e, + 0xaa, 0x28, 0x32, 0x95, 0x42, 0x7b, 0xa0, 0xcc, + 0xdf, 0xfd, 0x22, 0xc8, 0x56, 0x84, 0xc1, 0x62, + 0x15, 0xb2, 0x77, 0x86, 0x81, 0xfc, 0xa5, 0x12, + 0x3c, 0xca, 0x28, 0x17, 0x8f, 0x03, 0x16, 0x6e, + 0xb8, 0x24, 0xfa, 0x1b, 0x15, 0x02, 0xfd, 0x8b, + 0xb6, 0x0a, 0x1a, 0xf7, 0x47, 0x41, 0xc5, 0x2b, + 0x37, 0x3e, 0xa1, 0xbf, 0x68, 0xda, 0x1c, 0x55, + 0x44, 0xc3, 0xee, 0xa1, 0x63, 0x07, 0x11, 0x3b, + 0x5f, 0x00, 0x84, 0xb4, 0xc4, 0xe4, 0xa7, 0x97, + 0x29, 0xf8, 0xce, 0xab, 0xfc, 0x27, 0x3e, 0x34, + 0xe4, 0xc7, 0x81, 0x52, 0x32, 0x0e, 0x27, 0x3c, + 0xa6, 0x70, 0x3f, 0x4a, 0x54, 0xda, 0xdd, 0x60, + 0x26, 0xb3, 0x6e, 0x45, 0x26, 0x19, 0x41, 0x6f + }; + + static const PRUint8 dh_known_Y_1[] = { + 0xb4, 0xc7, 0x85, 0xba, 0xa6, 0x98, 0xb3, 0x77, + 0x41, 0x2b, 0xd9, 0x9a, 0x72, 0x90, 0xa4, 0xac, + 0xc4, 0xf7, 0xc2, 0x23, 0x9a, 0x68, 0xe2, 0x7d, + 0x3a, 0x54, 0x45, 0x91, 0xc1, 0xd7, 0x8a, 0x17, + 0x54, 0xd3, 0x37, 0xaa, 0x0c, 0xcd, 0x0b, 0xe2, + 0xf2, 0x34, 0x0f, 0x17, 0xa8, 0x07, 0x88, 0xaf, + 0xed, 0xc1, 0x02, 0xd4, 0xdb, 0xdc, 0x0f, 0x22, + 0x51, 0x23, 0x40, 0xb9, 0x65, 0x6d, 0x39, 0xf4, + 0xe1, 0x8b, 0x57, 0x7d, 0xb6, 0xd3, 0xf2, 0x6b, + 0x02, 0xa9, 0x36, 0xf0, 0x0d, 0xe3, 0xdb, 0x9a, + 0xbf, 0x20, 0x00, 0x4d, 0xec, 0x6f, 0x68, 0x95, + 0xee, 0x59, 0x4e, 0x3c, 0xb6, 0xda, 0x7b, 0x19, + 0x08, 0x9a, 0xef, 0x61, 0x43, 0xf5, 0xfb, 0x25, + 0x70, 0x19, 0xc1, 0x5f, 0x0e, 0x0f, 0x6a, 0x63, + 0x44, 0xe9, 0xcf, 0x33, 0xce, 0x13, 0x4f, 0x34, + 0x3c, 0x94, 0x40, 0x8d, 0xf2, 0x65, 0x42, 0xef, + 0x70, 0x54, 0xdd, 0x5f, 0xc1, 0xd7, 0x0b, 0xa6, + 0x06, 0xd5, 0xa6, 0x47, 0xae, 0x2c, 0x1f, 0x5a, + 0xa6, 0xb3, 0xc1, 0x38, 0x3a, 0x3b, 0x60, 0x94, + 0xa2, 0x95, 0xab, 0xb2, 0x86, 0x82, 0xc5, 0x3b, + 0xb8, 0x6f, 0x3e, 0x55, 0x86, 0x84, 0xe0, 0x00, + 0xe5, 0xef, 0xca, 0x5c, 0xec, 0x7e, 0x38, 0x0f, + 0x82, 0xa2, 0xb1, 0xee, 0x48, 0x1b, 0x32, 0xbb, + 0x5a, 0x33, 0xa5, 0x01, 0xba, 0xca, 0xa6, 0x64, + 0x61, 0xb6, 0xe5, 0x5c, 0x0e, 0x5f, 0x2c, 0x66, + 0x0d, 0x01, 0x6a, 0x20, 0x04, 0x70, 0x68, 0x82, + 0x93, 0x29, 0x15, 0x3b, 0x7a, 0x06, 0xb2, 0x92, + 0x61, 0xcd, 0x7e, 0xa4, 0xc1, 0x15, 0x64, 0x3b, + 0x3c, 0x51, 0x10, 0x4c, 0x87, 0xa6, 0xaf, 0x07, + 0xce, 0x46, 0x82, 0x75, 0xf3, 0x90, 0xf3, 0x21, + 0x55, 0x74, 0xc2, 0xe4, 0x96, 0x7d, 0xc3, 0xe6, + 0x33, 0xa5, 0xc6, 0x51, 0xef, 0xec, 0x90, 0x08 + }; + + static const PRUint8 dh_known_x_2[] = { + 0x9e, 0x9b, 0xc3, 0x25, 0x53, 0xf9, 0xfc, 0x92, + 0xb6, 0xae, 0x54, 0x8e, 0x23, 0x4c, 0x94, 0xba, + 0x41, 0xe6, 0x29, 0x33, 0xb9, 0xdb, 0xff, 0x6d, + 0xa8, 0xb8, 0x48, 0x49, 0x66, 0x11, 0xa6, 0x13 + }; + + static const PRUint8 dh_known_hash_result[] = { + 0x93, 0xa2, 0x89, 0x1c, 0x8a, 0xc3, 0x70, 0xbf, + 0xa7, 0xdf, 0xb6, 0xd7, 0x82, 0xfb, 0x87, 0x81, + 0x09, 0x47, 0xf3, 0x9f, 0x5a, 0xbf, 0x4f, 0x3f, + 0x8e, 0x5e, 0x06, 0xca, 0x30, 0xa7, 0xaf, 0x10 + }; + + /* DH variables. */ + SECStatus dhStatus; + SECItem dh_prime; + SECItem dh_pub_key_1; + SECItem dh_priv_key_2; + SECItem ZZ = { 0, 0, 0 }; + PRUint8 computed_hash_result[HASH_LENGTH_MAX]; + + dh_prime.data = (PRUint8 *)dh_known_P; + dh_prime.len = sizeof(dh_known_P); + dh_pub_key_1.data = (PRUint8 *)dh_known_Y_1; + dh_pub_key_1.len = sizeof(dh_known_Y_1); + dh_priv_key_2.data = (PRUint8 *)dh_known_x_2; + dh_priv_key_2.len = sizeof(dh_known_x_2); + + /* execute the derive */ + dhStatus = DH_Derive(&dh_pub_key_1, &dh_prime, &dh_priv_key_2, &ZZ, dh_prime.len); + if (dhStatus != SECSuccess) { + goto loser; + } + + dhStatus = SHA256_HashBuf(computed_hash_result, ZZ.data, ZZ.len); + if (dhStatus != SECSuccess) { + goto loser; + } + + if (PORT_Memcmp(computed_hash_result, dh_known_hash_result, + sizeof(dh_known_hash_result)) != 0) { + dhStatus = SECFailure; + goto loser; + } + +loser: + if (ZZ.data) { + SECITEM_FreeItem(&ZZ, PR_FALSE); + } + + if (dhStatus != SECSuccess) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return (SECFailure); + } + return (SECSuccess); +} + static SECStatus freebl_fips_RNG_PowerUpSelfTest(void) { @@ -1541,7 +1843,7 @@ freebl_fipsPowerUpSelfTest(unsigned int tests) return rv; /* NOTE: RSA can only be tested in full freebl. It requires access to - * the locking primitives */ + * the locking primitives */ /* RSA Power-Up SelfTest(s). */ rv = freebl_fips_RSA_PowerUpSelfTest(); @@ -1554,8 +1856,14 @@ freebl_fipsPowerUpSelfTest(unsigned int tests) if (rv != SECSuccess) return rv; - /* ECDSA Power-Up SelfTest(s). */ - rv = freebl_fips_ECDSA_PowerUpSelfTest(); + /* DH Power-Up SelfTest(s). */ + rv = freebl_fips_DH_PowerUpSelfTest(); + + if (rv != SECSuccess) + return rv; + + /* EC Power-Up SelfTest(s). */ + rv = freebl_fips_EC_PowerUpSelfTest(); if (rv != SECSuccess) return rv; diff --git a/security/nss/lib/freebl/intel-gcm-wrap.c b/security/nss/lib/freebl/intel-gcm-wrap.c index 37a1af7652c0f..7bc07a6e98af1 100644 --- a/security/nss/lib/freebl/intel-gcm-wrap.c +++ b/security/nss/lib/freebl/intel-gcm-wrap.c @@ -143,6 +143,7 @@ intel_AES_GCM_CreateContext(void *context, void intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit) { + PORT_Memset(gcm, 0, sizeof(intel_AES_GCMContext)); if (freeit) { PORT_Free(gcm); } diff --git a/security/nss/lib/freebl/pqg.c b/security/nss/lib/freebl/pqg.c index 98fe20f0daf3e..28930e2e4850e 100644 --- a/security/nss/lib/freebl/pqg.c +++ b/security/nss/lib/freebl/pqg.c @@ -491,11 +491,11 @@ makeQ2fromSeed( ** This implments steps 4 thorough 22 of FIPS 186-3 A.1.2.1 and ** steps 16 through 34 of FIPS 186-2 C.6 */ -#define MAX_ST_SEED_BITS (HASH_LENGTH_MAX * PR_BITS_PER_BYTE) static SECStatus makePrimefromPrimesShaweTaylor( HASH_HashType hashtype, /* selected Hashing algorithm */ unsigned int length, /* input. Length of prime in bits. */ + unsigned int seedlen, /* input seed length in bits */ mp_int *c0, /* seed prime */ mp_int *q, /* sub prime, can be 1 */ mp_int *prime, /* output. */ @@ -557,7 +557,7 @@ makePrimefromPrimesShaweTaylor( old_counter = *prime_gen_counter; /* ** Comment: Generate a pseudorandom integer x in the interval - ** [2**(lenght-1), 2**length]. + ** [2**(length-1), 2**length]. ** ** Step 6/18 x = 0 */ @@ -569,11 +569,10 @@ makePrimefromPrimesShaweTaylor( for (i = 0; i < iterations; i++) { /* is bigger than prime_seed should get to */ CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i, - MAX_ST_SEED_BITS, &x[(iterations - i - 1) * hashlen])); + seedlen, &x[(iterations - i - 1) * hashlen])); } /* Step 8/20 prime_seed = prime_seed + iterations + 1 */ - CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS, - prime_seed)); + CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed)); /* ** Step 9/21 x = 2 ** (length-1) + x mod 2 ** (length-1) ** @@ -595,7 +594,7 @@ makePrimefromPrimesShaweTaylor( x[offset] = (mask & x[offset]) | bit; /* ** Comment: Generate a candidate prime c in the interval - ** [2**(lenght-1), 2**length]. + ** [2**(length-1), 2**length]. ** ** Step 10 t = ceiling(x/(2q(p0))) ** Step 22 t = ceiling(x/(2(c0))) @@ -624,7 +623,7 @@ makePrimefromPrimesShaweTaylor( /* t = 2**(length-1) + 2qc0 -1 */ CHECK_MPI_OK(mp_add(&two_length_minus_1, &t, &t)); /* t = floor((2**(length-1)+2qc0 -1)/2qco) - * = ceil(2**(lenght-2)/2qc0) */ + * = ceil(2**(length-2)/2qc0) */ CHECK_MPI_OK(mp_div(&t, &c0_2, &t, NULL)); CHECK_MPI_OK(mp_mul(&t, &c0_2, &c)); CHECK_MPI_OK(mp_add_d(&c, (mp_digit)1, &c)); /* c= 2tqc0 + 1*/ @@ -645,13 +644,11 @@ makePrimefromPrimesShaweTaylor( ** NOTE: we reuse the x array for 'a' initially. */ for (i = 0; i < iterations; i++) { - /* MAX_ST_SEED_BITS is bigger than prime_seed should get to */ CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i, - MAX_ST_SEED_BITS, &x[(iterations - i - 1) * hashlen])); + seedlen, &x[(iterations - i - 1) * hashlen])); } /* Step 16/28 prime_seed = prime_seed + iterations + 1 */ - CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS, - prime_seed)); + CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed)); /* Step 17/29 a = 2 + (a mod (c-3)). */ CHECK_MPI_OK(mp_read_unsigned_octets(&a, x, iterations * hashlen)); CHECK_MPI_OK(mp_sub_d(&c, (mp_digit)3, &z)); /* z = c -3 */ @@ -742,6 +739,7 @@ makePrimefromSeedShaweTaylor( int hashlen = HASH_ResultLen(hashtype); int outlen = hashlen * PR_BITS_PER_BYTE; int offset; + int seedlen = input_seed->len * 8; /*seedlen is in bits */ unsigned char bit, mask; unsigned char x[HASH_LENGTH_MAX * 2]; mp_digit dummy; @@ -775,7 +773,7 @@ makePrimefromSeedShaweTaylor( goto cleanup; } /* Steps 16-34 */ - rv = makePrimefromPrimesShaweTaylor(hashtype, length, &c0, &one, + rv = makePrimefromPrimesShaweTaylor(hashtype, length, seedlen, &c0, &one, prime, prime_seed, prime_gen_counter); goto cleanup; /* we're done, one way or the other */ } @@ -787,8 +785,7 @@ makePrimefromSeedShaweTaylor( step_5: /* Step 5 c = Hash(prime_seed) xor Hash(prime_seed+1). */ CHECK_SEC_OK(HASH_HashBuf(hashtype, x, prime_seed->data, prime_seed->len)); - CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1, - MAX_ST_SEED_BITS, &x[hashlen])); + CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1, seedlen, &x[hashlen])); for (i = 0; i < hashlen; i++) { x[i] = x[i] ^ x[i + hashlen]; } @@ -817,7 +814,7 @@ makePrimefromSeedShaweTaylor( /* Step 8 prime_gen_counter = prime_gen_counter + 1 */ (*prime_gen_counter)++; /* Step 9 prime_seed = prime_seed + 2 */ - CHECK_SEC_OK(addToSeed(prime_seed, 2, MAX_ST_SEED_BITS, prime_seed)); + CHECK_SEC_OK(addToSeed(prime_seed, 2, seedlen, prime_seed)); /* Step 10 Perform deterministic primality test on c. For example, since ** c is small, it's primality can be tested by trial division, See ** See Appendic C.7. @@ -890,7 +887,8 @@ findQfromSeed( mp_int *Q_, /* output. */ unsigned int *qseed_len, /* output */ HASH_HashType *hashtypePtr, /* output. Hash uses */ - pqgGenType *typePtr) /* output. Generation Type used */ + pqgGenType *typePtr, /* output. Generation Type used */ + unsigned int *qgen_counter) /* output. q_counter */ { HASH_HashType hashtype; SECItem firstseed = { 0, 0, 0 }; @@ -964,6 +962,7 @@ findQfromSeed( *qseed_len = qseed.len; *hashtypePtr = hashtype; *typePtr = FIPS186_3_ST_TYPE; + *qgen_counter = count; SECITEM_FreeItem(&qseed, PR_FALSE); return SECSuccess; } @@ -1390,19 +1389,26 @@ pqg_ParamGen(unsigned int L, unsigned int N, pqgGenType type, CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1, &qseed, &p0, &pseed, &pgen_counter)); /* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */ - CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, + CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, seedBytes * 8, &p0, &Q, &P, &pseed, &pgen_counter)); /* combine all the seeds */ - seed->len = firstseed.len + qseed.len + pseed.len; + if ((qseed.len > firstseed.len) || (pseed.len > firstseed.len)) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); /* shouldn't happen */ + goto cleanup; + } + /* If the seed overflows, then pseed and qseed may have leading zeros which the mpl code clamps. + * we want to make sure those are added back in so the individual seed lengths are predictable from + * the overall seed length */ + seed->len = firstseed.len * 3; seed->data = PORT_ArenaZAlloc(verify->arena, seed->len); if (seed->data == NULL) { goto cleanup; } PORT_Memcpy(seed->data, firstseed.data, firstseed.len); - PORT_Memcpy(seed->data + firstseed.len, pseed.data, pseed.len); - PORT_Memcpy(seed->data + firstseed.len + pseed.len, qseed.data, qseed.len); - counter = 0; /* (qgen_counter << 16) | pgen_counter; */ + PORT_Memcpy(seed->data + 2 * firstseed.len - pseed.len, pseed.data, pseed.len); + PORT_Memcpy(seed->data + 3 * firstseed.len - qseed.len, qseed.data, qseed.len); + counter = (qgen_counter << 16) | pgen_counter; /* we've generated both P and Q now, skip to generating G */ goto generate_G; @@ -1622,6 +1628,7 @@ PQG_VerifyParams(const PQGParams *params, int j; unsigned int counter_max = 0; /* handle legacy L < 1024 */ unsigned int qseed_len; + unsigned int qgen_counter_ = 0; SECItem pseed_ = { 0, 0, 0 }; HASH_HashType hashtype; pqgGenType type; @@ -1701,48 +1708,55 @@ PQG_VerifyParams(const PQGParams *params, /* Steps 7-12 are done only if the optional PQGVerify is supplied. */ /* continue processing P */ /* 7. counter < 4*L */ - CHECKPARAM((vfy->counter == -1) || (vfy->counter < counter_max)); /* 8. g >= N and g < 2*L (g is length of seed in bits) */ - g = vfy->seed.len * 8; - CHECKPARAM(g >= N && g < counter_max / 2); + /* step 7 and 8 are delayed until we determine which type of generation + * was used */ /* 9. Q generated from SEED matches Q in PQGParams. */ /* This function checks all possible hash and generation types to * find a Q_ which matches Q. */ + g = vfy->seed.len * 8; CHECKPARAM(findQfromSeed(L, N, g, &vfy->seed, &Q, &Q_, &qseed_len, - &hashtype, &type) == SECSuccess); + &hashtype, &type, &qgen_counter_) == SECSuccess); CHECKPARAM(mp_cmp(&Q, &Q_) == 0); + /* now we can do steps 7 & 8*/ + if ((type == FIPS186_1_TYPE) || (type == FIPS186_3_TYPE)) { + CHECKPARAM((vfy->counter == -1) || (vfy->counter < counter_max)); + CHECKPARAM(g >= N && g < counter_max / 2); + } if (type == FIPS186_3_ST_TYPE) { SECItem qseed = { 0, 0, 0 }; SECItem pseed = { 0, 0, 0 }; unsigned int first_seed_len; - unsigned int pgen_counter = 0; + unsigned int pgen_counter_ = 0; + unsigned int qgen_counter = (vfy->counter >> 16) & 0xffff; + unsigned int pgen_counter = (vfy->counter) & 0xffff; /* extract pseed and qseed from domain_parameter_seed, which is * first_seed || pseed || qseed. qseed is first_seed + small_integer - * pseed is qseed + small_integer. This means most of the time + * mod the length of first_seed. pseed is qseed + small_integer mod + * the length of first_seed. This means most of the time * first_seed.len == qseed.len == pseed.len. Rarely qseed.len and/or - * pseed.len will be one greater than first_seed.len, so we can - * depend on the fact that - * first_seed.len = floor(domain_parameter_seed.len/3). - * findQfromSeed returned qseed.len, so we can calculate pseed.len as - * pseed.len = domain_parameter_seed.len - first_seed.len - qseed.len - * this is probably over kill, since 99.999% of the time they will all - * be equal. - * - * With the lengths, we can now find the offsets; + * pseed.len will be smaller because mpi clamps them. pqgGen + * automatically adds the zero pad back though, so we can depend + * domain_parameter_seed.len to be a multiple of three. We only have + * to deal with the fact that the returned seeds from our functions + * could be shorter. + * first_seed.len = domain_parameter_seed.len/3 + * We can now find the offsets; * first_seed.data = domain_parameter_seed.data + 0 * pseed.data = domain_parameter_seed.data + first_seed.len * qseed.data = domain_parameter_seed.data * + domain_paramter_seed.len - qseed.len - * + * We deal with pseed possibly having zero pad in the pseed check later. */ first_seed_len = vfy->seed.len / 3; CHECKPARAM(qseed_len < vfy->seed.len); CHECKPARAM(first_seed_len * 8 > N - 1); - CHECKPARAM(first_seed_len + qseed_len < vfy->seed.len); + CHECKPARAM(first_seed_len * 8 < counter_max / 2); + CHECKPARAM(first_seed_len >= qseed_len); qseed.len = qseed_len; qseed.data = vfy->seed.data + vfy->seed.len - qseed.len; - pseed.len = vfy->seed.len - (first_seed_len + qseed_len); + pseed.len = first_seed_len; pseed.data = vfy->seed.data + first_seed_len; /* @@ -1754,14 +1768,34 @@ PQG_VerifyParams(const PQGParams *params, ** (ST_Random_Prime((ceil(length/2)+1, input_seed) */ CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1, - &qseed, &p0, &pseed_, &pgen_counter)); + &qseed, &p0, &pseed_, &pgen_counter_)); /* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */ - CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, - &p0, &Q_, &P_, &pseed_, &pgen_counter)); + CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, first_seed_len * 8, + &p0, &Q_, &P_, &pseed_, &pgen_counter_)); CHECKPARAM(mp_cmp(&P, &P_) == 0); /* make sure pseed wasn't tampered with (since it is part of * calculating G) */ + if (pseed.len > pseed_.len) { + /* handle the case of zero pad for pseed */ + int extra = pseed.len - pseed_.len; + int i; + for (i = 0; i < extra; i++) { + if (pseed.data[i] != 0) { + *result = SECFailure; + goto cleanup; + } + } + pseed.data += extra; + pseed.len -= extra; + /* the rest is handled in the normal compare below */ + } CHECKPARAM(SECITEM_CompareItem(&pseed, &pseed_) == SECEqual); + if (vfy->counter != -1) { + CHECKPARAM(pgen_counter < counter_max); + CHECKPARAM(qgen_counter < counter_max); + CHECKPARAM((pgen_counter_ == pgen_counter)); + CHECKPARAM((qgen_counter_ == qgen_counter)); + } } else if (vfy->counter == -1) { /* If counter is set to -1, we are really only verifying G, skip * the remainder of the checks for P */ diff --git a/security/nss/lib/freebl/rijndael.c b/security/nss/lib/freebl/rijndael.c index 5de27de9ce72a..6dab440f8ba94 100644 --- a/security/nss/lib/freebl/rijndael.c +++ b/security/nss/lib/freebl/rijndael.c @@ -1032,13 +1032,19 @@ AES_CreateContext(const unsigned char *key, const unsigned char *iv, void AES_DestroyContext(AESContext *cx, PRBool freeit) { + void *mem = cx->mem; if (cx->worker_cx && cx->destroy) { (*cx->destroy)(cx->worker_cx, PR_TRUE); cx->worker_cx = NULL; cx->destroy = NULL; } + PORT_Memset(cx, 0, sizeof(AESContext)); if (freeit) { - PORT_Free(cx->mem); + PORT_Free(mem); + } else { + /* if we are not freeing the context, restore mem, We may get called + * again to actually free the context */ + cx->mem = mem; } } diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def index 53d463a66ffd4..17c69a7797727 100644 --- a/security/nss/lib/nss/nss.def +++ b/security/nss/lib/nss/nss.def @@ -1151,3 +1151,9 @@ CERT_GetCertificateDer; ;+ local: ;+ *; ;+}; +;+NSS_3.45 { # NSS 3.45 release +;+ global: +PK11_FindRawCertsWithSubject; +;+ local: +;+ *; +;+}; diff --git a/security/nss/lib/pk11wrap/pk11obj.c b/security/nss/lib/pk11wrap/pk11obj.c index 468f94ebccfdb..16ff15a809caa 100644 --- a/security/nss/lib/pk11wrap/pk11obj.c +++ b/security/nss/lib/pk11wrap/pk11obj.c @@ -4,6 +4,8 @@ /* * This file manages object type indepentent functions. */ +#include + #include "seccomon.h" #include "secmod.h" #include "secmodi.h" @@ -1883,6 +1885,96 @@ pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate, *object_count = -1; return objID; } + +SECStatus +PK11_FindRawCertsWithSubject(PK11SlotInfo *slot, SECItem *derSubject, + CERTCertificateList **results) +{ + if (!slot || !derSubject || !results) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + *results = NULL; + + // derSubject->data may be null. If so, derSubject->len must be 0. + if (!derSubject->data && derSubject->len != 0) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + CK_CERTIFICATE_TYPE ckc_x_509 = CKC_X_509; + CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE; + CK_ATTRIBUTE subjectTemplate[] = { + { CKA_CERTIFICATE_TYPE, &ckc_x_509, sizeof(ckc_x_509) }, + { CKA_CLASS, &cko_certificate, sizeof(cko_certificate) }, + { CKA_SUBJECT, derSubject->data, derSubject->len }, + }; + int templateCount = sizeof(subjectTemplate) / sizeof(subjectTemplate[0]); + int handleCount = 0; + CK_OBJECT_HANDLE *handles = + pk11_FindObjectsByTemplate(slot, subjectTemplate, templateCount, + &handleCount); + if (!handles) { + // pk11_FindObjectsByTemplate indicates there was an error by setting + // handleCount to -1 (and it has set an error with PORT_SetError). + if (handleCount == -1) { + return SECFailure; + } + return SECSuccess; + } + PORT_Assert(handleCount > 0); + if (handleCount <= 0) { + PORT_Free(handles); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + if (handleCount > INT_MAX / sizeof(SECItem)) { + PORT_Free(handles); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!arena) { + PORT_Free(handles); + return SECFailure; + } + CERTCertificateList *rawCertificates = + PORT_ArenaNew(arena, CERTCertificateList); + if (!rawCertificates) { + PORT_Free(handles); + PORT_FreeArena(arena, PR_FALSE); + return SECFailure; + } + rawCertificates->arena = arena; + rawCertificates->certs = PORT_ArenaNewArray(arena, SECItem, handleCount); + if (!rawCertificates->certs) { + PORT_Free(handles); + PORT_FreeArena(arena, PR_FALSE); + return SECFailure; + } + rawCertificates->len = handleCount; + int handleIndex; + for (handleIndex = 0; handleIndex < handleCount; handleIndex++) { + SECStatus rv = + PK11_ReadAttribute(slot, handles[handleIndex], CKA_VALUE, arena, + &rawCertificates->certs[handleIndex]); + if (rv != SECSuccess) { + PORT_Free(handles); + PORT_FreeArena(arena, PR_FALSE); + return SECFailure; + } + if (!rawCertificates->certs[handleIndex].data) { + PORT_Free(handles); + PORT_FreeArena(arena, PR_FALSE); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + } + PORT_Free(handles); + *results = rawCertificates; + return SECSuccess; +} + /* * given a PKCS #11 object, match it's peer based on the KeyID. searchID * is typically a privateKey or a certificate while the peer is the opposite diff --git a/security/nss/lib/pk11wrap/pk11pub.h b/security/nss/lib/pk11wrap/pk11pub.h index 8db969e4cfde8..9ca4018d94530 100644 --- a/security/nss/lib/pk11wrap/pk11pub.h +++ b/security/nss/lib/pk11wrap/pk11pub.h @@ -875,6 +875,17 @@ SECStatus PK11_WriteRawAttribute(PK11ObjectType type, void *object, PK11SlotList * PK11_GetAllSlotsForCert(CERTCertificate *cert, void *arg); +/* + * Finds all certificates on the given slot with the given subject distinguished + * name and returns them as DER bytes. If no such certificates can be found, + * returns SECSuccess and sets *results to NULL. If a failure is encountered + * while fetching any of the matching certificates, SECFailure is returned and + * *results will be NULL. + */ +SECStatus +PK11_FindRawCertsWithSubject(PK11SlotInfo *slot, SECItem *derSubject, + CERTCertificateList **results); + /********************************************************************** * New functions which are already deprecated.... **********************************************************************/ diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c index 5830a8857325f..8b3c68d444bca 100644 --- a/security/nss/lib/softoken/pkcs11c.c +++ b/security/nss/lib/softoken/pkcs11c.c @@ -4727,6 +4727,13 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, return crv; } + /* detect trivial signing transforms */ + if ((signature_length >= pairwise_digest_length) && + (PORT_Memcmp(known_digest, signature + (signature_length - pairwise_digest_length), pairwise_digest_length) == 0)) { + PORT_Free(signature); + return CKR_DEVICE_ERROR; + } + /* Verify the known hash using the public key. */ crv = NSC_VerifyInit(hSession, &mech, publicKey->handle); if (crv != CKR_OK) { @@ -7562,14 +7569,14 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession, case CKM_DH_PKCS_DERIVE: { SECItem derived, dhPublic; - SECItem dhPrime, dhValue; + SECItem dhPrime, dhSubPrime, dhValue; /* sourceKey - values for the local existing low key */ /* get prime and value attributes */ crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME); - if (crv != SECSuccess) + if (crv != CKR_OK) break; crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE); - if (crv != SECSuccess) { + if (crv != CKR_OK) { PORT_Free(dhPrime.data); break; } @@ -7577,6 +7584,20 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession, dhPublic.data = pMechanism->pParameter; dhPublic.len = pMechanism->ulParameterLen; + /* If the caller bothered to provide Q, use Q to validate + * the public key. */ + crv = sftk_Attribute2SecItem(NULL, &dhSubPrime, sourceKey, CKA_SUBPRIME); + if (crv == CKR_OK) { + rv = KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime); + PORT_Free(dhSubPrime.data); + if (rv != SECSuccess) { + crv = CKR_ARGUMENTS_BAD; + PORT_Free(dhPrime.data); + PORT_Free(dhValue.data); + break; + } + } + /* calculate private value - oct */ rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize); @@ -7586,6 +7607,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession, if (rv == SECSuccess) { sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len); PORT_ZFree(derived.data, derived.len); + crv = CKR_OK; } else crv = CKR_HOST_MEMORY; diff --git a/testing/web-platform/manifestupdate.py b/testing/web-platform/manifestupdate.py index 389b776aa2aed..1a362505800a6 100644 --- a/testing/web-platform/manifestupdate.py +++ b/testing/web-platform/manifestupdate.py @@ -118,8 +118,7 @@ def run(src_root, obj_root, logger=None, **kwargs): manifests = load_and_update(logger, src_wpt_dir, test_paths, update=update, rebuild=kwargs["rebuild"], - cache_root=kwargs["cache_root"], - meta_filters=kwargs.get("meta_filters")) + cache_root=kwargs["cache_root"]) return manifests @@ -176,7 +175,7 @@ def generate_config(logger, repo_root, wpt_dir, dest_path, force_rewrite=False): def load_and_update(logger, wpt_dir, test_paths, rebuild=False, config_dir=None, cache_root=None, - meta_filters=None, update=True): + update=True): rv = {} wptdir_hash = hashlib.sha256(os.path.abspath(wpt_dir)).hexdigest() for url_base, paths in test_paths.iteritems(): @@ -188,8 +187,7 @@ def load_and_update(logger, wpt_dir, test_paths, rebuild=False, config_dir=None, update=update, rebuild=rebuild, working_copy=True, - cache_root=this_cache_root, - meta_filters=meta_filters) + cache_root=this_cache_root) path_data = {"url_base": url_base} path_data.update(paths) rv[m] = path_data diff --git a/testing/web-platform/meta/2dcontext/imagebitmap/createImageBitmap-flipY.html.ini b/testing/web-platform/meta/2dcontext/imagebitmap/createImageBitmap-flipY.html.ini new file mode 100644 index 0000000000000..f9332a11de9c5 --- /dev/null +++ b/testing/web-platform/meta/2dcontext/imagebitmap/createImageBitmap-flipY.html.ini @@ -0,0 +1,67 @@ +[createImageBitmap-flipY.html] + [createImageBitmap from a vector SVGImageElement imageOrientation: "none", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from a vector SVGImageElement imageOrientation: "flipY", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from an HTMLCanvasElement imageOrientation: "none", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from an ImageData imageOrientation: "none", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from an HTMLVideoElement from a data URL imageOrientation: "flipY", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from an OffscreenCanvas imageOrientation: "flipY", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from a vector HTMLImageElement imageOrientation: "flipY", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from an HTMLVideoElement imageOrientation: "flipY", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from a Blob imageOrientation: "flipY", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from an HTMLCanvasElement imageOrientation: "flipY", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from an HTMLVideoElement imageOrientation: "none", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from an ImageData imageOrientation: "flipY", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from a bitmap HTMLImageElement imageOrientation: "flipY", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from an OffscreenCanvas imageOrientation: "none", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from an ImageBitmap imageOrientation: "flipY", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from a vector HTMLImageElement imageOrientation: "none", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from a Blob imageOrientation: "none", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from an HTMLVideoElement from a data URL imageOrientation: "none", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from an ImageBitmap imageOrientation: "none", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from a bitmap HTMLImageElement imageOrientation: "none", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from a bitmap SVGImageElement imageOrientation: "flipY", and drawImage on the created ImageBitmap] + expected: FAIL + + [createImageBitmap from a bitmap SVGImageElement imageOrientation: "none", and drawImage on the created ImageBitmap] + expected: FAIL + diff --git a/testing/web-platform/meta/FileAPI/blob/Blob-array-buffer.any.js.ini b/testing/web-platform/meta/FileAPI/blob/Blob-array-buffer.any.js.ini new file mode 100644 index 0000000000000..957045c5fc844 --- /dev/null +++ b/testing/web-platform/meta/FileAPI/blob/Blob-array-buffer.any.js.ini @@ -0,0 +1,33 @@ +[Blob-array-buffer.any.html] + [Blob.arrayBuffer() non-ascii input] + expected: FAIL + + [Blob.arrayBuffer()] + expected: FAIL + + [Blob.arrayBuffer() non-unicode input] + expected: FAIL + + [Blob.arrayBuffer() empty Blob data] + expected: FAIL + + [Blob.arrayBuffer() concurrent reads] + expected: FAIL + + +[Blob-array-buffer.any.worker.html] + [Blob.arrayBuffer() non-ascii input] + expected: FAIL + + [Blob.arrayBuffer()] + expected: FAIL + + [Blob.arrayBuffer() non-unicode input] + expected: FAIL + + [Blob.arrayBuffer() empty Blob data] + expected: FAIL + + [Blob.arrayBuffer() concurrent reads] + expected: FAIL + diff --git a/testing/web-platform/meta/FileAPI/blob/Blob-stream.any.js.ini b/testing/web-platform/meta/FileAPI/blob/Blob-stream.any.js.ini new file mode 100644 index 0000000000000..facf4573cb341 --- /dev/null +++ b/testing/web-platform/meta/FileAPI/blob/Blob-stream.any.js.ini @@ -0,0 +1,27 @@ +[Blob-stream.any.worker.html] + [Blob.stream() empty Blob] + expected: FAIL + + [Blob.stream()] + expected: FAIL + + [Blob.stream() non-unicode input] + expected: FAIL + + [Blob.stream() garbage collection of blob shouldn't break streamconsumption] + expected: FAIL + + +[Blob-stream.any.html] + [Blob.stream() empty Blob] + expected: FAIL + + [Blob.stream()] + expected: FAIL + + [Blob.stream() non-unicode input] + expected: FAIL + + [Blob.stream() garbage collection of blob shouldn't break streamconsumption] + expected: FAIL + diff --git a/testing/web-platform/meta/FileAPI/blob/Blob-text.any.js.ini b/testing/web-platform/meta/FileAPI/blob/Blob-text.any.js.ini new file mode 100644 index 0000000000000..648c5ea67b188 --- /dev/null +++ b/testing/web-platform/meta/FileAPI/blob/Blob-text.any.js.ini @@ -0,0 +1,51 @@ +[Blob-text.any.html] + [Blob.text() different charset param in type option] + expected: FAIL + + [Blob.text() different charset param with non-ascii input] + expected: FAIL + + [Blob.text() concurrent reads] + expected: FAIL + + [Blob.text() multi-element array in constructor] + expected: FAIL + + [Blob.text() invalid utf-8 input] + expected: FAIL + + [Blob.text() non-unicode] + expected: FAIL + + [Blob.text()] + expected: FAIL + + [Blob.text() empty blob data] + expected: FAIL + + +[Blob-text.any.worker.html] + [Blob.text() different charset param in type option] + expected: FAIL + + [Blob.text() different charset param with non-ascii input] + expected: FAIL + + [Blob.text() concurrent reads] + expected: FAIL + + [Blob.text() multi-element array in constructor] + expected: FAIL + + [Blob.text() invalid utf-8 input] + expected: FAIL + + [Blob.text() non-unicode] + expected: FAIL + + [Blob.text()] + expected: FAIL + + [Blob.text() empty blob data] + expected: FAIL + diff --git a/testing/web-platform/meta/FileAPI/idlharness.html.ini b/testing/web-platform/meta/FileAPI/idlharness.html.ini new file mode 100644 index 0000000000000..836c5f090dff9 --- /dev/null +++ b/testing/web-platform/meta/FileAPI/idlharness.html.ini @@ -0,0 +1,28 @@ +[idlharness.html] + [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "text()" with the proper type] + expected: FAIL + + [Blob interface: operation stream()] + expected: FAIL + + [Blob interface: new Blob(["TEST"\]) must inherit property "arrayBuffer()" with the proper type] + expected: FAIL + + [Blob interface: operation text()] + expected: FAIL + + [Blob interface: new Blob(["TEST"\]) must inherit property "text()" with the proper type] + expected: FAIL + + [Blob interface: new Blob(["TEST"\]) must inherit property "stream()" with the proper type] + expected: FAIL + + [Blob interface: operation arrayBuffer()] + expected: FAIL + + [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "stream()" with the proper type] + expected: FAIL + + [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "arrayBuffer()" with the proper type] + expected: FAIL + diff --git a/testing/web-platform/meta/FileAPI/idlharness.worker.js.ini b/testing/web-platform/meta/FileAPI/idlharness.worker.js.ini new file mode 100644 index 0000000000000..f966393ffe385 --- /dev/null +++ b/testing/web-platform/meta/FileAPI/idlharness.worker.js.ini @@ -0,0 +1,28 @@ +[idlharness.worker.html] + [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "text()" with the proper type] + expected: FAIL + + [Blob interface: operation stream()] + expected: FAIL + + [Blob interface: new Blob(["TEST"\]) must inherit property "arrayBuffer()" with the proper type] + expected: FAIL + + [Blob interface: operation text()] + expected: FAIL + + [Blob interface: new Blob(["TEST"\]) must inherit property "text()" with the proper type] + expected: FAIL + + [Blob interface: new Blob(["TEST"\]) must inherit property "stream()" with the proper type] + expected: FAIL + + [Blob interface: operation arrayBuffer()] + expected: FAIL + + [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "stream()" with the proper type] + expected: FAIL + + [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "arrayBuffer()" with the proper type] + expected: FAIL + diff --git a/testing/web-platform/meta/FileAPI/reading-data-section/filereader_events.any.js.ini b/testing/web-platform/meta/FileAPI/reading-data-section/filereader_events.any.js.ini new file mode 100644 index 0000000000000..fe19471261dc3 --- /dev/null +++ b/testing/web-platform/meta/FileAPI/reading-data-section/filereader_events.any.js.ini @@ -0,0 +1,15 @@ +[filereader_events.any.html] + [events are dispatched in the correct order for a non-empty blob] + expected: FAIL + + [events are dispatched in the correct order for an empty blob] + expected: FAIL + + +[filereader_events.any.worker.html] + [events are dispatched in the correct order for a non-empty blob] + expected: FAIL + + [events are dispatched in the correct order for an empty blob] + expected: FAIL + diff --git a/testing/web-platform/meta/FileAPI/reading-data-section/filereader_result.html.ini b/testing/web-platform/meta/FileAPI/reading-data-section/filereader_result.html.ini new file mode 100644 index 0000000000000..cda42af42c0f1 --- /dev/null +++ b/testing/web-platform/meta/FileAPI/reading-data-section/filereader_result.html.ini @@ -0,0 +1,16 @@ +[filereader_result.html] + [result is null during "loadstart" event for readAsBinaryString] + expected: FAIL + + [result is null during "loadstart" event for readAsDataURL] + expected: FAIL + + [result is null during "progress" event for readAsBinaryString] + expected: FAIL + + [result is null during "loadstart" event for readAsArrayBuffer] + expected: FAIL + + [result is null during "loadstart" event for readAsText] + expected: FAIL + diff --git a/testing/web-platform/meta/animation-worklet/animator-animate.https.html.ini b/testing/web-platform/meta/animation-worklet/animator-animate.https.html.ini deleted file mode 100644 index 930e2c63e4649..0000000000000 --- a/testing/web-platform/meta/animation-worklet/animator-animate.https.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[animator-animate.https.html] - [Simple worklet animation should output values at specified local time] - expected: FAIL - diff --git a/testing/web-platform/meta/animation-worklet/idlharness.any.js.ini b/testing/web-platform/meta/animation-worklet/idlharness.any.js.ini index 305369aa88e9e..4d84d5aeb74dc 100644 --- a/testing/web-platform/meta/animation-worklet/idlharness.any.js.ini +++ b/testing/web-platform/meta/animation-worklet/idlharness.any.js.ini @@ -44,9 +44,6 @@ [WorkletGroupEffect interface: operation getChildren()] expected: FAIL - [WorkletGroupEffect interface: existence and properties of interface object] - expected: FAIL - [WorkletAnimation interface object name] expected: FAIL diff --git a/testing/web-platform/meta/animation-worklet/stateful-animator.https.html.ini b/testing/web-platform/meta/animation-worklet/stateful-animator.https.html.ini new file mode 100644 index 0000000000000..8f1e867ba71b8 --- /dev/null +++ b/testing/web-platform/meta/animation-worklet/stateful-animator.https.html.ini @@ -0,0 +1,19 @@ +[stateful-animator.https.html] + [Stateful Animator instance gets dropped (does not get migrated) if state function is not serializable.] + expected: FAIL + + [Stateful animator gets recreated with 'undefined' state if state function returns undefined.] + expected: FAIL + + [Stateless animator gets reecreated with 'undefined' state.] + expected: FAIL + + [Stateless animator should not copy the effect object.] + expected: FAIL + + [Stateless animator should preserve the local time of its effect.] + expected: FAIL + + [Stateful animator can use its state to update the animation. Pass if test does not timeout] + expected: FAIL + diff --git a/testing/web-platform/meta/animation-worklet/worklet-animation-creation.https.html.ini b/testing/web-platform/meta/animation-worklet/worklet-animation-creation.https.html.ini index 13c172e9835c2..ecfaf6942713e 100644 --- a/testing/web-platform/meta/animation-worklet/worklet-animation-creation.https.html.ini +++ b/testing/web-platform/meta/animation-worklet/worklet-animation-creation.https.html.ini @@ -23,3 +23,9 @@ [ScrollTimeline is a valid timeline for a WorkletAnimation] expected: FAIL + [WorkletAnimation creation should choose the correct timeline based on the current global object] + expected: FAIL + + [Creating animation with effects from different documents is allowed] + expected: FAIL + diff --git a/testing/web-platform/meta/animation-worklet/worklet-animation-play.https.html.ini b/testing/web-platform/meta/animation-worklet/worklet-animation-play.https.html.ini new file mode 100644 index 0000000000000..0061d6b6a78d9 --- /dev/null +++ b/testing/web-platform/meta/animation-worklet/worklet-animation-play.https.html.ini @@ -0,0 +1,7 @@ +[worklet-animation-play.https.html] + [A running worklet animation should output values at specified local time.] + expected: FAIL + + [Playing a running animation should be a no-op.] + expected: FAIL + diff --git a/testing/web-platform/meta/animation-worklet/worklet-animation-with-effects-from-different-frames.https.html.ini b/testing/web-platform/meta/animation-worklet/worklet-animation-with-effects-from-different-frames.https.html.ini new file mode 100644 index 0000000000000..e5281909f0fbf --- /dev/null +++ b/testing/web-platform/meta/animation-worklet/worklet-animation-with-effects-from-different-frames.https.html.ini @@ -0,0 +1,4 @@ +[worklet-animation-with-effects-from-different-frames.https.html] + [Effects from different documents can be animated within one worklet animation] + expected: FAIL + diff --git a/testing/web-platform/meta/animation-worklet/worklet-animation-without-target.https.html.ini b/testing/web-platform/meta/animation-worklet/worklet-animation-without-target.https.html.ini new file mode 100644 index 0000000000000..aa7ceb9e6f60b --- /dev/null +++ b/testing/web-platform/meta/animation-worklet/worklet-animation-without-target.https.html.ini @@ -0,0 +1,4 @@ +[worklet-animation-without-target.https.html] + [Verify that effect without target is supported] + expected: FAIL + diff --git a/testing/web-platform/meta/bluetooth/idl/idlharness.tentative.https.window.js.ini b/testing/web-platform/meta/bluetooth/idl/idlharness.tentative.https.window.js.ini index 572085316b5ce..f763a1f957357 100644 --- a/testing/web-platform/meta/bluetooth/idl/idlharness.tentative.https.window.js.ini +++ b/testing/web-platform/meta/bluetooth/idl/idlharness.tentative.https.window.js.ini @@ -542,3 +542,9 @@ [BluetoothDevice interface: attribute onadvertisementreceived] expected: FAIL + [BluetoothRemoteGATTCharacteristic interface: operation writeValueWithoutResponse(BufferSource)] + expected: FAIL + + [BluetoothRemoteGATTCharacteristic interface: operation writeValueWithResponse(BufferSource)] + expected: FAIL + diff --git a/testing/web-platform/meta/clipboard-apis/async-navigator-clipboard-basics.https.html.ini b/testing/web-platform/meta/clipboard-apis/async-navigator-clipboard-basics.https.html.ini index 959b4eca00784..7f603daabee10 100644 --- a/testing/web-platform/meta/clipboard-apis/async-navigator-clipboard-basics.https.html.ini +++ b/testing/web-platform/meta/clipboard-apis/async-navigator-clipboard-basics.https.html.ini @@ -29,3 +29,9 @@ [navigator.clipboard.write([image/png Blob\]) succeeds] expected: FAIL + [navigator.clipboard.write([text/plain ClipboardItem\]) succeeds] + expected: FAIL + + [navigator.clipboard.read() succeeds] + expected: FAIL + diff --git a/testing/web-platform/meta/clipboard-apis/clipboard-item.https.html.ini b/testing/web-platform/meta/clipboard-apis/clipboard-item.https.html.ini new file mode 100644 index 0000000000000..eb7e654a64694 --- /dev/null +++ b/testing/web-platform/meta/clipboard-apis/clipboard-item.https.html.ini @@ -0,0 +1,31 @@ +[clipboard-item.https.html] + [ClipboardItem({}) fails with empty dictionary input] + expected: FAIL + + [ClipboardItem(Blob) fails] + expected: FAIL + + [getType(DOMString valid type) succeeds with correct output] + expected: FAIL + + [ClipboardItem() fails with no input] + expected: FAIL + + [ClipboardItem() fails with null input] + expected: FAIL + + [getType(DOMString type) rejects correctly when querying for missing type] + expected: FAIL + + [ClipboardItem() succeeds with empty options] + expected: FAIL + + [ClipboardItem({string, Blob}) succeeds with different types] + expected: FAIL + + [types() returns correct values] + expected: FAIL + + [getType(DOMString invalid type) succeeds with correct output] + expected: FAIL + diff --git a/testing/web-platform/meta/content-security-policy/connect-src/connect-src-beacon-redirect-to-blocked.sub.html.ini b/testing/web-platform/meta/content-security-policy/connect-src/connect-src-beacon-redirect-to-blocked.sub.html.ini new file mode 100644 index 0000000000000..c7a458ceb54cb --- /dev/null +++ b/testing/web-platform/meta/content-security-policy/connect-src/connect-src-beacon-redirect-to-blocked.sub.html.ini @@ -0,0 +1,5 @@ +[connect-src-beacon-redirect-to-blocked.sub.html] + [Expecting logs: ["violated-directive=connect-src"\]] + expected: + if (os == "android") and e10s: FAIL + diff --git a/testing/web-platform/meta/content-security-policy/connect-src/connect-src-eventsource-redirect-to-blocked.sub.html.ini b/testing/web-platform/meta/content-security-policy/connect-src/connect-src-eventsource-redirect-to-blocked.sub.html.ini index 18d6b7bc3baf8..ec1e2746494ee 100644 --- a/testing/web-platform/meta/content-security-policy/connect-src/connect-src-eventsource-redirect-to-blocked.sub.html.ini +++ b/testing/web-platform/meta/content-security-policy/connect-src/connect-src-eventsource-redirect-to-blocked.sub.html.ini @@ -3,3 +3,7 @@ [Expecting logs: ["PASS EventSource() did not follow the disallowed redirect.","PASS successfullyParsed is true","TEST COMPLETE"\]] expected: FAIL + [Expecting logs: ["PASS EventSource() did not follow the disallowed redirect.","TEST COMPLETE", "violated-directive=connect-src"\]] + expected: + if (os == "android") and e10s: FAIL + diff --git a/testing/web-platform/meta/content-security-policy/connect-src/connect-src-xmlhttprequest-redirect-to-blocked.sub.html.ini b/testing/web-platform/meta/content-security-policy/connect-src/connect-src-xmlhttprequest-redirect-to-blocked.sub.html.ini new file mode 100644 index 0000000000000..3d145c5676a17 --- /dev/null +++ b/testing/web-platform/meta/content-security-policy/connect-src/connect-src-xmlhttprequest-redirect-to-blocked.sub.html.ini @@ -0,0 +1,5 @@ +[connect-src-xmlhttprequest-redirect-to-blocked.sub.html] + [Expecting logs: ["PASS XMLHttpRequest.send() did not follow the disallowed redirect.","TEST COMPLETE","violated-directive=connect-src"\]] + expected: + if (os == "android") and e10s: FAIL + diff --git a/testing/web-platform/meta/content-security-policy/embedded-enforcement/subsumption_algorithm-hashes.html.ini b/testing/web-platform/meta/content-security-policy/embedded-enforcement/subsumption_algorithm-hashes.html.ini index d458f903d8941..dcea6e4ad9ad1 100644 --- a/testing/web-platform/meta/content-security-policy/embedded-enforcement/subsumption_algorithm-hashes.html.ini +++ b/testing/web-platform/meta/content-security-policy/embedded-enforcement/subsumption_algorithm-hashes.html.ini @@ -1,6 +1,11 @@ [subsumption_algorithm-hashes.html] [Returned should not include hashes not present in required csp.] - expected: FAIL + expected: + if (os == "linux") and debug and not webrender: FAIL + if (os == "linux") and not debug: FAIL + if os == "android": FAIL + if os == "win": FAIL + FAIL [Hashes do not have to be present in returned csp but must not allow all inline behavior.] expected: FAIL diff --git a/testing/web-platform/meta/content-security-policy/generic/eval-typecheck-callout-order.tentative.html.ini b/testing/web-platform/meta/content-security-policy/generic/eval-typecheck-callout-order.tentative.html.ini new file mode 100644 index 0000000000000..81ffa3f9f4b54 --- /dev/null +++ b/testing/web-platform/meta/content-security-policy/generic/eval-typecheck-callout-order.tentative.html.ini @@ -0,0 +1,4 @@ +[eval-typecheck-callout-order.tentative.html] + [eval of a non-string should not be checked by CSP] + expected: FAIL + diff --git a/testing/web-platform/meta/content-security-policy/inheritance/document-write-iframe.html.ini b/testing/web-platform/meta/content-security-policy/inheritance/document-write-iframe.html.ini new file mode 100644 index 0000000000000..abc6b2c55968d --- /dev/null +++ b/testing/web-platform/meta/content-security-policy/inheritance/document-write-iframe.html.ini @@ -0,0 +1,8 @@ +[document-write-iframe.html] + expected: TIMEOUT + [Image loaded in srcdoc iframe using document.write is blocked] + expected: NOTRUN + + [Image loaded in normal iframe using document.write is blocked] + expected: NOTRUN + diff --git a/testing/web-platform/meta/content-security-policy/navigate-to/unsafe-allow-redirects/allowed-end-of-chain.sub.html.ini b/testing/web-platform/meta/content-security-policy/navigate-to/unsafe-allow-redirects/allowed-end-of-chain.sub.html.ini index 6f0600595a223..725ac4e235caa 100644 --- a/testing/web-platform/meta/content-security-policy/navigate-to/unsafe-allow-redirects/allowed-end-of-chain.sub.html.ini +++ b/testing/web-platform/meta/content-security-policy/navigate-to/unsafe-allow-redirects/allowed-end-of-chain.sub.html.ini @@ -1,4 +1,3 @@ [allowed-end-of-chain.sub.html] disabled: - if os == "android" and not e10s: https://bugzilla.mozilla.org/show_bug.cgi?id=1511193 - + if (os == "android") and not e10s: https://bugzilla.mozilla.org/show_bug.cgi?id=1511193 diff --git a/testing/web-platform/meta/content-security-policy/object-src/object-src-url-redirect-blocked.sub.html.ini b/testing/web-platform/meta/content-security-policy/object-src/object-src-url-redirect-blocked.sub.html.ini new file mode 100644 index 0000000000000..a149b71df0b4f --- /dev/null +++ b/testing/web-platform/meta/content-security-policy/object-src/object-src-url-redirect-blocked.sub.html.ini @@ -0,0 +1,7 @@ +[object-src-url-redirect-blocked.sub.html] + expected: + if (os == "android") and e10s: TIMEOUT + [Should block the object and fire a spv] + expected: + if (os == "android") and e10s: NOTRUN + diff --git a/testing/web-platform/meta/content-security-policy/securitypolicyviolation/inside-dedicated-worker.html.ini b/testing/web-platform/meta/content-security-policy/securitypolicyviolation/inside-dedicated-worker.html.ini new file mode 100644 index 0000000000000..59dc90a7a7fc5 --- /dev/null +++ b/testing/web-platform/meta/content-security-policy/securitypolicyviolation/inside-dedicated-worker.html.ini @@ -0,0 +1,7 @@ +[inside-dedicated-worker.html] + expected: + if (os == "android") and e10s: TIMEOUT + [SecurityPolicyViolation event fired on global with the correct blockedURI.] + expected: + if (os == "android") and e10s: TIMEOUT + diff --git a/testing/web-platform/meta/content-security-policy/securitypolicyviolation/inside-service-worker.https.html.ini b/testing/web-platform/meta/content-security-policy/securitypolicyviolation/inside-service-worker.https.html.ini new file mode 100644 index 0000000000000..ba24e1c22d76b --- /dev/null +++ b/testing/web-platform/meta/content-security-policy/securitypolicyviolation/inside-service-worker.https.html.ini @@ -0,0 +1,7 @@ +[inside-service-worker.https.html] + expected: + if (os == "android") and e10s: TIMEOUT + [SecurityPolicyViolation event fired on global with the correct blockedURI.] + expected: + if (os == "android") and e10s: TIMEOUT + diff --git a/testing/web-platform/meta/cookies/samesite/form-get-blank-reload.html.ini b/testing/web-platform/meta/cookies/samesite/form-get-blank-reload.html.ini index a791c6cf297ca..9b728612b0bb5 100644 --- a/testing/web-platform/meta/cookies/samesite/form-get-blank-reload.html.ini +++ b/testing/web-platform/meta/cookies/samesite/form-get-blank-reload.html.ini @@ -2,6 +2,3 @@ [Untitled] expected: FAIL - [Reloaded cross-site top-level form GETs are laxly same-site] - expected: FAIL - diff --git a/testing/web-platform/meta/cookies/samesite/form-get-blank.html.ini b/testing/web-platform/meta/cookies/samesite/form-get-blank.html.ini index 03d8b884e4722..1fd6e7b912925 100644 --- a/testing/web-platform/meta/cookies/samesite/form-get-blank.html.ini +++ b/testing/web-platform/meta/cookies/samesite/form-get-blank.html.ini @@ -2,21 +2,9 @@ [Untitled] expected: FAIL - [Cross-site top-level form GETs are laxly same-site] - expected: FAIL - [Cross-site redirecting to same-host top-level form GETs are strictly same-site] expected: FAIL [Cross-site redirecting to subdomain top-level form GETs are strictly same-site] expected: FAIL - [Same-host redirecting to cross-site top-level form GETs are laxly same-site] - expected: FAIL - - [Subdomain redirecting to cross-site top-level form GETs are laxly same-site] - expected: FAIL - - [Cross-site redirecting to cross-site top-level form GETs are laxly same-site] - expected: FAIL - diff --git a/testing/web-platform/meta/cookies/samesite/window-open-reload.html.ini b/testing/web-platform/meta/cookies/samesite/window-open-reload.html.ini index e1ff57adeb6aa..6f511fb0f2786 100644 --- a/testing/web-platform/meta/cookies/samesite/window-open-reload.html.ini +++ b/testing/web-platform/meta/cookies/samesite/window-open-reload.html.ini @@ -5,6 +5,3 @@ [Reloaded ross-site auxiliary navigations are laxly same-site] expected: FAIL - [Reloaded cross-site auxiliary navigations are laxly same-site] - expected: FAIL - diff --git a/testing/web-platform/meta/cookies/samesite/window-open.html.ini b/testing/web-platform/meta/cookies/samesite/window-open.html.ini index 0eba184195424..293a78e778de8 100644 --- a/testing/web-platform/meta/cookies/samesite/window-open.html.ini +++ b/testing/web-platform/meta/cookies/samesite/window-open.html.ini @@ -2,15 +2,3 @@ [Untitled] expected: FAIL - [Cross-site auxiliary navigations are laxly same-site] - expected: FAIL - - [Same-host redirecting to cross-site auxiliary navigations are laxly same-site] - expected: FAIL - - [Subdomain redirecting to cross-site auxiliary navigations are laxly same-site] - expected: FAIL - - [Cross-site redirecting to cross-site auxiliary navigations are laxly same-site] - expected: FAIL - diff --git a/testing/web-platform/meta/cors/basic.htm.ini b/testing/web-platform/meta/cors/basic.htm.ini new file mode 100644 index 0000000000000..4fd11a97b092f --- /dev/null +++ b/testing/web-platform/meta/cors/basic.htm.ini @@ -0,0 +1,4 @@ +[basic.htm] + [Same domain basic usage] + expected: FAIL + diff --git a/testing/web-platform/meta/css/CSS2/selectors/first-letter-punctuation-088.xht.ini b/testing/web-platform/meta/css/CSS2/selectors/first-letter-punctuation-088.xht.ini index 380adaa6471c7..7a2883ed00ac9 100644 --- a/testing/web-platform/meta/css/CSS2/selectors/first-letter-punctuation-088.xht.ini +++ b/testing/web-platform/meta/css/CSS2/selectors/first-letter-punctuation-088.xht.ini @@ -1,4 +1,3 @@ [first-letter-punctuation-088.xht] expected: if (os == "android") and not e10s: FAIL - if (os == "android") and e10s: FAIL diff --git a/testing/web-platform/meta/css/css-backgrounds/background-attachment-local/attachment-scroll-positioning-1.html.ini b/testing/web-platform/meta/css/css-backgrounds/background-attachment-local/attachment-scroll-positioning-1.html.ini index f09f9f1935040..3f8592dad6dae 100644 --- a/testing/web-platform/meta/css/css-backgrounds/background-attachment-local/attachment-scroll-positioning-1.html.ini +++ b/testing/web-platform/meta/css/css-backgrounds/background-attachment-local/attachment-scroll-positioning-1.html.ini @@ -1,5 +1,4 @@ [attachment-scroll-positioning-1.html] expected: if (os == "win") and (version == "6.1.7601"): FAIL - if (os == "win") and (processor == "aarch64"): PASS if not webrender and (os == "win") and (version == "10.0.17134"): FAIL diff --git a/testing/web-platform/meta/css/css-break/form-control.html.ini b/testing/web-platform/meta/css/css-break/form-control.html.ini new file mode 100644 index 0000000000000..bd012e6de747f --- /dev/null +++ b/testing/web-platform/meta/css/css-break/form-control.html.ini @@ -0,0 +1,4 @@ +[form-control.html] + expected: + if not debug and not webrender and not e10s and (os == "android") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL + if not debug and not webrender and e10s and (os == "android") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL diff --git a/testing/web-platform/meta/css/css-contain/contain-layout-baseline-005.html.ini b/testing/web-platform/meta/css/css-contain/contain-layout-baseline-005.html.ini new file mode 100644 index 0000000000000..513f2af63fa6b --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/contain-layout-baseline-005.html.ini @@ -0,0 +1,3 @@ +[contain-layout-baseline-005.html] + expected: + if os == "android": "FAIL" diff --git a/testing/web-platform/meta/css/css-contain/contain-layout-button-001.html.ini b/testing/web-platform/meta/css/css-contain/contain-layout-button-001.html.ini new file mode 100644 index 0000000000000..e3e9bbb42c01d --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/contain-layout-button-001.html.ini @@ -0,0 +1,3 @@ +[contain-layout-button-001.html] + expected: + if os == "android": "FAIL" diff --git a/testing/web-platform/meta/css/css-contain/contain-size-flexbox-002.html.ini b/testing/web-platform/meta/css/css-contain/contain-size-flexbox-002.html.ini new file mode 100644 index 0000000000000..d8807c71bea38 --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/contain-size-flexbox-002.html.ini @@ -0,0 +1,4 @@ +[contain-size-flexbox-002.html] + expected: + if not debug and not webrender and not e10s and (os == "android") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL + if not debug and not webrender and e10s and (os == "android") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL diff --git a/testing/web-platform/meta/css/css-contain/contain-size-grid-003.html.ini b/testing/web-platform/meta/css/css-contain/contain-size-grid-003.html.ini new file mode 100644 index 0000000000000..2a9fc840b8afe --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/contain-size-grid-003.html.ini @@ -0,0 +1,88 @@ +[contain-size-grid-003.html] + [.grid 19] + expected: FAIL + + [.grid 18] + expected: FAIL + + [.grid 15] + expected: FAIL + + [.grid 17] + expected: FAIL + + [.grid 16] + expected: FAIL + + [.grid 13] + expected: FAIL + + [.grid 34] + expected: FAIL + + [.grid 33] + expected: FAIL + + [.grid 32] + expected: FAIL + + [.grid 31] + expected: FAIL + + [.grid 30] + expected: FAIL + + [.grid 1] + expected: FAIL + + [.grid 3] + expected: FAIL + + [.grid 4] + expected: FAIL + + [.grid 7] + expected: FAIL + + [.grid 6] + expected: FAIL + + [.grid 9] + expected: FAIL + + [.grid 8] + expected: FAIL + + [.grid 25] + expected: FAIL + + [.grid 26] + expected: FAIL + + [.grid 27] + expected: FAIL + + [.grid 20] + expected: FAIL + + [.grid 21] + expected: FAIL + + [.grid 22] + expected: FAIL + + [.grid 28] + expected: FAIL + + [.grid 29] + expected: FAIL + + [.grid 35] + expected: FAIL + + [.grid 37] + expected: FAIL + + [.grid 39] + expected: FAIL + diff --git a/testing/web-platform/meta/css/css-flexbox/flex-vertical-align-effect.html.ini b/testing/web-platform/meta/css/css-flexbox/flex-vertical-align-effect.html.ini deleted file mode 100644 index b1007b3f0f963..0000000000000 --- a/testing/web-platform/meta/css/css-flexbox/flex-vertical-align-effect.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[flex-vertical-align-effect.html] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-grid/grid-definition/grid-auto-repeat-max-size-001.html.ini b/testing/web-platform/meta/css/css-grid/grid-definition/grid-auto-repeat-max-size-001.html.ini new file mode 100644 index 0000000000000..4d73fcf4b4934 --- /dev/null +++ b/testing/web-platform/meta/css/css-grid/grid-definition/grid-auto-repeat-max-size-001.html.ini @@ -0,0 +1,13 @@ +[grid-auto-repeat-max-size-001.html] + [.grid 9] + expected: FAIL + + [.grid 11] + expected: FAIL + + [.grid 10] + expected: FAIL + + [.grid 12] + expected: FAIL + diff --git a/testing/web-platform/meta/css/css-grid/grid-definition/grid-auto-repeat-max-size-002.html.ini b/testing/web-platform/meta/css/css-grid/grid-definition/grid-auto-repeat-max-size-002.html.ini new file mode 100644 index 0000000000000..5c79cea32894a --- /dev/null +++ b/testing/web-platform/meta/css/css-grid/grid-definition/grid-auto-repeat-max-size-002.html.ini @@ -0,0 +1,7 @@ +[grid-auto-repeat-max-size-002.html] + [.grid 3] + expected: FAIL + + [.grid 4] + expected: FAIL + diff --git a/testing/web-platform/meta/css/css-grid/grid-definition/grid-auto-repeat-min-size-001.html.ini b/testing/web-platform/meta/css/css-grid/grid-definition/grid-auto-repeat-min-size-001.html.ini new file mode 100644 index 0000000000000..70d8cff2ffcbf --- /dev/null +++ b/testing/web-platform/meta/css/css-grid/grid-definition/grid-auto-repeat-min-size-001.html.ini @@ -0,0 +1,13 @@ +[grid-auto-repeat-min-size-001.html] + [.grid 9] + expected: FAIL + + [.grid 11] + expected: FAIL + + [.grid 10] + expected: FAIL + + [.grid 12] + expected: FAIL + diff --git a/testing/web-platform/meta/css/css-images/idlharness.html.ini b/testing/web-platform/meta/css/css-images/idlharness.html.ini new file mode 100644 index 0000000000000..21c229b683214 --- /dev/null +++ b/testing/web-platform/meta/css/css-images/idlharness.html.ini @@ -0,0 +1,4 @@ +[idlharness.html] + [CSS namespace: attribute elementSources] + expected: FAIL + diff --git a/testing/web-platform/meta/css/css-images/inheritance.html.ini b/testing/web-platform/meta/css/css-images/inheritance.html.ini new file mode 100644 index 0000000000000..e01233e51c1c1 --- /dev/null +++ b/testing/web-platform/meta/css/css-images/inheritance.html.ini @@ -0,0 +1,7 @@ +[inheritance.html] + [Property image-rendering inherits] + expected: FAIL + + [Property image-orientation has initial value 0deg] + expected: FAIL + diff --git a/testing/web-platform/meta/css/css-images/parsing/image-rendering-computed.html.ini b/testing/web-platform/meta/css/css-images/parsing/image-rendering-computed.html.ini new file mode 100644 index 0000000000000..3ec7c22fb57ae --- /dev/null +++ b/testing/web-platform/meta/css/css-images/parsing/image-rendering-computed.html.ini @@ -0,0 +1,10 @@ +[image-rendering-computed.html] + [Property image-rendering value 'pixelated' computes to 'pixelated'] + expected: FAIL + + [Property image-rendering value 'smooth' computes to 'smooth'] + expected: FAIL + + [Property image-rendering value 'high-quality' computes to 'high-quality'] + expected: FAIL + diff --git a/testing/web-platform/meta/css/css-images/parsing/object-fit-computed.html.ini b/testing/web-platform/meta/css/css-images/parsing/object-fit-computed.html.ini new file mode 100644 index 0000000000000..8b71c1c874e4c --- /dev/null +++ b/testing/web-platform/meta/css/css-images/parsing/object-fit-computed.html.ini @@ -0,0 +1,4 @@ +[object-fit-computed.html] + [Property object-fit value 'cover scale-down' computes to 'cover scale-down'] + expected: FAIL + diff --git a/testing/web-platform/meta/css/css-position/fixed-z-index-blend.html.ini b/testing/web-platform/meta/css/css-position/fixed-z-index-blend.html.ini new file mode 100644 index 0000000000000..fb3388e2b7ed1 --- /dev/null +++ b/testing/web-platform/meta/css/css-position/fixed-z-index-blend.html.ini @@ -0,0 +1,9 @@ +[fixed-z-index-blend.html] + disabled: + if (os == "mac"): https://bugzilla.mozilla.org/show_bug.cgi?id=1552460 + expected: + if (os == "linux") and not debug and not webrender: FAIL + if (os == "linux") and debug and not webrender: FAIL + if (os == "win") and (version == "10.0.17134"): FAIL + if (os == "win") and debug: FAIL + if os == "android": FAIL diff --git a/testing/web-platform/meta/css/css-position/position-absolute-in-inline-002.html.ini b/testing/web-platform/meta/css/css-position/position-absolute-in-inline-002.html.ini new file mode 100644 index 0000000000000..8d3739d5c8865 --- /dev/null +++ b/testing/web-platform/meta/css/css-position/position-absolute-in-inline-002.html.ini @@ -0,0 +1,4 @@ +[position-absolute-in-inline-002.html] + [absolute inside inline container location should be correct.] + expected: FAIL + diff --git a/testing/web-platform/meta/css/css-position/position-sticky-get-bounding-client-rect.html.ini b/testing/web-platform/meta/css/css-position/position-sticky-get-bounding-client-rect.html.ini new file mode 100644 index 0000000000000..d604d90cc2ebd --- /dev/null +++ b/testing/web-platform/meta/css/css-position/position-sticky-get-bounding-client-rect.html.ini @@ -0,0 +1,5 @@ +[position-sticky-get-bounding-client-rect.html] + [sticky positioned element should be observable by getBoundingClientRect.] + expected: + if (os == "android") and e10s: "FAIL" + diff --git a/testing/web-platform/meta/css/css-position/position-sticky-input-box-gets-focused-after-scroll.html.ini b/testing/web-platform/meta/css/css-position/position-sticky-input-box-gets-focused-after-scroll.html.ini new file mode 100644 index 0000000000000..c61db7b430916 --- /dev/null +++ b/testing/web-platform/meta/css/css-position/position-sticky-input-box-gets-focused-after-scroll.html.ini @@ -0,0 +1,5 @@ +[position-sticky-input-box-gets-focused-after-scroll.html] + [Focusing on visible sticky input box should not scroll the page.] + expected: + if (os == "android") and e10s: "FAIL" + diff --git a/testing/web-platform/meta/css/css-position/position-sticky-scrolled-remove-sibling.html.ini b/testing/web-platform/meta/css/css-position/position-sticky-scrolled-remove-sibling.html.ini new file mode 100644 index 0000000000000..6f4fc1c6690cc --- /dev/null +++ b/testing/web-platform/meta/css/css-position/position-sticky-scrolled-remove-sibling.html.ini @@ -0,0 +1,4 @@ +[position-sticky-scrolled-remove-sibling.html] + [Sticky position and its overflow contribution] + expected: FAIL + diff --git a/testing/web-platform/meta/css/css-position/position-sticky-transforms-translate.html.ini b/testing/web-platform/meta/css/css-position/position-sticky-transforms-translate.html.ini new file mode 100644 index 0000000000000..30da63870ad8d --- /dev/null +++ b/testing/web-platform/meta/css/css-position/position-sticky-transforms-translate.html.ini @@ -0,0 +1,5 @@ +[position-sticky-transforms-translate.html] + [Translation transform can move sticky element past sticking point] + expected: + if (os == "android") and e10s: "FAIL" + diff --git a/testing/web-platform/meta/css/css-properties-values-api/register-property-syntax-parsing.html.ini b/testing/web-platform/meta/css/css-properties-values-api/register-property-syntax-parsing.html.ini index 5cb028e0b71c3..32972f8f48445 100644 --- a/testing/web-platform/meta/css/css-properties-values-api/register-property-syntax-parsing.html.ini +++ b/testing/web-platform/meta/css/css-properties-values-api/register-property-syntax-parsing.html.ini @@ -449,3 +449,57 @@ [syntax:' |', initialValue:'banana' is invalid] expected: FAIL + [syntax:'\\1F914 hmm', initialValue:'🤔hmm' is valid] + expected: FAIL + + [syntax:'default', initialValue:'default' is invalid] + expected: FAIL + + [syntax:'hmm\\1F914', initialValue:'hmm🤔' is valid] + expected: FAIL + + [syntax:'\\1F914\\1F914', initialValue:'🤔🤔' is valid] + expected: FAIL + + [syntax:'|REVert', initialValue:'red' is invalid] + expected: FAIL + + [syntax:'\\1F914', initialValue:'🤔' is valid] + expected: FAIL + + [syntax:'', initialValue:'default' is invalid] + expected: FAIL + + [syntax:'*', initialValue:'default' is invalid] + expected: FAIL + + [syntax:'\\1F914hmm', initialValue:'🤔hmm' is valid] + expected: FAIL + + [syntax:'|deFAUlt', initialValue:'1' is invalid] + expected: FAIL + + [syntax:'+', initialValue:'foo revert bar' is invalid] + expected: FAIL + + [syntax:'', initialValue:'revert' is invalid] + expected: FAIL + + [syntax:'+', initialValue:'foo default bar' is invalid] + expected: FAIL + + [syntax:'revert', initialValue:'revert' is invalid] + expected: FAIL + + [syntax:'+', initialValue:'foo unset bar' is invalid] + expected: FAIL + + [syntax:'', initialValue:'inherit' is invalid] + expected: FAIL + + [syntax:'+', initialValue:'foo initial bar' is invalid] + expected: FAIL + + [syntax:'', initialValue:'unset' is invalid] + expected: FAIL + diff --git a/testing/web-platform/meta/css/css-properties-values-api/typedom.html.ini b/testing/web-platform/meta/css/css-properties-values-api/typedom.html.ini new file mode 100644 index 0000000000000..7aa9b76685b44 --- /dev/null +++ b/testing/web-platform/meta/css/css-properties-values-api/typedom.html.ini @@ -0,0 +1,5 @@ +[typedom.html] + expected: ERROR + [Computed * is reified as CSSUnparsedValue] + expected: FAIL + diff --git a/testing/web-platform/meta/css/css-properties-values-api/typedom.tentative.html.ini b/testing/web-platform/meta/css/css-properties-values-api/typedom.tentative.html.ini deleted file mode 100644 index d43221f39eca7..0000000000000 --- a/testing/web-platform/meta/css/css-properties-values-api/typedom.tentative.html.ini +++ /dev/null @@ -1,128 +0,0 @@ -[typedom.tentative.html] - expected: ERROR - [Computed * is reified as CSSUnparsedValue] - expected: FAIL - - [Computed is reified as CSSUnitValue] - expected: FAIL - - [Computed is reified as CSSStyleValue] - expected: FAIL - - [Computed is reified as CSSKeywordValue] - expected: FAIL - - [Computed [url\] is reified as CSSImageValue] - expected: FAIL - - [Computed is reified as CSSUnitValue] - expected: FAIL - - [Computed [%\] is reified as CSSUnitValue] - expected: FAIL - - [Computed [px\] is reified as CSSUnitValue] - expected: FAIL - - [Computed [px + %\] is reified as CSSMathSum] - expected: FAIL - - [Computed is reified as CSSUnitValue] - expected: FAIL - - [Computed is reified as CSSUnitValue] - expected: FAIL - - [Computed is reified as CSSUnitValue] - expected: FAIL - - [Computed is reified as CSSUnitValue] - expected: FAIL - - [Computed