Merge mozilla-central to mozilla-inbound. a=merge on a CLOSED TREE

This commit is contained in:
Razvan Maries 2018-12-05 00:01:48 +02:00
commit 36f8be9d4e
23 changed files with 509 additions and 255 deletions

View File

@ -2,3 +2,8 @@
# https://hg.mozilla.org/mozilla-central/rev/0ceae9db9ec0be18daa1a279511ad305723185d4
abd6d77c618998827e5ffc3dab12f1a34d6ed03d # cinnabar
804b8b8883ba2a6795b0fcf65ebcb18306b6416b # gecko-dev
# Bug 1511181 - Reformat everything to the Google coding style r=ehsan
# https://hg.mozilla.org/mozilla-central/rev/6f3709b3878117466168c40affa7bca0b60cf75b
0e0308d10a5fd4a8dcf0601978776342a2abf2df # cinnabar
265e6721798a455604328ed5262f430cfcc37c2f # gecko-dev

1
Cargo.lock generated
View File

@ -1918,6 +1918,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "profiler_helper"
version = "0.1.0"
dependencies = [
"goblin 0.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"object 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"thin-vec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -33,7 +33,7 @@
<vbox id="separateProfileBox">
<checkbox id="separateProfileMode"
data-l10n-id="separate-profile-mode"/>
<hbox id="sync-dev-edition-root" lign="center" class="indent" hidden="true">
<hbox id="sync-dev-edition-root" align="center" class="indent" hidden="true">
<label id="useFirefoxSync" data-l10n-id="use-firefox-sync"/>
<deck id="getStarted">
<label class="text-link" data-l10n-id="get-started-not-logged-in"/>

View File

@ -216,18 +216,30 @@ const reducers = {
// Find the position of any added declaration which matches the incoming
// declaration to be removed.
const addIndex = rule.add.findIndex(addDecl => {
return addDecl.index === decl.index;
return addDecl.index === decl.index &&
addDecl.property === decl.property &&
addDecl.value === decl.value;
});
// Find the position of any removed declaration which matches the incoming
// declaration to be removed. It's possible to get duplicate remove operations
// when, for example, disabling a declaration then deleting it.
const removeIndex = rule.remove.findIndex(removeDecl => {
return removeDecl.index === decl.index &&
removeDecl.property === decl.property &&
removeDecl.value === decl.value;
});
// Track the remove operation only if the property was not previously introduced
// by an add operation. This ensures repeated changes of the same property
// register as a single remove operation of its original value.
if (addIndex < 0) {
// register as a single remove operation of its original value. Avoid tracking the
// remove declaration if already tracked (happens on disable followed by delete).
if (addIndex < 0 && removeIndex < 0) {
rule.remove.push(decl);
}
// Delete any previous add operation which would be canceled out by this remove.
if (rule.add[addIndex] && rule.add[addIndex].value === decl.value) {
if (rule.add[addIndex]) {
rule.add.splice(addIndex, 1);
}
@ -258,18 +270,19 @@ const reducers = {
// Find the position of any removed declaration which matches the incoming
// declaration to be added.
const removeIndex = rule.remove.findIndex(removeDecl => {
return removeDecl.index === decl.index;
return removeDecl.index === decl.index &&
removeDecl.value === decl.value &&
removeDecl.property === decl.property;
});
// Find the position of any added declaration which matches the incoming
// declaration to be added in case we need to replace it.
const addIndex = rule.add.findIndex(addDecl => {
return addDecl.index === decl.index;
return addDecl.index === decl.index &&
addDecl.property === decl.property;
});
if (rule.remove[removeIndex] &&
rule.remove[removeIndex].value === decl.value &&
rule.remove[removeIndex].property === decl.property) {
if (rule.remove[removeIndex]) {
// Delete any previous remove operation which would be canceled out by this add.
rule.remove.splice(removeIndex, 1);
} else if (rule.add[addIndex]) {

View File

@ -16,6 +16,7 @@ support-files =
[browser_changes_declaration_duplicate.js]
[browser_changes_declaration_edit_value.js]
[browser_changes_declaration_remove_ahead.js]
[browser_changes_declaration_remove_disabled.js]
[browser_changes_declaration_remove.js]
[browser_changes_declaration_rename.js]
[browser_changes_rule_selector.js]

View File

@ -0,0 +1,99 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that disabling a CSS declaration and then removing it from the Rule view
// is tracked as removed only once. Toggling leftover declarations should not introduce
// duplicate changes.
const TEST_URI = `
<style type='text/css'>
div {
color: red;
background: black;
}
</style>
<div></div>
`;
add_task(async function() {
await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
const { inspector, view: ruleView } = await openRuleView();
const { document: doc, store } = selectChangesView(inspector);
await selectNode("div", inspector);
const rule = getRuleViewRuleEditor(ruleView, 1).rule;
info("Using the second declaration");
await testRemoveValue(ruleView, store, doc, rule.textProps[1]);
info("Using the first declaration");
await testToggle(ruleView, store, doc, rule.textProps[0]);
info("Using the first declaration");
await testRemoveName(ruleView, store, doc, rule.textProps[0]);
});
async function testRemoveValue(ruleView, store, doc, prop) {
info("Test removing disabled declaration by clearing its property value.");
let onTrackChange;
onTrackChange = waitUntilAction(store, "TRACK_CHANGE");
info("Disable the declaration");
await togglePropStatus(ruleView, prop);
info("Wait for change to be tracked");
await onTrackChange;
onTrackChange = waitUntilAction(store, "TRACK_CHANGE");
info("Remove the disabled declaration by clearing its value");
await setProperty(ruleView, prop, null);
await onTrackChange;
const removeDecl = getRemovedDeclarations(doc);
is(removeDecl.length, 1, "Only one declaration tracked as removed");
}
async function testToggle(ruleView, store, doc, prop) {
info("Test toggling leftover declaration off and on will not track extra changes.");
let onTrackChange;
onTrackChange = waitUntilAction(store, "TRACK_CHANGE");
info("Disable the declaration");
await togglePropStatus(ruleView, prop);
await onTrackChange;
onTrackChange = waitUntilAction(store, "TRACK_CHANGE");
info("Re-enable the declaration");
await togglePropStatus(ruleView, prop);
await onTrackChange;
const removeDecl = getRemovedDeclarations(doc);
is(removeDecl.length, 1, "Still just one declaration tracked as removed");
}
async function testRemoveName(ruleView, store, doc, prop) {
info("Test removing disabled declaration by clearing its property name.");
let onTrackChange;
onTrackChange = waitUntilAction(store, "TRACK_CHANGE");
info("Disable the declaration");
await togglePropStatus(ruleView, prop);
await onTrackChange;
onTrackChange = waitUntilAction(store, "TRACK_CHANGE");
info("Remove the disabled declaration by clearing its name");
await removeProperty(ruleView, prop);
await onTrackChange;
info(`Expecting two declarations removed:
- one removed by its value in the other test
- one removed by its name from this test
`);
const removeDecl = getRemovedDeclarations(doc);
is(removeDecl.length, 2, "Two declarations tracked as removed");
is(removeDecl[0].property, "background", "First declaration name correct");
is(removeDecl[0].value, "black", "First declaration value correct");
is(removeDecl[1].property, "color", "Second declaration name correct");
is(removeDecl[1].value, "red", "Second declaration value correct");
}

View File

@ -49,5 +49,6 @@ support-files =
[browser_flexbox_sizing_info_updates_on_change.js]
[browser_flexbox_sizing_wanted_to_grow_but_was_clamped.js]
[browser_flexbox_text_nodes_are_listed.js]
[browser_flexbox_text_nodes_are_not_inlined.js]
[browser_flexbox_toggle_flexbox_highlighter_01.js]
[browser_flexbox_toggle_flexbox_highlighter_02.js]

View File

@ -0,0 +1,40 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that single child text nodes that are also flex items can be selected in the
// flexbox inspector.
// This means that they are not inlined like normal single child text nodes, since
// selecting them in the flexbox inspector also means selecting them in the markup view.
const TEST_URI = URL_ROOT + "doc_flexbox_text_nodes.html";
add_task(async function() {
await addTab(TEST_URI);
const { inspector, flexboxInspector } = await openLayoutView();
const { document: doc } = flexboxInspector;
// Select the flex container in the inspector.
const onItemsListRendered = waitForDOM(doc, ".layout-flexbox-wrapper .flex-item-list");
await selectNode(".container.single-child", inspector);
const [flexItemList] = await onItemsListRendered;
const items = [...flexItemList.querySelectorAll("button .objectBox")];
is(items.length, 1, "There is 1 item displayed in the list");
is(items[0].textContent, "#text", "The item in the list is a text node");
info("Click on the item to select it");
const onFlexItemOutlineRendered = waitForDOM(doc, ".flex-outline-container");
items[0].closest("button").click();
const [flexOutlineContainer] = await onFlexItemOutlineRendered;
ok(flexOutlineContainer,
"The flex outline is displayed for a single child short text node too");
ok(inspector.selection.isTextNode(),
"The current inspector selection is the text node");
const markupContainer = inspector.markup.getContainer(inspector.selection.nodeFront);
is(markupContainer.elt.textContent, "short text", "This is the right text node");
});

View File

@ -17,3 +17,4 @@
<div></div>
Here is yet another text node
</div>
<div class="container single-child">short text</div>

View File

@ -20,17 +20,6 @@ const DATA = [
value: null,
extra: {
oldpanel: "layoutview",
newpanel: "changesview",
},
},
{
timestamp: null,
category: "devtools.main",
method: "sidepanel_changed",
object: "inspector",
value: null,
extra: {
oldpanel: "changesview",
newpanel: "animationinspector",
},
},
@ -75,17 +64,6 @@ const DATA = [
value: null,
extra: {
oldpanel: "computedview",
newpanel: "changesview",
},
},
{
timestamp: null,
category: "devtools.main",
method: "sidepanel_changed",
object: "inspector",
value: null,
extra: {
oldpanel: "changesview",
newpanel: "animationinspector",
},
},
@ -128,9 +106,6 @@ add_task(async function() {
// Let's reset the counts.
Services.telemetry.clearEvents();
// Ensure the Changes panel is enabled before running the tests.
await pushPref("devtools.inspector.changes.enabled", true);
// Ensure no events have been logged
const snapshot = Services.telemetry.snapshotEvents(OPTOUT, true);
ok(!snapshot.parent, "No events have been logged for the main process");
@ -155,7 +130,7 @@ function testSidebar(toolbox) {
const inspector = toolbox.getCurrentPanel();
let sidebarTools = ["computedview", "layoutview", "fontinspector",
"animationinspector", "changesview"];
"animationinspector"];
// Concatenate the array with itself so that we can open each tool twice.
sidebarTools = [...sidebarTools, ...sidebarTools];
@ -184,11 +159,9 @@ function checkResults() {
checkTelemetry("DEVTOOLS_COMPUTEDVIEW_OPENED_COUNT", "", {0: 2, 1: 0}, "array");
checkTelemetry("DEVTOOLS_LAYOUTVIEW_OPENED_COUNT", "", {0: 3, 1: 0}, "array");
checkTelemetry("DEVTOOLS_FONTINSPECTOR_OPENED_COUNT", "", {0: 2, 1: 0}, "array");
checkTelemetry("devtools.changesview.opened_count", "", 2, "scalar");
checkTelemetry("DEVTOOLS_COMPUTEDVIEW_TIME_ACTIVE_SECONDS", "", null, "hasentries");
checkTelemetry("DEVTOOLS_LAYOUTVIEW_TIME_ACTIVE_SECONDS", "", null, "hasentries");
checkTelemetry("DEVTOOLS_FONTINSPECTOR_TIME_ACTIVE_SECONDS", "", null, "hasentries");
checkTelemetry("DEVTOOLS_CHANGESVIEW_TIME_ACTIVE_SECONDS", "", null, "hasentries");
}
function checkEventTelemetry() {

View File

@ -35,6 +35,7 @@ loader.lazyRequireGetter(this, "SKIP_TO_SIBLING", "devtools/server/actors/inspec
loader.lazyRequireGetter(this, "NodeActor", "devtools/server/actors/inspector/node", true);
loader.lazyRequireGetter(this, "NodeListActor", "devtools/server/actors/inspector/node", true);
loader.lazyRequireGetter(this, "LayoutActor", "devtools/server/actors/layout", true);
loader.lazyRequireGetter(this, "findFlexOrGridParentContainerForNode", "devtools/server/actors/layout", true);
loader.lazyRequireGetter(this, "getLayoutChangesObserver", "devtools/server/actors/reflow", true);
loader.lazyRequireGetter(this, "releaseLayoutChangesObserver", "devtools/server/actors/reflow", true);
loader.lazyRequireGetter(this, "WalkerSearch", "devtools/server/actors/utils/walker-search", true);
@ -509,13 +510,13 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
*
* @param NodeActor node
*/
inlineTextChild: function(node) {
inlineTextChild: function({ rawNode }) {
// Quick checks to prevent creating a new walker if possible.
if (isBeforePseudoElement(node.rawNode) ||
isAfterPseudoElement(node.rawNode) ||
isShadowHost(node.rawNode) ||
node.rawNode.nodeType != Node.ELEMENT_NODE ||
node.rawNode.children.length > 0) {
if (isBeforePseudoElement(rawNode) ||
isAfterPseudoElement(rawNode) ||
isShadowHost(rawNode) ||
rawNode.nodeType != Node.ELEMENT_NODE ||
rawNode.children.length > 0) {
return undefined;
}
@ -524,11 +525,11 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
// By default always try to use an anonymous walker. Even for DirectShadowHostChild,
// children should be available through an anonymous walker (unless the child is not
// slotted, see catch block).
walker = this.getDocumentWalker(node.rawNode);
walker = this.getDocumentWalker(rawNode);
} catch (e) {
// Using an anonymous walker might throw, for instance on unslotted shadow host
// children.
walker = this.getNonAnonymousWalker(node.rawNode);
walker = this.getNonAnonymousWalker(rawNode);
}
const firstChild = walker.firstChild();
@ -539,17 +540,23 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
// - unique child is a text node, but is too long to be inlined
// - we are a slot -> these are always represented on their own lines with
// a link to the original node.
// - we are a flex item -> these are always shown on their own lines so they can be
// selected by the flexbox inspector.
const isAssignedSlot =
!!firstChild &&
node.rawNode.nodeName === "SLOT" &&
rawNode.nodeName === "SLOT" &&
isDirectShadowHostChild(firstChild);
const isFlexItem =
!!firstChild &&
findFlexOrGridParentContainerForNode(firstChild, "flex", this);
if (!firstChild ||
walker.nextSibling() ||
firstChild.nodeType !== Node.TEXT_NODE ||
firstChild.nodeValue.length > gValueSummaryLength ||
isAssignedSlot
) {
isAssignedSlot ||
isFlexItem) {
return undefined;
}

View File

@ -89,7 +89,8 @@ const FlexboxActor = ActorClassWithSpec(flexboxSpec, {
* Returns an array of FlexItemActor objects for all the flex item elements contained
* in the flex container element.
*
* @return {Array} An array of FlexItemActor objects.
* @return {Array}
* An array of FlexItemActor objects.
*/
getFlexItems() {
if (isNodeDead(this.containerEl)) {
@ -335,12 +336,11 @@ const LayoutActor = ActorClassWithSpec(layoutSpec, {
* The node to start iterating at.
* @param {String} type
* Can be "grid" or "flex", the display type we are searching for.
* @param {Node|null} container
* The container of the current node.
* @return {GridActor|FlexboxActor|null} The GridActor or FlexboxActor of the
* grid/flex container of the give node. Otherwise, returns null.
* @return {GridActor|FlexboxActor|null}
* The GridActor or FlexboxActor of the grid/flex container of the given node.
* Otherwise, returns null.
*/
getCurrentDisplay(node, type, container) {
getCurrentDisplay(node, type) {
if (isNodeDead(node)) {
return null;
}
@ -350,33 +350,20 @@ const LayoutActor = ActorClassWithSpec(layoutSpec, {
node = node.rawNode;
}
const treeWalker = this.walker.getDocumentWalker(node, SHOW_ELEMENT);
let currentNode = treeWalker.currentNode;
let displayType = this.walker.getNode(currentNode).displayType;
const flexType = type === "flex";
const gridType = type === "grid";
const displayType = this.walker.getNode(node).displayType;
// If the node is an element, check first if it is itself a flex or a grid.
if (currentNode.nodeType === currentNode.ELEMENT_NODE) {
if (node.nodeType === node.ELEMENT_NODE) {
if (!displayType) {
return null;
}
if (type == "flex") {
// If only the current node is being considered when finding its display, then
// return it as only a flex container.
if ((displayType == "inline-flex" || displayType == "flex") &&
!container) {
return new FlexboxActor(this, currentNode);
// If considering the current node's container, then we are trying to determine
// the current node's flex item status.
} else if (container) {
if (this.isNodeFlexItemInContainer(currentNode, container)) {
return new FlexboxActor(this, container);
}
}
} else if (type == "grid" &&
(displayType == "inline-grid" || displayType == "grid")) {
return new GridActor(this, currentNode);
if (flexType && displayType.includes("flex")) {
return new FlexboxActor(this, node);
} else if (gridType && displayType.includes("grid")) {
return new GridActor(this, node);
}
}
@ -385,68 +372,53 @@ const LayoutActor = ActorClassWithSpec(layoutSpec, {
// Note that text nodes that are children of flex/grid containers are wrapped in
// anonymous containers, so even if their displayType getter returns null we still
// want to walk up the chain to find their container.
while ((currentNode = treeWalker.parentNode())) {
if (!currentNode) {
break;
}
displayType = this.walker.getNode(currentNode).displayType;
if (type == "flex" &&
(displayType == "inline-flex" || displayType == "flex")) {
if (this.isNodeFlexItemInContainer(node, currentNode)) {
return new FlexboxActor(this, currentNode);
}
} else if (type == "grid" &&
(displayType == "inline-grid" || displayType == "grid")) {
return new GridActor(this, currentNode);
} else if (displayType == "contents") {
// Continue walking up the tree since the parent node is a content element.
continue;
}
break;
const container = findFlexOrGridParentContainerForNode(node, type, this.walker);
if (container && flexType) {
return new FlexboxActor(this, container);
}
if (container && gridType) {
return new GridActor(this, container);
}
return null;
},
/**
* Returns the grid container found by iterating on the given selected node. The current
* node can be a grid container or grid item. If it is a grid item, returns the parent
* grid container. Otherwise, return null if the current or parent node is not a grid
* Returns the grid container for a given selected node.
* The node itself can be a container, but if not, walk up the DOM to find its
* container.
* Returns null if no container can be found.
*
* @param {Node|NodeActor} node
* The node to start iterating at.
* @return {GridActor|null} The GridActor of the grid container of the given node.
* Otherwise, returns null.
* @return {GridActor|null}
* The GridActor of the grid container of the given node. Otherwise, returns
* null.
*/
getCurrentGrid(node) {
return this.getCurrentDisplay(node, "grid");
},
/**
* Returns the flex container found by iterating on the given selected node. The current
* node can be a flex container or flex item. If it is a flex item, returns the parent
* flex container. Otherwise, return null if the current or parent node is not a flex
* Returns the flex container for a given selected node.
* The node itself can be a container, but if not, walk up the DOM to find its
* container.
* Returns null if no container can be found.
*
* @param {Node|NodeActor} node
* The node to start iterating at.
* @param {Boolean|null} onlyLookAtParents
* Whether or not to only consider the parent node of the given node.
* @return {FlexboxActor|null} The FlexboxActor of the flex container of the given node.
* Otherwise, returns null.
* If true, skip the passed node and only start looking at its parent and up.
* @return {FlexboxActor|null}
* The FlexboxActor of the flex container of the given node. Otherwise, returns
* null.
*/
getCurrentFlexbox(node, onlyLookAtParents) {
let container = null;
if (onlyLookAtParents) {
container = node.rawNode.parentNode;
node = node.rawNode.parentNode;
}
return this.getCurrentDisplay(node, "flex", container);
return this.getCurrentDisplay(node, "flex");
},
/**
@ -482,41 +454,93 @@ const LayoutActor = ActorClassWithSpec(layoutSpec, {
return gridActors;
},
/**
* Returns whether or not the given node is actually considered a flex item by its
* container.
*
* @param {Node|NodeActor} supposedItem
* The node that might be a flex item of its container.
* @param {Node} container
* The node's container.
* @return {Boolean} Whether or not the node we are looking at is a flex item of its
* container.
*/
isNodeFlexItemInContainer(supposedItem, container) {
const containerDisplayType = this.walker.getNode(container).displayType;
if (containerDisplayType == "inline-flex" || containerDisplayType == "flex") {
const containerFlex = container.getAsFlexContainer();
for (const line of containerFlex.getLines()) {
for (const item of line.getItems()) {
if (item.node === supposedItem) {
return true;
}
}
}
}
return false;
},
});
function isNodeDead(node) {
return !node || (node.rawNode && Cu.isDeadWrapper(node.rawNode));
}
/**
* If the provided node is a grid of flex item, then return its parent grid or flex
* container.
*
* @param {DOMNode} node
* The node that is supposedly a grid or flex item.
* @param {String} type
* The type of container/item to look for: "flex" or "grid".
* @param {WalkerActor} walkerActor
* The current instance of WalkerActor.
* @return {DOMNode|null}
* The parent grid or flex container if found, null otherwise.
*/
function findFlexOrGridParentContainerForNode(node, type, walker) {
const treeWalker = walker.getDocumentWalker(node, SHOW_ELEMENT);
let currentNode = treeWalker.currentNode;
const flexType = type === "flex";
const gridType = type === "grid";
try {
while ((currentNode = treeWalker.parentNode())) {
if (!currentNode) {
break;
}
const displayType = walker.getNode(currentNode).displayType;
if (!displayType) {
break;
}
if (flexType && displayType.includes("flex")) {
if (isNodeAFlexItemInContainer(node, currentNode, walker)) {
return currentNode;
}
} else if (gridType && displayType.includes("grid")) {
return currentNode;
} else if (displayType === "contents") {
// Continue walking up the tree since the parent node is a content element.
continue;
}
break;
}
} catch (e) {
// Getting the parentNode can fail when the supplied node is in shadow DOM.
}
return null;
}
/**
* Returns whether or not the given node is actually considered a flex item by its
* container.
*
* @param {Node|NodeActor} supposedItem
* The node that might be a flex item of its container.
* @param {Node} container
* The node's container.
* @return {Boolean}
* Whether or not the node we are looking at is a flex item of its container.
*/
function isNodeAFlexItemInContainer(supposedItem, container, walker) {
const containerDisplayType = walker.getNode(container).displayType;
if (containerDisplayType.includes("flex")) {
const containerFlex = container.getAsFlexContainer();
for (const line of containerFlex.getLines()) {
for (const item of line.getItems()) {
if (item.node === supposedItem) {
return true;
}
}
}
}
return false;
}
exports.findFlexOrGridParentContainerForNode = findFlexOrGridParentContainerForNode;
exports.FlexboxActor = FlexboxActor;
exports.FlexItemActor = FlexItemActor;
exports.GridActor = GridActor;

View File

@ -35,9 +35,7 @@ support-files =
[test_addon_events.js]
[test_addon_reload.js]
skip-if = verify # verify mode causes AddonRepository shutdown errors
[test_addons_actor.js]
skip-if = (verify && !debug && (os == 'win'))
[test_animation_name.js]
[test_animation_type.js]
[test_actor-registry-actor.js]

View File

@ -1 +1 @@
a1758f0fc17a71c8d53387be5e9da42495ee11ae
add1538234a214a371e471bff67734afd7c3ca95

View File

@ -586,7 +586,7 @@ impl AlphaBatchBuilder {
};
let instance = PrimitiveInstanceData::from(BrushInstance {
segment_index: 0,
segment_index: INVALID_SEGMENT_INDEX,
edge_flags: EdgeAaSegmentMask::all(),
clip_task_address,
brush_flags: BrushFlags::PERSPECTIVE_INTERPOLATION,
@ -862,7 +862,7 @@ impl AlphaBatchBuilder {
};
let instance = PrimitiveInstanceData::from(BrushInstance {
segment_index: 0,
segment_index: INVALID_SEGMENT_INDEX,
edge_flags: EdgeAaSegmentMask::all(),
clip_task_address,
brush_flags: BrushFlags::PERSPECTIVE_INTERPOLATION,
@ -1107,7 +1107,7 @@ impl AlphaBatchBuilder {
let instance = BrushInstance {
prim_header_index,
segment_index: 0,
segment_index: INVALID_SEGMENT_INDEX,
edge_flags: EdgeAaSegmentMask::empty(),
brush_flags: BrushFlags::empty(),
clip_task_address,
@ -1189,7 +1189,7 @@ impl AlphaBatchBuilder {
let shadow_instance = BrushInstance {
prim_header_index: shadow_prim_header_index,
clip_task_address,
segment_index: 0,
segment_index: INVALID_SEGMENT_INDEX,
edge_flags: EdgeAaSegmentMask::empty(),
brush_flags: BrushFlags::empty(),
user_data: shadow_uv_rect_address,
@ -1198,7 +1198,7 @@ impl AlphaBatchBuilder {
let content_instance = BrushInstance {
prim_header_index: content_prim_header_index,
clip_task_address,
segment_index: 0,
segment_index: INVALID_SEGMENT_INDEX,
edge_flags: EdgeAaSegmentMask::empty(),
brush_flags: BrushFlags::empty(),
user_data: content_uv_rect_address,
@ -1283,7 +1283,7 @@ impl AlphaBatchBuilder {
let instance = BrushInstance {
prim_header_index,
clip_task_address,
segment_index: 0,
segment_index: INVALID_SEGMENT_INDEX,
edge_flags: EdgeAaSegmentMask::empty(),
brush_flags: BrushFlags::empty(),
user_data: 0,
@ -1328,7 +1328,7 @@ impl AlphaBatchBuilder {
let instance = BrushInstance {
prim_header_index,
clip_task_address,
segment_index: 0,
segment_index: INVALID_SEGMENT_INDEX,
edge_flags: EdgeAaSegmentMask::empty(),
brush_flags: BrushFlags::empty(),
user_data: 0,
@ -1368,7 +1368,7 @@ impl AlphaBatchBuilder {
let instance = BrushInstance {
prim_header_index,
clip_task_address,
segment_index: 0,
segment_index: INVALID_SEGMENT_INDEX,
edge_flags: EdgeAaSegmentMask::empty(),
brush_flags: BrushFlags::empty(),
user_data: uv_rect_address,

View File

@ -1017,7 +1017,7 @@ impl PrimitiveTemplateKind {
fn write_prim_gpu_blocks(
&self,
request: &mut GpuDataRequest,
prim_rect: LayoutRect,
prim_size: LayoutSize,
) {
match *self {
PrimitiveTemplateKind::Clear => {
@ -1034,8 +1034,8 @@ impl PrimitiveTemplateKind {
request.push(PremultipliedColorF::WHITE);
request.push(PremultipliedColorF::WHITE);
request.push([
prim_rect.size.width,
prim_rect.size.height,
prim_size.width,
prim_size.height,
0.0,
0.0,
]);
@ -1047,8 +1047,8 @@ impl PrimitiveTemplateKind {
request.push(PremultipliedColorF::WHITE);
request.push(PremultipliedColorF::WHITE);
request.push([
prim_rect.size.width,
prim_rect.size.height,
prim_size.width,
prim_size.height,
0.0,
0.0,
]);
@ -1165,15 +1165,8 @@ impl PrimitiveTemplateKind {
fn write_segment_gpu_blocks(
&self,
request: &mut GpuDataRequest,
prim_rect: LayoutRect,
) {
match *self {
PrimitiveTemplateKind::Clear => {
request.write_segment(
prim_rect,
[0.0; 4],
);
}
PrimitiveTemplateKind::NormalBorder { ref template, .. } => {
for segment in &template.brush_segments {
// has to match VECS_PER_SEGMENT
@ -1192,12 +1185,6 @@ impl PrimitiveTemplateKind {
);
}
}
PrimitiveTemplateKind::LineDecoration { .. } => {
request.write_segment(
prim_rect,
[0.0; 4],
);
}
PrimitiveTemplateKind::LinearGradient { ref brush_segments, .. } |
PrimitiveTemplateKind::RadialGradient { ref brush_segments, .. } => {
for segment in brush_segments {
@ -1208,6 +1195,8 @@ impl PrimitiveTemplateKind {
);
}
}
PrimitiveTemplateKind::Clear |
PrimitiveTemplateKind::LineDecoration { .. } |
PrimitiveTemplateKind::Image { .. } |
PrimitiveTemplateKind::Rectangle { .. } |
PrimitiveTemplateKind::TextRun { .. } |
@ -1233,8 +1222,11 @@ impl PrimitiveTemplate {
frame_state: &mut FrameBuildingState,
) {
if let Some(mut request) = frame_state.gpu_cache.request(&mut self.gpu_cache_handle) {
self.kind.write_prim_gpu_blocks(&mut request, self.prim_rect);
self.kind.write_segment_gpu_blocks(&mut request, self.prim_rect);
self.kind.write_prim_gpu_blocks(
&mut request,
self.prim_rect.size,
);
self.kind.write_segment_gpu_blocks(&mut request);
}
self.opacity = match self.kind {
@ -3097,10 +3089,6 @@ impl PrimitiveStore {
0.0,
0.0,
]);
request.write_segment(
pic.local_rect,
[0.0; 4],
);
}
}
PrimitiveInstanceKind::TextRun { .. } |
@ -3604,7 +3592,10 @@ impl PrimitiveStore {
if let Some(mut request) = frame_state.gpu_cache.request(&mut segment_instance.gpu_cache_handle) {
let segments = &scratch.segments[segment_instance.segments_range];
prim_data.kind.write_prim_gpu_blocks(&mut request, prim_data.prim_rect);
prim_data.kind.write_prim_gpu_blocks(
&mut request,
prim_data.prim_rect.size,
);
for segment in segments {
request.write_segment(

View File

@ -380,9 +380,9 @@ class Bootstrapper(object):
sys.exit(1)
self.instance.state_dir = state_dir
self.instance.ensure_clang_static_analysis_package(checkout_root)
self.instance.ensure_stylo_packages(state_dir, checkout_root)
self.instance.ensure_node_packages(state_dir, checkout_root)
self.instance.ensure_clang_static_analysis_package(checkout_root)
def check_telemetry_opt_in(self, state_dir):
# We can't prompt the user.

View File

@ -885,10 +885,15 @@ bool AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor(
return false;
}
// Let's check if this is a 3rd party context.
if (!nsContentUtils::IsThirdPartyWindowOrChannel(aWindow, nullptr, aURI)) {
LOG(("Our window isn't a third-party window"));
return true;
// As a performance optimization, we only perform this check for
// BEHAVIOR_REJECT_FOREIGN and BEHAVIOR_LIMIT_FOREIGN. For
// BEHAVIOR_REJECT_TRACKER, third-partiness is implicily checked later below.
if (behavior != nsICookieService::BEHAVIOR_REJECT_TRACKER) {
// Let's check if this is a 3rd party context.
if (!nsContentUtils::IsThirdPartyWindowOrChannel(aWindow, nullptr, aURI)) {
LOG(("Our window isn't a third-party window"));
return true;
}
}
if (behavior == nsICookieService::BEHAVIOR_REJECT_FOREIGN ||
@ -909,6 +914,20 @@ bool AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor(
return true;
}
#ifdef DEBUG
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = services::GetThirdPartyUtil();
if (thirdPartyUtil) {
bool thirdParty = false;
nsresult rv = thirdPartyUtil->IsThirdPartyWindow(aWindow->GetOuterWindow(),
aURI, &thirdParty);
// The result of this assertion depends on whether IsThirdPartyWindow
// succeeds, because otherwise IsThirdPartyWindowOrChannel artificially
// fails.
MOZ_ASSERT(nsContentUtils::IsThirdPartyWindowOrChannel(
aWindow, nullptr, aURI) == NS_SUCCEEDED(rv));
}
#endif
nsCOMPtr<nsIPrincipal> parentPrincipal;
nsCOMPtr<nsIURI> parentPrincipalURI;
nsCOMPtr<nsIURI> trackingURI;

View File

@ -1,61 +1,61 @@
# 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/.
title = About Networking
warning = This is very experimental. Do not use without adult supervision.
show-next-time-checkbox = Show this warning next time
ok = OK
http = HTTP
sockets = Sockets
dns = DNS
websockets = WebSockets
refresh = Refresh
auto-refresh = Autorefresh every 3 seconds
hostname = Hostname
port = Port
http2 = HTTP/2
ssl = SSL
active = Active
idle = Idle
host = Host
tcp = TCP
sent = Sent
received = Received
family = Family
trr = TRR
addresses = Addresses
expires = Expires (Seconds)
messages-sent = Messages Sent
messages-received = Messages Received
bytes-sent = Bytes Sent
bytes-received = Bytes Received
logging = Logging
log-tutorial =
See <a data-l10n-name="logging">HTTP Logging</a>
for instructions on how to use this tool.
current-log-file = Current Log File:
current-log-modules = Current Log Modules:
set-log-file = Set Log File
set-log-modules = Set Log Modules
start-logging = Start Logging
stop-logging = Stop Logging
dns-lookup = DNS Lookup
dns-lookup-button = Resolve
dns-domain = Domain:
dns-lookup-table-column = IPs
rcwn = RCWN Stats
rcwn-status = RCWN Status
rcwn-cache-won-count = Cache won count
rcwn-net-won-count = Net won count
total-network-requests = Total network request count
rcwn-operation = Cache Operation
rcwn-perf-open = Open
rcwn-perf-read = Read
rcwn-perf-write = Write
rcwn-perf-entry-open = Entry Open
rcwn-avg-short = Short Average
rcwn-avg-long = Long Average
rcwn-std-dev-long = Long Standard Deviation
rcwn-cache-slow = Cache slow count
rcwn-cache-not-slow = Cache not slow count
# 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/.
title = About Networking
warning = This is very experimental. Do not use without adult supervision.
show-next-time-checkbox = Show this warning next time
ok = OK
http = HTTP
sockets = Sockets
dns = DNS
websockets = WebSockets
refresh = Refresh
auto-refresh = Autorefresh every 3 seconds
hostname = Hostname
port = Port
http2 = HTTP/2
ssl = SSL
active = Active
idle = Idle
host = Host
tcp = TCP
sent = Sent
received = Received
family = Family
trr = TRR
addresses = Addresses
expires = Expires (Seconds)
messages-sent = Messages Sent
messages-received = Messages Received
bytes-sent = Bytes Sent
bytes-received = Bytes Received
logging = Logging
log-tutorial =
See <a data-l10n-name="logging">HTTP Logging</a>
for instructions on how to use this tool.
current-log-file = Current Log File:
current-log-modules = Current Log Modules:
set-log-file = Set Log File
set-log-modules = Set Log Modules
start-logging = Start Logging
stop-logging = Stop Logging
dns-lookup = DNS Lookup
dns-lookup-button = Resolve
dns-domain = Domain:
dns-lookup-table-column = IPs
rcwn = RCWN Stats
rcwn-status = RCWN Status
rcwn-cache-won-count = Cache won count
rcwn-net-won-count = Net won count
total-network-requests = Total network request count
rcwn-operation = Cache Operation
rcwn-perf-open = Open
rcwn-perf-read = Read
rcwn-perf-write = Write
rcwn-perf-entry-open = Entry Open
rcwn-avg-short = Short Average
rcwn-avg-long = Long Average
rcwn-std-dev-long = Long Standard Deviation
rcwn-cache-slow = Cache slow count
rcwn-cache-not-slow = Cache not slow count

View File

@ -12,9 +12,17 @@ optional = true
default-features = false
features = ["std"]
[dependencies.goblin]
optional = true
# The version and features of goblin need to match what's in object's Cargo.toml,
# because we really want object's goblin and not another instance of goblin.
version = "0.0.17"
features = ["endian_fd", "elf32", "elf64", "mach32", "mach64", "pe32", "pe64", "archive"]
default-features = false
[dependencies.thin-vec]
version = "0.1.0"
features = ["gecko-ffi"]
[features]
parse_elf = ["object"]
parse_elf = ["object", "goblin"]

View File

@ -1,6 +1,11 @@
use compact_symbol_table::CompactSymbolTable;
use object::{ElfFile, Object, SymbolKind, Uuid};
use std::collections::HashMap;
use std::cmp;
use goblin::elf;
const UUID_SIZE: usize = 16;
const PAGE_SIZE: usize = 4096;
fn get_symbol_map<'a, 'b, T>(object_file: &'b T) -> HashMap<u32, &'a str>
where
@ -16,9 +21,73 @@ where
pub fn get_compact_symbol_table(buffer: &[u8], breakpad_id: &str) -> Option<CompactSymbolTable> {
let elf_file = ElfFile::parse(buffer).ok()?;
let elf_id = Uuid::from_bytes(elf_file.build_id()?).ok()?;
let elf_id = get_elf_id(&elf_file, buffer)?;
if format!("{:X}0", elf_id.simple()) != breakpad_id {
return None;
}
return Some(CompactSymbolTable::from_map(get_symbol_map(&elf_file)));
}
fn create_elf_id(identifier: &[u8], little_endian: bool) -> Option<Uuid> {
// Make sure that we have exactly UUID_SIZE bytes available
let mut data = [0 as u8; UUID_SIZE];
let len = cmp::min(identifier.len(), UUID_SIZE);
data[0..len].copy_from_slice(&identifier[0..len]);
if little_endian {
// The file ELF file targets a little endian architecture. Convert to
// network byte order (big endian) to match the Breakpad processor's
// expectations. For big endian object files, this is not needed.
data[0..4].reverse(); // uuid field 1
data[4..6].reverse(); // uuid field 2
data[6..8].reverse(); // uuid field 3
}
Uuid::from_bytes(&data).ok()
}
/// Tries to obtain the object identifier of an ELF object.
///
/// As opposed to Mach-O, ELF does not specify a unique ID for object files in
/// its header. Compilers and linkers usually add either `SHT_NOTE` sections or
/// `PT_NOTE` program header elements for this purpose. If one of these notes
/// is present, ElfFile's build_id() method will find it.
///
/// If neither of the above are present, this function will hash the first page
/// of the `.text` section (program code). This matches what the Breakpad
/// processor does.
///
/// If all of the above fails, this function will return `None`.
pub fn get_elf_id(elf_file: &ElfFile, data: &[u8]) -> Option<Uuid> {
if let Some(identifier) = elf_file.build_id() {
return create_elf_id(identifier, elf_file.elf().little_endian);
}
// We were not able to locate the build ID, so fall back to hashing the
// first page of the ".text" (program code) section. This algorithm XORs
// 16-byte chunks directly into a UUID buffer.
if let Some(section_data) = find_text_section(elf_file.elf(), data) {
let mut hash = [0; UUID_SIZE];
for i in 0..cmp::min(section_data.len(), PAGE_SIZE) {
hash[i % UUID_SIZE] ^= section_data[i];
}
return create_elf_id(&hash, elf_file.elf().little_endian);
}
None
}
/// Returns a reference to the data of the the .text section in an ELF binary.
fn find_text_section<'elf, 'data>(
elf: &'elf elf::Elf,
data: &'data [u8],
) -> Option<&'data[u8]> {
elf.section_headers.iter().find_map(|header| {
match (header.sh_type, elf.shdr_strtab.get(header.sh_name)) {
(elf::section_header::SHT_PROGBITS, Some(Ok(".text"))) =>
Some(&data[header.sh_offset as usize..][..header.sh_size as usize]),
_ => None
}
})
}

View File

@ -3,6 +3,8 @@ extern crate thin_vec;
#[cfg(feature = "parse_elf")]
extern crate object;
#[cfg(feature = "parse_elf")]
extern crate goblin;
mod compact_symbol_table;

View File

@ -128,15 +128,20 @@ nsMacUtilsImpl::GetIsTranslated(bool* aIsTranslated) {
}
#if defined(MOZ_CONTENT_SANDBOX)
// Get the path to the .app directory for the parent process. When executing
// in the child process, this is the outer .app (such as Firefox.app) and not
// the inner .app containing the child process executable.
// Get the path to the .app directory (aka bundle) for the parent process.
// When executing in the child process, this is the outer .app (such as
// Firefox.app) and not the inner .app containing the child process
// executable. We don't rely on the actual .app extension to allow for the
// bundle being renamed.
bool nsMacUtilsImpl::GetAppPath(nsCString& aAppPath) {
nsAutoCString appPath;
nsAutoCString appBinaryPath(
(CommandLine::ForCurrentProcess()->argv()[0]).c_str());
auto pattern = NS_LITERAL_CSTRING(".app/Contents/MacOS/");
// The binary path resides within the .app dir in Contents/MacOS,
// e.g., Firefox.app/Contents/MacOS/firefox. Search backwards in
// the binary path for the end of .app path.
auto pattern = NS_LITERAL_CSTRING("/Contents/MacOS/");
nsAutoCString::const_iterator start, end;
appBinaryPath.BeginReading(start);
appBinaryPath.EndReading(end);
@ -144,8 +149,9 @@ bool nsMacUtilsImpl::GetAppPath(nsCString& aAppPath) {
end = start;
appBinaryPath.BeginReading(start);
// If we're executing in a child process, get the
// parent .app by searching right-to-left once more.
// If we're executing in a child process, get the parent .app path
// by searching backwards once more. The child executable resides
// in Firefox.app/Contents/MacOS/plugin-container/Contents/MacOS.
if (!XRE_IsParentProcess()) {
if (RFindInReadable(pattern, start, end)) {
end = start;
@ -155,10 +161,6 @@ bool nsMacUtilsImpl::GetAppPath(nsCString& aAppPath) {
}
}
++end;
++end;
++end;
++end;
appPath.Assign(Substring(start, end));
} else {
return false;