diff --git a/browser/components/contextualidentity/test/browser/browser_aboutURLs.js b/browser/components/contextualidentity/test/browser/browser_aboutURLs.js
index 6206755fb09a..586bca37fb39 100644
--- a/browser/components/contextualidentity/test/browser/browser_aboutURLs.js
+++ b/browser/components/contextualidentity/test/browser/browser_aboutURLs.js
@@ -38,10 +38,11 @@ add_task(function* () {
}
for (let url of aboutURLs) {
+ info("Loading about:" + url);
let tab = gBrowser.addTab("about:"+url, {userContextId: 1});
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
- ok(true);
+ ok(true, "Done loading about:" + url);
yield BrowserTestUtils.removeTab(tab);
}
diff --git a/devtools/client/inspector/rules/test/browser.ini b/devtools/client/inspector/rules/test/browser.ini
index 673e6da9d058..23bc62592af4 100644
--- a/devtools/client/inspector/rules/test/browser.ini
+++ b/devtools/client/inspector/rules/test/browser.ini
@@ -128,6 +128,8 @@ skip-if = os == "mac" # Bug 1245996 : click on scrollbar not working on OSX
[browser_rules_edit-selector_07.js]
[browser_rules_edit-selector_08.js]
[browser_rules_edit-selector_09.js]
+[browser_rules_edit-selector_10.js]
+[browser_rules_edit-selector_11.js]
[browser_rules_edit-value-after-name_01.js]
[browser_rules_edit-value-after-name_02.js]
[browser_rules_edit-value-after-name_03.js]
diff --git a/devtools/client/inspector/rules/test/browser_rules_edit-selector_10.js b/devtools/client/inspector/rules/test/browser_rules_edit-selector_10.js
new file mode 100644
index 000000000000..d878dd5163f7
--- /dev/null
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-selector_10.js
@@ -0,0 +1,64 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Regression test for bug 1293616: make sure that editing a selector
+// keeps the rule in the proper position.
+
+const TEST_URI = `
+
+
+
+ Styled Node
+
+
+`;
+
+add_task(function* () {
+ yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+ let {inspector, view} = yield openRuleView();
+ yield selectNode(".pickme", inspector);
+ yield testEditSelector(view);
+});
+
+function* testEditSelector(view) {
+ let ruleEditor = getRuleViewRuleEditor(view, 1);
+ let editor = yield focusEditableField(view, ruleEditor.selectorText);
+
+ editor.input.value = "#testid span";
+ let onRuleViewChanged = once(view, "ruleview-changed");
+ EventUtils.synthesizeKey("VK_RETURN", {});
+ yield onRuleViewChanged;
+
+ // Escape the new property editor after editing the selector
+ let onBlur = once(view.styleDocument.activeElement, "blur");
+ EventUtils.synthesizeKey("VK_ESCAPE", {}, view.styleWindow);
+ yield onBlur;
+
+ // Get the new rule editor that replaced the original
+ ruleEditor = getRuleViewRuleEditor(view, 1);
+
+ info("Check that the correct rules are visible");
+ is(view._elementStyle.rules.length, 3, "Should have 3 rules.");
+ is(ruleEditor.element.getAttribute("unmatched"), "false", "Rule editor is matched.");
+
+ let props = ruleEditor.rule.textProps;
+ is(props.length, 1, "Rule has correct number of properties");
+ is(props[0].name, "background", "Found background property");
+ ok(!props[0].overridden, "Background property is not overridden");
+
+ ruleEditor = getRuleViewRuleEditor(view, 2);
+ props = ruleEditor.rule.textProps;
+ is(props.length, 1, "Rule has correct number of properties");
+ is(props[0].name, "background", "Found background property");
+ ok(props[0].overridden, "Background property is overridden");
+}
diff --git a/devtools/client/inspector/rules/test/browser_rules_edit-selector_11.js b/devtools/client/inspector/rules/test/browser_rules_edit-selector_11.js
new file mode 100644
index 000000000000..9a1bdc8fa86e
--- /dev/null
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-selector_11.js
@@ -0,0 +1,69 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Regression test for bug 1293616, where editing a selector should
+// change the relative priority of the rule.
+
+const TEST_URI = `
+
+
+
+ Styled Node
+
+
+`;
+
+add_task(function* () {
+ yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+ let {inspector, view} = yield openRuleView();
+ yield selectNode(".pickme", inspector);
+ yield testEditSelector(view);
+});
+
+function* testEditSelector(view) {
+ let ruleEditor = getRuleViewRuleEditor(view, 1);
+ let editor = yield focusEditableField(view, ruleEditor.selectorText);
+
+ editor.input.value = ".pickme";
+ let onRuleViewChanged = once(view, "ruleview-changed");
+ EventUtils.synthesizeKey("VK_RETURN", {});
+ yield onRuleViewChanged;
+
+ // Escape the new property editor after editing the selector
+ let onBlur = once(view.styleDocument.activeElement, "blur");
+ EventUtils.synthesizeKey("VK_ESCAPE", {}, view.styleWindow);
+ yield onBlur;
+
+ // Get the new rule editor that replaced the original
+ ruleEditor = getRuleViewRuleEditor(view, 1);
+
+ info("Check that the correct rules are visible");
+ is(view._elementStyle.rules.length, 4, "Should have 4 rules.");
+ is(ruleEditor.element.getAttribute("unmatched"), "false", "Rule editor is matched.");
+
+ let props = ruleEditor.rule.textProps;
+ is(props.length, 1, "Rule has correct number of properties");
+ is(props[0].name, "background", "Found background property");
+ is(props[0].value, "aqua", "Background property is aqua");
+ ok(props[0].overridden, "Background property is overridden");
+
+ ruleEditor = getRuleViewRuleEditor(view, 2);
+ props = ruleEditor.rule.textProps;
+ is(props.length, 1, "Rule has correct number of properties");
+ is(props[0].name, "background", "Found background property");
+ is(props[0].value, "seagreen", "Background property is seagreen");
+ ok(!props[0].overridden, "Background property is not overridden");
+}
diff --git a/devtools/client/inspector/rules/views/rule-editor.js b/devtools/client/inspector/rules/views/rule-editor.js
index fa0c3aa6abae..e12794434ac0 100644
--- a/devtools/client/inspector/rules/views/rule-editor.js
+++ b/devtools/client/inspector/rules/views/rule-editor.js
@@ -27,6 +27,7 @@ const {
const promise = require("promise");
const Services = require("Services");
const EventEmitter = require("devtools/shared/event-emitter");
+const {Task} = require("devtools/shared/task");
const STYLE_INSPECTOR_PROPERTIES = "devtools-shared/locale/styleinspector.properties";
const {LocalizationHelper} = require("devtools/shared/l10n");
@@ -517,7 +518,7 @@ RuleEditor.prototype = {
* @param {Number} direction
* The move focus direction number.
*/
- _onSelectorDone: function (value, commit, direction) {
+ _onSelectorDone: Task.async(function* (value, commit, direction) {
if (!commit || this.isEditing || value === "" ||
value === this.rule.selectorText) {
return;
@@ -531,16 +532,28 @@ RuleEditor.prototype = {
this.isEditing = true;
- this.rule.domRule.modifySelector(element, value).then(response => {
- this.isEditing = false;
+ try {
+ let response = yield this.rule.domRule.modifySelector(element, value);
if (!supportsUnmatchedRules) {
+ this.isEditing = false;
+
if (response) {
this.ruleView.refreshPanel();
}
return;
}
+ // We recompute the list of applied styles, because editing a
+ // selector might cause this rule's position to change.
+ let applied = yield elementStyle.pageStyle.getApplied(element, {
+ inherited: true,
+ matchedSelectors: true,
+ filter: elementStyle.showUserAgentStyles ? "ua" : undefined
+ });
+
+ this.isEditing = false;
+
let {ruleProps, isMatching} = response;
if (!ruleProps) {
// Notify for changes, even when nothing changes,
@@ -554,11 +567,25 @@ RuleEditor.prototype = {
let editor = new RuleEditor(ruleView, newRule);
let rules = elementStyle.rules;
- rules.splice(rules.indexOf(this.rule), 1);
- rules.push(newRule);
+ let newRuleIndex = applied.findIndex((r) => r.rule == ruleProps.rule);
+ let oldIndex = rules.indexOf(this.rule);
+
+ // If the selector no longer matches, then we leave the rule in
+ // the same relative position.
+ if (newRuleIndex === -1) {
+ newRuleIndex = oldIndex;
+ }
+
+ // Remove the old rule and insert the new rule.
+ rules.splice(oldIndex, 1);
+ rules.splice(newRuleIndex, 0, newRule);
elementStyle._changed();
elementStyle.markOverriddenAll();
+ // We install the new editor in place of the old -- you might
+ // think we would replicate the list-modification logic above,
+ // but that is complicated due to the way the UI installs
+ // pseudo-element rules and the like.
this.element.parentNode.replaceChild(editor.element, this.element);
// Remove highlight for modified selector
@@ -568,11 +595,11 @@ RuleEditor.prototype = {
}
editor._moveSelectorFocus(direction);
- }).then(null, err => {
+ } catch (err) {
this.isEditing = false;
promiseWarn(err);
- });
- },
+ }
+ }),
/**
* Handle moving the focus change after a tab or return keypress in the
diff --git a/devtools/client/netmonitor/events.js b/devtools/client/netmonitor/events.js
new file mode 100644
index 000000000000..8062a2f8c2e3
--- /dev/null
+++ b/devtools/client/netmonitor/events.js
@@ -0,0 +1,86 @@
+"use strict";
+
+// The panel's window global is an EventEmitter firing the following events:
+const EVENTS = {
+ // When the monitored target begins and finishes navigating.
+ TARGET_WILL_NAVIGATE: "NetMonitor:TargetWillNavigate",
+ TARGET_DID_NAVIGATE: "NetMonitor:TargetNavigate",
+
+ // When a network or timeline event is received.
+ // See https://developer.mozilla.org/docs/Tools/Web_Console/remoting for
+ // more information about what each packet is supposed to deliver.
+ NETWORK_EVENT: "NetMonitor:NetworkEvent",
+ TIMELINE_EVENT: "NetMonitor:TimelineEvent",
+
+ // When a network event is added to the view
+ REQUEST_ADDED: "NetMonitor:RequestAdded",
+
+ // When request headers begin and finish receiving.
+ UPDATING_REQUEST_HEADERS: "NetMonitor:NetworkEventUpdating:RequestHeaders",
+ RECEIVED_REQUEST_HEADERS: "NetMonitor:NetworkEventUpdated:RequestHeaders",
+
+ // When request cookies begin and finish receiving.
+ UPDATING_REQUEST_COOKIES: "NetMonitor:NetworkEventUpdating:RequestCookies",
+ RECEIVED_REQUEST_COOKIES: "NetMonitor:NetworkEventUpdated:RequestCookies",
+
+ // When request post data begins and finishes receiving.
+ UPDATING_REQUEST_POST_DATA: "NetMonitor:NetworkEventUpdating:RequestPostData",
+ RECEIVED_REQUEST_POST_DATA: "NetMonitor:NetworkEventUpdated:RequestPostData",
+
+ // When security information begins and finishes receiving.
+ UPDATING_SECURITY_INFO: "NetMonitor::NetworkEventUpdating:SecurityInfo",
+ RECEIVED_SECURITY_INFO: "NetMonitor::NetworkEventUpdated:SecurityInfo",
+
+ // When response headers begin and finish receiving.
+ UPDATING_RESPONSE_HEADERS: "NetMonitor:NetworkEventUpdating:ResponseHeaders",
+ RECEIVED_RESPONSE_HEADERS: "NetMonitor:NetworkEventUpdated:ResponseHeaders",
+
+ // When response cookies begin and finish receiving.
+ UPDATING_RESPONSE_COOKIES: "NetMonitor:NetworkEventUpdating:ResponseCookies",
+ RECEIVED_RESPONSE_COOKIES: "NetMonitor:NetworkEventUpdated:ResponseCookies",
+
+ // When event timings begin and finish receiving.
+ UPDATING_EVENT_TIMINGS: "NetMonitor:NetworkEventUpdating:EventTimings",
+ RECEIVED_EVENT_TIMINGS: "NetMonitor:NetworkEventUpdated:EventTimings",
+
+ // When response content begins, updates and finishes receiving.
+ STARTED_RECEIVING_RESPONSE: "NetMonitor:NetworkEventUpdating:ResponseStart",
+ UPDATING_RESPONSE_CONTENT: "NetMonitor:NetworkEventUpdating:ResponseContent",
+ RECEIVED_RESPONSE_CONTENT: "NetMonitor:NetworkEventUpdated:ResponseContent",
+
+ // When the request post params are displayed in the UI.
+ REQUEST_POST_PARAMS_DISPLAYED: "NetMonitor:RequestPostParamsAvailable",
+
+ // When the response body is displayed in the UI.
+ RESPONSE_BODY_DISPLAYED: "NetMonitor:ResponseBodyAvailable",
+
+ // When the html response preview is displayed in the UI.
+ RESPONSE_HTML_PREVIEW_DISPLAYED: "NetMonitor:ResponseHtmlPreviewAvailable",
+
+ // When the image response thumbnail is displayed in the UI.
+ RESPONSE_IMAGE_THUMBNAIL_DISPLAYED:
+ "NetMonitor:ResponseImageThumbnailAvailable",
+
+ // When a tab is selected in the NetworkDetailsView and subsequently rendered.
+ TAB_UPDATED: "NetMonitor:TabUpdated",
+
+ // Fired when Sidebar has finished being populated.
+ SIDEBAR_POPULATED: "NetMonitor:SidebarPopulated",
+
+ // Fired when NetworkDetailsView has finished being populated.
+ NETWORKDETAILSVIEW_POPULATED: "NetMonitor:NetworkDetailsViewPopulated",
+
+ // Fired when CustomRequestView has finished being populated.
+ CUSTOMREQUESTVIEW_POPULATED: "NetMonitor:CustomRequestViewPopulated",
+
+ // Fired when charts have been displayed in the PerformanceStatisticsView.
+ PLACEHOLDER_CHARTS_DISPLAYED: "NetMonitor:PlaceholderChartsDisplayed",
+ PRIMED_CACHE_CHART_DISPLAYED: "NetMonitor:PrimedChartsDisplayed",
+ EMPTY_CACHE_CHART_DISPLAYED: "NetMonitor:EmptyChartsDisplayed",
+
+ // Fired once the NetMonitorController establishes a connection to the debug
+ // target.
+ CONNECTED: "connected",
+};
+
+exports.EVENTS = EVENTS;
diff --git a/devtools/client/netmonitor/moz.build b/devtools/client/netmonitor/moz.build
index ca3d10fc15ca..e2c4288a7c30 100644
--- a/devtools/client/netmonitor/moz.build
+++ b/devtools/client/netmonitor/moz.build
@@ -8,12 +8,14 @@ DIRS += [
]
DevToolsModules(
+ 'events.js',
'filter-predicates.js',
'l10n.js',
'panel.js',
'prefs.js',
'request-utils.js',
'requests-menu-view.js',
+ 'sort-predicates.js',
)
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
diff --git a/devtools/client/netmonitor/netmonitor-controller.js b/devtools/client/netmonitor/netmonitor-controller.js
index 733db8454c2c..a47c0f6f71f3 100644
--- a/devtools/client/netmonitor/netmonitor-controller.js
+++ b/devtools/client/netmonitor/netmonitor-controller.js
@@ -9,89 +9,6 @@
var { utils: Cu } = Components;
-// The panel's window global is an EventEmitter firing the following events:
-const EVENTS = {
- // When the monitored target begins and finishes navigating.
- TARGET_WILL_NAVIGATE: "NetMonitor:TargetWillNavigate",
- TARGET_DID_NAVIGATE: "NetMonitor:TargetNavigate",
-
- // When a network or timeline event is received.
- // See https://developer.mozilla.org/docs/Tools/Web_Console/remoting for
- // more information about what each packet is supposed to deliver.
- NETWORK_EVENT: "NetMonitor:NetworkEvent",
- TIMELINE_EVENT: "NetMonitor:TimelineEvent",
-
- // When a network event is added to the view
- REQUEST_ADDED: "NetMonitor:RequestAdded",
-
- // When request headers begin and finish receiving.
- UPDATING_REQUEST_HEADERS: "NetMonitor:NetworkEventUpdating:RequestHeaders",
- RECEIVED_REQUEST_HEADERS: "NetMonitor:NetworkEventUpdated:RequestHeaders",
-
- // When request cookies begin and finish receiving.
- UPDATING_REQUEST_COOKIES: "NetMonitor:NetworkEventUpdating:RequestCookies",
- RECEIVED_REQUEST_COOKIES: "NetMonitor:NetworkEventUpdated:RequestCookies",
-
- // When request post data begins and finishes receiving.
- UPDATING_REQUEST_POST_DATA: "NetMonitor:NetworkEventUpdating:RequestPostData",
- RECEIVED_REQUEST_POST_DATA: "NetMonitor:NetworkEventUpdated:RequestPostData",
-
- // When security information begins and finishes receiving.
- UPDATING_SECURITY_INFO: "NetMonitor::NetworkEventUpdating:SecurityInfo",
- RECEIVED_SECURITY_INFO: "NetMonitor::NetworkEventUpdated:SecurityInfo",
-
- // When response headers begin and finish receiving.
- UPDATING_RESPONSE_HEADERS: "NetMonitor:NetworkEventUpdating:ResponseHeaders",
- RECEIVED_RESPONSE_HEADERS: "NetMonitor:NetworkEventUpdated:ResponseHeaders",
-
- // When response cookies begin and finish receiving.
- UPDATING_RESPONSE_COOKIES: "NetMonitor:NetworkEventUpdating:ResponseCookies",
- RECEIVED_RESPONSE_COOKIES: "NetMonitor:NetworkEventUpdated:ResponseCookies",
-
- // When event timings begin and finish receiving.
- UPDATING_EVENT_TIMINGS: "NetMonitor:NetworkEventUpdating:EventTimings",
- RECEIVED_EVENT_TIMINGS: "NetMonitor:NetworkEventUpdated:EventTimings",
-
- // When response content begins, updates and finishes receiving.
- STARTED_RECEIVING_RESPONSE: "NetMonitor:NetworkEventUpdating:ResponseStart",
- UPDATING_RESPONSE_CONTENT: "NetMonitor:NetworkEventUpdating:ResponseContent",
- RECEIVED_RESPONSE_CONTENT: "NetMonitor:NetworkEventUpdated:ResponseContent",
-
- // When the request post params are displayed in the UI.
- REQUEST_POST_PARAMS_DISPLAYED: "NetMonitor:RequestPostParamsAvailable",
-
- // When the response body is displayed in the UI.
- RESPONSE_BODY_DISPLAYED: "NetMonitor:ResponseBodyAvailable",
-
- // When the html response preview is displayed in the UI.
- RESPONSE_HTML_PREVIEW_DISPLAYED: "NetMonitor:ResponseHtmlPreviewAvailable",
-
- // When the image response thumbnail is displayed in the UI.
- RESPONSE_IMAGE_THUMBNAIL_DISPLAYED:
- "NetMonitor:ResponseImageThumbnailAvailable",
-
- // When a tab is selected in the NetworkDetailsView and subsequently rendered.
- TAB_UPDATED: "NetMonitor:TabUpdated",
-
- // Fired when Sidebar has finished being populated.
- SIDEBAR_POPULATED: "NetMonitor:SidebarPopulated",
-
- // Fired when NetworkDetailsView has finished being populated.
- NETWORKDETAILSVIEW_POPULATED: "NetMonitor:NetworkDetailsViewPopulated",
-
- // Fired when CustomRequestView has finished being populated.
- CUSTOMREQUESTVIEW_POPULATED: "NetMonitor:CustomRequestViewPopulated",
-
- // Fired when charts have been displayed in the PerformanceStatisticsView.
- PLACEHOLDER_CHARTS_DISPLAYED: "NetMonitor:PlaceholderChartsDisplayed",
- PRIMED_CACHE_CHART_DISPLAYED: "NetMonitor:PrimedChartsDisplayed",
- EMPTY_CACHE_CHART_DISPLAYED: "NetMonitor:EmptyChartsDisplayed",
-
- // Fired once the NetMonitorController establishes a connection to the debug
- // target.
- CONNECTED: "connected",
-};
-
// Descriptions for what this frontend is currently doing.
const ACTIVITY_TYPE = {
// Standing by and handling requests normally.
@@ -124,6 +41,7 @@ const Editor = require("devtools/client/sourceeditor/editor");
const {TimelineFront} = require("devtools/shared/fronts/timeline");
const {Task} = require("devtools/shared/task");
const {Prefs} = require("./prefs");
+const {EVENTS} = require("./events");
XPCOMUtils.defineConstant(this, "EVENTS", EVENTS);
XPCOMUtils.defineConstant(this, "ACTIVITY_TYPE", ACTIVITY_TYPE);
diff --git a/devtools/client/netmonitor/netmonitor-view.js b/devtools/client/netmonitor/netmonitor-view.js
index 5a7a96e6d1b6..355b1d628904 100644
--- a/devtools/client/netmonitor/netmonitor-view.js
+++ b/devtools/client/netmonitor/netmonitor-view.js
@@ -19,7 +19,11 @@ const { testing: isTesting } = require("devtools/shared/flags");
const {ViewHelpers, Heritage} = require("devtools/client/shared/widgets/view-helpers");
const {PluralForm} = require("devtools/shared/plural-form");
const {Filters} = require("./filter-predicates");
-const {getFormDataSections, formDataURI, writeHeaderText, getKeyWithEvent} = require("./request-utils");
+const {getFormDataSections,
+ formDataURI,
+ writeHeaderText,
+ getKeyWithEvent,
+ getUriHostPort} = require("./request-utils");
const {L10N} = require("./l10n");
const {RequestsMenuView} = require("./requests-menu-view");
@@ -1315,7 +1319,7 @@ NetworkDetailsView.prototype = {
setValue("#security-ciphersuite-value", securityInfo.cipherSuite);
// Host header
- let domain = NetMonitorView.RequestsMenu._getUriHostPort(url);
+ let domain = getUriHostPort(url);
let hostHeader = L10N.getFormatStr("netmonitor.security.hostHeader",
domain);
setValue("#security-info-host-header", hostHeader);
diff --git a/devtools/client/netmonitor/request-utils.js b/devtools/client/netmonitor/request-utils.js
index c019796b06ce..0332e320c3d5 100644
--- a/devtools/client/netmonitor/request-utils.js
+++ b/devtools/client/netmonitor/request-utils.js
@@ -3,6 +3,7 @@
const { Ci } = require("chrome");
const { KeyCodes } = require("devtools/client/shared/keycodes");
const { Task } = require("devtools/shared/task");
+const NetworkHelper = require("devtools/shared/webconsole/network-helper");
/**
* Helper method to get a wrapped function which can be bound to as
@@ -108,6 +109,48 @@ exports.writeHeaderText = function (headers) {
return headers.map(({name, value}) => name + ": " + value).join("\n");
};
+/**
+ * Helper for getting an abbreviated string for a mime type.
+ *
+ * @param string mimeType
+ * @return string
+ */
+exports.getAbbreviatedMimeType = function (mimeType) {
+ if (!mimeType) {
+ return "";
+ }
+ return (mimeType.split(";")[0].split("/")[1] || "").split("+")[0];
+};
+
+/**
+ * Helpers for getting details about an nsIURL.
+ *
+ * @param nsIURL | string url
+ * @return string
+ */
+exports.getUriNameWithQuery = function (url) {
+ if (!(url instanceof Ci.nsIURL)) {
+ url = NetworkHelper.nsIURL(url);
+ }
+
+ let name = NetworkHelper.convertToUnicode(
+ unescape(url.fileName || url.filePath || "/"));
+ let query = NetworkHelper.convertToUnicode(unescape(url.query));
+
+ return name + (query ? "?" + query : "");
+};
+
+exports.getUriHostPort = function (url) {
+ if (!(url instanceof Ci.nsIURL)) {
+ url = NetworkHelper.nsIURL(url);
+ }
+ return NetworkHelper.convertToUnicode(unescape(url.hostPort));
+};
+
+exports.getUriHost = function (url) {
+ return exports.getUriHostPort(url).replace(/:\d+$/, "");
+};
+
/**
* Convert a nsIContentPolicy constant to a display string
*/
diff --git a/devtools/client/netmonitor/requests-menu-view.js b/devtools/client/netmonitor/requests-menu-view.js
index 6ffe68d857aa..f8a25689edee 100644
--- a/devtools/client/netmonitor/requests-menu-view.js
+++ b/devtools/client/netmonitor/requests-menu-view.js
@@ -16,9 +16,17 @@ const {gDevTools} = require("devtools/client/framework/devtools");
const {Curl, CurlUtils} = require("devtools/client/shared/curl");
const {PluralForm} = require("devtools/shared/plural-form");
const {Filters, isFreetextMatch} = require("./filter-predicates");
-const {getFormDataSections, formDataURI, writeHeaderText, getKeyWithEvent,
- loadCauseString} = require("./request-utils");
+const {Sorters} = require("./sort-predicates");
const {L10N, WEBCONSOLE_L10N} = require("./l10n");
+const {getFormDataSections,
+ formDataURI,
+ writeHeaderText,
+ getKeyWithEvent,
+ getAbbreviatedMimeType,
+ getUriNameWithQuery,
+ getUriHostPort,
+ getUriHost,
+ loadCauseString} = require("./request-utils");
loader.lazyServiceGetter(this, "clipboardHelper",
"@mozilla.org/widget/clipboardhelper;1", "nsIClipboardHelper");
@@ -92,9 +100,6 @@ function RequestsMenuView() {
this._onSwap = this._onSwap.bind(this);
this._onResize = this._onResize.bind(this);
this._onScroll = this._onScroll.bind(this);
- this._byFile = this._byFile.bind(this);
- this._byDomain = this._byDomain.bind(this);
- this._byType = this._byType.bind(this);
this._onSecurityIconClick = this._onSecurityIconClick.bind(this);
}
@@ -122,7 +127,7 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
$("#requests-menu-contents").addEventListener("scroll", this._onScroll, true);
Prefs.filters.forEach(type => this.filterOn(type));
- this.sortContents(this._byTiming);
+ this.sortContents((a, b) => Sorters.waterfall(a.attachment, b.attachment));
this.allowFocusOnRightClick = true;
this.maintainSelectionVisible = true;
@@ -789,65 +794,65 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
switch (type) {
case "status":
if (direction == "ascending") {
- this.sortContents(this._byStatus);
+ this.sortContents((a, b) => Sorters.status(a.attachment, b.attachment));
} else {
- this.sortContents((a, b) => !this._byStatus(a, b));
+ this.sortContents((a, b) => -Sorters.status(a.attachment, b.attachment));
}
break;
case "method":
if (direction == "ascending") {
- this.sortContents(this._byMethod);
+ this.sortContents((a, b) => Sorters.method(a.attachment, b.attachment));
} else {
- this.sortContents((a, b) => !this._byMethod(a, b));
+ this.sortContents((a, b) => -Sorters.method(a.attachment, b.attachment));
}
break;
case "file":
if (direction == "ascending") {
- this.sortContents(this._byFile);
+ this.sortContents((a, b) => Sorters.file(a.attachment, b.attachment));
} else {
- this.sortContents((a, b) => !this._byFile(a, b));
+ this.sortContents((a, b) => -Sorters.file(a.attachment, b.attachment));
}
break;
case "domain":
if (direction == "ascending") {
- this.sortContents(this._byDomain);
+ this.sortContents((a, b) => Sorters.domain(a.attachment, b.attachment));
} else {
- this.sortContents((a, b) => !this._byDomain(a, b));
+ this.sortContents((a, b) => -Sorters.domain(a.attachment, b.attachment));
}
break;
case "cause":
if (direction == "ascending") {
- this.sortContents(this._byCause);
+ this.sortContents((a, b) => Sorters.cause(a.attachment, b.attachment));
} else {
- this.sortContents((a, b) => !this._byCause(a, b));
+ this.sortContents((a, b) => -Sorters.cause(a.attachment, b.attachment));
}
break;
case "type":
if (direction == "ascending") {
- this.sortContents(this._byType);
+ this.sortContents((a, b) => Sorters.type(a.attachment, b.attachment));
} else {
- this.sortContents((a, b) => !this._byType(a, b));
+ this.sortContents((a, b) => -Sorters.type(a.attachment, b.attachment));
}
break;
case "transferred":
if (direction == "ascending") {
- this.sortContents(this._byTransferred);
+ this.sortContents((a, b) => Sorters.transferred(a.attachment, b.attachment));
} else {
- this.sortContents((a, b) => !this._byTransferred(a, b));
+ this.sortContents((a, b) => -Sorters.transferred(a.attachment, b.attachment));
}
break;
case "size":
if (direction == "ascending") {
- this.sortContents(this._bySize);
+ this.sortContents((a, b) => Sorters.size(a.attachment, b.attachment));
} else {
- this.sortContents((a, b) => !this._bySize(a, b));
+ this.sortContents((a, b) => -Sorters.size(a.attachment, b.attachment));
}
break;
case "waterfall":
if (direction == "ascending") {
- this.sortContents(this._byTiming);
+ this.sortContents((a, b) => Sorters.waterfall(a.attachment, b.attachment));
} else {
- this.sortContents((a, b) => !this._byTiming(a, b));
+ this.sortContents((a, b) => -Sorters.waterfall(a.attachment, b.attachment));
}
break;
}
@@ -870,76 +875,6 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
this.refreshSummary();
},
- /**
- * Predicates used when sorting items.
- *
- * @param object aFirst
- * The first item used in the comparison.
- * @param object aSecond
- * The second item used in the comparison.
- * @return number
- * -1 to sort aFirst to a lower index than aSecond
- * 0 to leave aFirst and aSecond unchanged with respect to each other
- * 1 to sort aSecond to a lower index than aFirst
- */
- _byTiming: function ({ attachment: first }, { attachment: second }) {
- return first.startedMillis > second.startedMillis;
- },
-
- _byStatus: function ({ attachment: first }, { attachment: second }) {
- return first.status == second.status
- ? first.startedMillis > second.startedMillis
- : first.status > second.status;
- },
-
- _byMethod: function ({ attachment: first }, { attachment: second }) {
- return first.method == second.method
- ? first.startedMillis > second.startedMillis
- : first.method > second.method;
- },
-
- _byFile: function ({ attachment: first }, { attachment: second }) {
- let firstUrl = this._getUriNameWithQuery(first.url).toLowerCase();
- let secondUrl = this._getUriNameWithQuery(second.url).toLowerCase();
- return firstUrl == secondUrl
- ? first.startedMillis > second.startedMillis
- : firstUrl > secondUrl;
- },
-
- _byDomain: function ({ attachment: first }, { attachment: second }) {
- let firstDomain = this._getUriHostPort(first.url).toLowerCase();
- let secondDomain = this._getUriHostPort(second.url).toLowerCase();
- return firstDomain == secondDomain
- ? first.startedMillis > second.startedMillis
- : firstDomain > secondDomain;
- },
-
- _byCause: function ({ attachment: first }, { attachment: second }) {
- let firstCause = loadCauseString(first.cause.type);
- let secondCause = loadCauseString(second.cause.type);
-
- return firstCause == secondCause
- ? first.startedMillis > second.startedMillis
- : firstCause > secondCause;
- },
-
- _byType: function ({ attachment: first }, { attachment: second }) {
- let firstType = this._getAbbreviatedMimeType(first.mimeType).toLowerCase();
- let secondType = this._getAbbreviatedMimeType(second.mimeType).toLowerCase();
-
- return firstType == secondType
- ? first.startedMillis > second.startedMillis
- : firstType > secondType;
- },
-
- _byTransferred: function ({ attachment: first }, { attachment: second }) {
- return first.transferredSize > second.transferredSize;
- },
-
- _bySize: function ({ attachment: first }, { attachment: second }) {
- return first.contentSize > second.contentSize;
- },
-
/**
* Refreshes the status displayed in this container's footer, providing
* concise information about all requests.
@@ -1345,9 +1280,9 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
// User input may not make a well-formed url yet.
break;
}
- let nameWithQuery = this._getUriNameWithQuery(uri);
- let hostPort = this._getUriHostPort(uri);
- let host = this._getUriHost(uri);
+ let nameWithQuery = getUriNameWithQuery(uri);
+ let hostPort = getUriHostPort(uri);
+ let host = getUriHost(uri);
let unicodeUrl = NetworkHelper.convertToUnicode(unescape(uri.spec));
let file = $(".requests-menu-file", target);
@@ -1464,7 +1399,7 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
break;
}
case "mimeType": {
- let type = this._getAbbreviatedMimeType(value);
+ let type = getAbbreviatedMimeType(value);
let node = $(".requests-menu-type", target);
let text = CONTENT_MIME_TYPE_ABBREVIATIONS[type] || type;
node.setAttribute("value", text);
@@ -1993,48 +1928,6 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
}
},
- /**
- * Helpers for getting details about an nsIURL.
- *
- * @param nsIURL | string url
- * @return string
- */
- _getUriNameWithQuery: function (url) {
- if (!(url instanceof Ci.nsIURL)) {
- url = NetworkHelper.nsIURL(url);
- }
-
- let name = NetworkHelper.convertToUnicode(
- unescape(url.fileName || url.filePath || "/"));
- let query = NetworkHelper.convertToUnicode(unescape(url.query));
-
- return name + (query ? "?" + query : "");
- },
-
- _getUriHostPort: function (url) {
- if (!(url instanceof Ci.nsIURL)) {
- url = NetworkHelper.nsIURL(url);
- }
- return NetworkHelper.convertToUnicode(unescape(url.hostPort));
- },
-
- _getUriHost: function (url) {
- return this._getUriHostPort(url).replace(/:\d+$/, "");
- },
-
- /**
- * Helper for getting an abbreviated string for a mime type.
- *
- * @param string mimeType
- * @return string
- */
- _getAbbreviatedMimeType: function (mimeType) {
- if (!mimeType) {
- return "";
- }
- return (mimeType.split(";")[0].split("/")[1] || "").split("+")[0];
- },
-
/**
* Gets the total number of bytes representing the cumulated content size of
* a set of requests. Returns 0 for an empty set.
diff --git a/devtools/client/netmonitor/sort-predicates.js b/devtools/client/netmonitor/sort-predicates.js
new file mode 100644
index 000000000000..1ead67c22e3d
--- /dev/null
+++ b/devtools/client/netmonitor/sort-predicates.js
@@ -0,0 +1,92 @@
+"use strict";
+
+const { getAbbreviatedMimeType,
+ getUriNameWithQuery,
+ getUriHostPort,
+ loadCauseString } = require("./request-utils");
+
+/**
+ * Predicates used when sorting items.
+ *
+ * @param object first
+ * The first item used in the comparison.
+ * @param object second
+ * The second item used in the comparison.
+ * @return number
+ * <0 to sort first to a lower index than second
+ * =0 to leave first and second unchanged with respect to each other
+ * >0 to sort second to a lower index than first
+ */
+
+function waterfall(first, second) {
+ return first.startedMillis - second.startedMillis;
+}
+
+function status(first, second) {
+ return first.status == second.status
+ ? first.startedMillis - second.startedMillis
+ : first.status - second.status;
+}
+
+function method(first, second) {
+ if (first.method == second.method) {
+ return first.startedMillis - second.startedMillis;
+ }
+ return first.method > second.method ? 1 : -1;
+}
+
+function file(first, second) {
+ let firstUrl = getUriNameWithQuery(first.url).toLowerCase();
+ let secondUrl = getUriNameWithQuery(second.url).toLowerCase();
+ if (firstUrl == secondUrl) {
+ return first.startedMillis - second.startedMillis;
+ }
+ return firstUrl > secondUrl ? 1 : -1;
+}
+
+function domain(first, second) {
+ let firstDomain = getUriHostPort(first.url).toLowerCase();
+ let secondDomain = getUriHostPort(second.url).toLowerCase();
+ if (firstDomain == secondDomain) {
+ return first.startedMillis - second.startedMillis;
+ }
+ return firstDomain > secondDomain ? 1 : -1;
+}
+
+function cause(first, second) {
+ let firstCause = loadCauseString(first.cause.type);
+ let secondCause = loadCauseString(second.cause.type);
+ if (firstCause == secondCause) {
+ return first.startedMillis - second.startedMillis;
+ }
+ return firstCause > secondCause ? 1 : -1;
+}
+
+function type(first, second) {
+ let firstType = getAbbreviatedMimeType(first.mimeType).toLowerCase();
+ let secondType = getAbbreviatedMimeType(second.mimeType).toLowerCase();
+ if (firstType == secondType) {
+ return first.startedMillis - second.startedMillis;
+ }
+ return firstType > secondType ? 1 : -1;
+}
+
+function transferred(first, second) {
+ return first.transferredSize - second.transferredSize;
+}
+
+function size(first, second) {
+ return first.contentSize - second.contentSize;
+}
+
+exports.Sorters = {
+ status,
+ method,
+ file,
+ domain,
+ cause,
+ type,
+ transferred,
+ size,
+ waterfall,
+};
diff --git a/devtools/client/shared/components/moz.build b/devtools/client/shared/components/moz.build
index fc573ef4bb48..0d67e90b553a 100644
--- a/devtools/client/shared/components/moz.build
+++ b/devtools/client/shared/components/moz.build
@@ -16,6 +16,7 @@ DevToolsModules(
'h-split-box.js',
'notification-box.css',
'notification-box.js',
+ 'search-box.js',
'sidebar-toggle.css',
'sidebar-toggle.js',
'stack-trace.js',
diff --git a/devtools/client/shared/components/search-box.js b/devtools/client/shared/components/search-box.js
new file mode 100644
index 000000000000..2eaaccb5fe9b
--- /dev/null
+++ b/devtools/client/shared/components/search-box.js
@@ -0,0 +1,107 @@
+/* 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/. */
+
+/* global window */
+
+"use strict";
+
+const { DOM: dom, createClass, PropTypes } = require("devtools/client/shared/vendor/react");
+const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
+
+/**
+ * A generic search box component for use across devtools
+ */
+module.exports = createClass({
+ displayName: "SearchBox",
+
+ propTypes: {
+ delay: PropTypes.number,
+ keyShortcut: PropTypes.string,
+ onChange: PropTypes.func,
+ placeholder: PropTypes.string,
+ type: PropTypes.string
+ },
+
+ getInitialState() {
+ return {
+ value: ""
+ };
+ },
+
+ componentDidMount() {
+ if (!this.props.keyShortcut) {
+ return;
+ }
+
+ this.shortcuts = new KeyShortcuts({
+ window
+ });
+ this.shortcuts.on(this.props.keyShortcut, (name, event) => {
+ event.preventDefault();
+ this.refs.input.focus();
+ });
+ },
+
+ componentWillUnmount() {
+ this.shortcuts.destroy();
+ // Clean up an existing timeout.
+ if (this.searchTimeout) {
+ clearTimeout(this.searchTimeout);
+ }
+ },
+
+ onChange() {
+ if (this.state.value !== this.refs.input.value) {
+ this.setState({ value: this.refs.input.value });
+ }
+
+ if (!this.props.delay) {
+ this.props.onChange(this.state.value);
+ return;
+ }
+
+ // Clean up an existing timeout before creating a new one.
+ if (this.searchTimeout) {
+ clearTimeout(this.searchTimeout);
+ }
+
+ // Execute the search after a timeout. It makes the UX
+ // smoother if the user is typing quickly.
+ this.searchTimeout = setTimeout(() => {
+ this.searchTimeout = null;
+ this.props.onChange(this.state.value);
+ }, this.props.delay);
+ },
+
+ onClearButtonClick() {
+ this.refs.input.value = "";
+ this.onChange();
+ },
+
+ render() {
+ let { type = "search", placeholder } = this.props;
+ let { value } = this.state;
+ let divClassList = ["devtools-searchbox", "has-clear-btn"];
+ let inputClassList = [`devtools-${type}input`];
+
+ if (value !== "") {
+ inputClassList.push("filled");
+ }
+ return dom.div(
+ { className: divClassList.join(" ") },
+ dom.input({
+ className: inputClassList.join(" "),
+ onChange: this.onChange,
+ placeholder,
+ ref: "input",
+ value
+ }),
+ dom.button({
+ className: "devtools-searchinput-clear",
+ hidden: value == "",
+ onClick: this.onClearButtonClick
+ })
+ );
+ }
+});
diff --git a/devtools/client/webconsole/new-console-output/new-console-output-wrapper.js b/devtools/client/webconsole/new-console-output/new-console-output-wrapper.js
index 3e4912c2d3f4..db00dbe2f428 100644
--- a/devtools/client/webconsole/new-console-output/new-console-output-wrapper.js
+++ b/devtools/client/webconsole/new-console-output/new-console-output-wrapper.js
@@ -72,34 +72,40 @@ NewConsoleOutputWrapper.prototype = {
this.body = ReactDOM.render(provider, this.parentNode);
},
- dispatchMessageAdd: function(message, waitForResponse) {
- let action = actions.messageAdd(message);
- let messageId = action.message.get("id");
- batchedMessageAdd(action);
- // Wait for the message to render to resolve with the DOM node.
- // This is just for backwards compatibility with old tests, and should
- // be removed once it's not needed anymore.
- if (waitForResponse) {
- return new Promise(resolve => {
- let jsterm = this.jsterm;
- jsterm.hud.on("new-messages", function onThisMessage(e, messages) {
- for (let m of messages) {
- if (m.messageId == messageId) {
- resolve(m.node);
- jsterm.hud.off("new-messages", onThisMessage);
- return;
- }
+ dispatchMessageAdd: function (message, waitForResponse) {
+ let action = actions.messageAdd(message);
+ batchedMessageAdd(action);
+
+ // Wait for the message to render to resolve with the DOM node.
+ // This is just for backwards compatibility with old tests, and should
+ // be removed once it's not needed anymore.
+ // Can only wait for response if the action contains a valid message.
+ if (waitForResponse && action.message) {
+ let messageId = action.message.get("id");
+ return new Promise(resolve => {
+ let jsterm = this.jsterm;
+ jsterm.hud.on("new-messages", function onThisMessage(e, messages) {
+ for (let m of messages) {
+ if (m.messageId == messageId) {
+ resolve(m.node);
+ jsterm.hud.off("new-messages", onThisMessage);
+ return;
}
- });
+ }
});
- }
+ });
+ }
+
+ return Promise.resolve();
},
- dispatchMessagesAdd: function(messages) {
+
+ dispatchMessagesAdd: function (messages) {
const batchedActions = messages.map(message => actions.messageAdd(message));
store.dispatch(actions.batchActions(batchedActions));
},
- dispatchMessagesClear: function() {
+
+ dispatchMessagesClear: function () {
store.dispatch(actions.messagesClear());
},
};
diff --git a/devtools/shared/css/generated/generate-properties-db.js b/devtools/shared/css/generated/generate-properties-db.js
index a02118a6adb4..ad8dfb0ab626 100644
--- a/devtools/shared/css/generated/generate-properties-db.js
+++ b/devtools/shared/css/generated/generate-properties-db.js
@@ -11,15 +11,17 @@
var {require} = Components.utils.import("resource://devtools/shared/Loader.jsm", {});
var {generateCssProperties} = require("devtools/server/actors/css-properties");
+// xpcshell can output extra information, so place some delimiter text between
+// the output of the css properties database.
+dump("DEVTOOLS_CSS_DB_DELIMITER");
+
// Output JSON
dump(JSON.stringify({
cssProperties: cssProperties(),
pseudoElements: pseudoElements()
}));
-// In a debug build, xpcshell might print extra debugging information,
-// so we emit a trailing newline and then arrange to just read a
-// single (long) line of JSON from the output.
-dump("\n");
+
+dump("DEVTOOLS_CSS_DB_DELIMITER");
/*
* A list of CSS Properties and their various characteristics. This is used on the
diff --git a/devtools/shared/css/generated/mach_commands.py b/devtools/shared/css/generated/mach_commands.py
index 2a8b9ca3d680..4d6016276aa7 100644
--- a/devtools/shared/css/generated/mach_commands.py
+++ b/devtools/shared/css/generated/mach_commands.py
@@ -3,11 +3,9 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
"""
-This script implements the `mach devtools-css-db` command. It runs the C preprocessor
-on the CSS properties header file to get the list of preferences associated with
-a specific property, and it runs an xpcshell script that uses inIDOMUtils to query
-the CSS properties used by the browser. This information is used to generate the
-properties-db.js file.
+This script implements the `mach devtools-css-db` command. It runs an xpcshell script
+that uses inIDOMUtils to query the CSS properties used by the browser. This information
+is used to generate the properties-db.js file.
"""
import json
@@ -15,7 +13,6 @@ import os
import sys
import string
import subprocess
-from mozbuild import shellutil
from mozbuild.base import (
MozbuildObject,
MachCommandBase,
@@ -42,46 +39,12 @@ class MachCommands(MachCommandBase):
"""Generate the static css properties database for devtools and write it to file."""
print("Re-generating the css properties database...")
- preferences = self.get_preferences()
db = self.get_properties_db_from_xpcshell()
self.output_template({
- 'preferences': stringify(preferences),
'cssProperties': stringify(db['cssProperties']),
'pseudoElements': stringify(db['pseudoElements'])})
- def get_preferences(self):
- """Get all of the preferences associated with enabling and disabling a property."""
- # Build the command to run the preprocessor on PythonCSSProps.h
- headerPath = resolve_path(self.topsrcdir, 'layout/style/PythonCSSProps.h')
-
- cpp = self.substs['CPP']
-
- if not cpp:
- print("Unable to find the cpp program. Please do a full, non-artifact")
- print("build and try this again.")
- sys.exit(1)
-
- if type(cpp) is list:
- cmd = cpp
- else:
- cmd = shellutil.split(cpp)
- cmd += shellutil.split(self.substs['ACDEFINES'])
- cmd.append(headerPath)
-
- # The preprocessed list takes the following form:
- # [ (name, prop, id, flags, pref, proptype), ... ]
- preprocessed = eval(subprocess.check_output(cmd))
-
- # Map this list
- # (name, prop, id, flags, pref, proptype) => (name, pref)
- preferences = [
- (name, pref)
- for name, prop, id, flags, pref, proptype in preprocessed
- if 'CSS_PROPERTY_INTERNAL' not in flags]
-
- return preferences
-
def get_properties_db_from_xpcshell(self):
"""Generate the static css properties db for devtools from an xpcshell script."""
build = MozbuildObject.from_environment()
@@ -103,9 +66,9 @@ class MachCommands(MachCommandBase):
contents = subprocess.check_output([xpcshell_path, '-g', gre_path,
'-a', browser_path, script_path],
env = sub_env)
- # Extract just the first line of output, since a debug-build
- # xpcshell might emit extra output that we don't want.
- contents = contents.split('\n')[0]
+ # Extract just the output between the delimiters as the xpcshell output can
+ # have extra output that we don't want.
+ contents = contents.split('DEVTOOLS_CSS_DB_DELIMITER')[1]
return json.loads(contents)
diff --git a/devtools/shared/css/generated/properties-db.js b/devtools/shared/css/generated/properties-db.js
index 5949fc214c94..2dd94caa05b2 100644
--- a/devtools/shared/css/generated/properties-db.js
+++ b/devtools/shared/css/generated/properties-db.js
@@ -9302,1834 +9302,3 @@ exports.PSEUDO_ELEMENTS = [
":placeholder",
":-moz-color-swatch"
];
-
-/**
- * A list of the preferences keys for whether a CSS property is enabled or not. This is
- * exposed for testing purposes.
- */
-exports.PREFERENCES = [
- [
- "align-content",
- ""
- ],
- [
- "align-items",
- ""
- ],
- [
- "align-self",
- ""
- ],
- [
- "all",
- "layout.css.all-shorthand.enabled"
- ],
- [
- "animation",
- ""
- ],
- [
- "animation-delay",
- ""
- ],
- [
- "animation-direction",
- ""
- ],
- [
- "animation-duration",
- ""
- ],
- [
- "animation-fill-mode",
- ""
- ],
- [
- "animation-iteration-count",
- ""
- ],
- [
- "animation-name",
- ""
- ],
- [
- "animation-play-state",
- ""
- ],
- [
- "animation-timing-function",
- ""
- ],
- [
- "-moz-appearance",
- ""
- ],
- [
- "backface-visibility",
- ""
- ],
- [
- "background",
- ""
- ],
- [
- "background-attachment",
- ""
- ],
- [
- "background-blend-mode",
- "layout.css.background-blend-mode.enabled"
- ],
- [
- "background-clip",
- ""
- ],
- [
- "background-color",
- ""
- ],
- [
- "background-image",
- ""
- ],
- [
- "background-origin",
- ""
- ],
- [
- "background-position",
- ""
- ],
- [
- "background-position-x",
- ""
- ],
- [
- "background-position-y",
- ""
- ],
- [
- "background-repeat",
- ""
- ],
- [
- "background-size",
- ""
- ],
- [
- "-moz-binding",
- ""
- ],
- [
- "block-size",
- ""
- ],
- [
- "border",
- ""
- ],
- [
- "border-block-end",
- ""
- ],
- [
- "border-block-end-color",
- ""
- ],
- [
- "border-block-end-style",
- ""
- ],
- [
- "border-block-end-width",
- ""
- ],
- [
- "border-block-start",
- ""
- ],
- [
- "border-block-start-color",
- ""
- ],
- [
- "border-block-start-style",
- ""
- ],
- [
- "border-block-start-width",
- ""
- ],
- [
- "border-bottom",
- ""
- ],
- [
- "border-bottom-color",
- ""
- ],
- [
- "-moz-border-bottom-colors",
- ""
- ],
- [
- "border-bottom-left-radius",
- ""
- ],
- [
- "border-bottom-right-radius",
- ""
- ],
- [
- "border-bottom-style",
- ""
- ],
- [
- "border-bottom-width",
- ""
- ],
- [
- "border-collapse",
- ""
- ],
- [
- "border-color",
- ""
- ],
- [
- "border-image",
- ""
- ],
- [
- "border-image-outset",
- ""
- ],
- [
- "border-image-repeat",
- ""
- ],
- [
- "border-image-slice",
- ""
- ],
- [
- "border-image-source",
- ""
- ],
- [
- "border-image-width",
- ""
- ],
- [
- "border-inline-end",
- ""
- ],
- [
- "border-inline-end-color",
- ""
- ],
- [
- "border-inline-end-style",
- ""
- ],
- [
- "border-inline-end-width",
- ""
- ],
- [
- "border-inline-start",
- ""
- ],
- [
- "border-inline-start-color",
- ""
- ],
- [
- "border-inline-start-style",
- ""
- ],
- [
- "border-inline-start-width",
- ""
- ],
- [
- "border-left",
- ""
- ],
- [
- "border-left-color",
- ""
- ],
- [
- "-moz-border-left-colors",
- ""
- ],
- [
- "border-left-style",
- ""
- ],
- [
- "border-left-width",
- ""
- ],
- [
- "border-radius",
- ""
- ],
- [
- "border-right",
- ""
- ],
- [
- "border-right-color",
- ""
- ],
- [
- "-moz-border-right-colors",
- ""
- ],
- [
- "border-right-style",
- ""
- ],
- [
- "border-right-width",
- ""
- ],
- [
- "border-spacing",
- ""
- ],
- [
- "border-style",
- ""
- ],
- [
- "border-top",
- ""
- ],
- [
- "border-top-color",
- ""
- ],
- [
- "-moz-border-top-colors",
- ""
- ],
- [
- "border-top-left-radius",
- ""
- ],
- [
- "border-top-right-radius",
- ""
- ],
- [
- "border-top-style",
- ""
- ],
- [
- "border-top-width",
- ""
- ],
- [
- "border-width",
- ""
- ],
- [
- "bottom",
- ""
- ],
- [
- "-moz-box-align",
- ""
- ],
- [
- "box-decoration-break",
- "layout.css.box-decoration-break.enabled"
- ],
- [
- "-moz-box-direction",
- ""
- ],
- [
- "-moz-box-flex",
- ""
- ],
- [
- "-moz-box-ordinal-group",
- ""
- ],
- [
- "-moz-box-orient",
- ""
- ],
- [
- "-moz-box-pack",
- ""
- ],
- [
- "box-shadow",
- ""
- ],
- [
- "box-sizing",
- ""
- ],
- [
- "caption-side",
- ""
- ],
- [
- "clear",
- ""
- ],
- [
- "clip",
- ""
- ],
- [
- "clip-path",
- ""
- ],
- [
- "clip-rule",
- ""
- ],
- [
- "color",
- ""
- ],
- [
- "color-adjust",
- "layout.css.color-adjust.enabled"
- ],
- [
- "color-interpolation",
- ""
- ],
- [
- "color-interpolation-filters",
- ""
- ],
- [
- "column-count",
- ""
- ],
- [
- "column-fill",
- ""
- ],
- [
- "column-gap",
- ""
- ],
- [
- "column-rule",
- ""
- ],
- [
- "column-rule-color",
- ""
- ],
- [
- "column-rule-style",
- ""
- ],
- [
- "column-rule-width",
- ""
- ],
- [
- "column-width",
- ""
- ],
- [
- "columns",
- ""
- ],
- [
- "contain",
- "layout.css.contain.enabled"
- ],
- [
- "content",
- ""
- ],
- [
- "counter-increment",
- ""
- ],
- [
- "counter-reset",
- ""
- ],
- [
- "cursor",
- ""
- ],
- [
- "direction",
- ""
- ],
- [
- "display",
- ""
- ],
- [
- "dominant-baseline",
- ""
- ],
- [
- "empty-cells",
- ""
- ],
- [
- "fill",
- ""
- ],
- [
- "fill-opacity",
- ""
- ],
- [
- "fill-rule",
- ""
- ],
- [
- "filter",
- ""
- ],
- [
- "flex",
- ""
- ],
- [
- "flex-basis",
- ""
- ],
- [
- "flex-direction",
- ""
- ],
- [
- "flex-flow",
- ""
- ],
- [
- "flex-grow",
- ""
- ],
- [
- "flex-shrink",
- ""
- ],
- [
- "flex-wrap",
- ""
- ],
- [
- "float",
- ""
- ],
- [
- "-moz-float-edge",
- ""
- ],
- [
- "flood-color",
- ""
- ],
- [
- "flood-opacity",
- ""
- ],
- [
- "font",
- ""
- ],
- [
- "font-family",
- ""
- ],
- [
- "font-feature-settings",
- ""
- ],
- [
- "font-kerning",
- ""
- ],
- [
- "font-language-override",
- ""
- ],
- [
- "font-size",
- ""
- ],
- [
- "font-size-adjust",
- ""
- ],
- [
- "font-stretch",
- ""
- ],
- [
- "font-style",
- ""
- ],
- [
- "font-synthesis",
- ""
- ],
- [
- "font-variant",
- ""
- ],
- [
- "font-variant-alternates",
- ""
- ],
- [
- "font-variant-caps",
- ""
- ],
- [
- "font-variant-east-asian",
- ""
- ],
- [
- "font-variant-ligatures",
- ""
- ],
- [
- "font-variant-numeric",
- ""
- ],
- [
- "font-variant-position",
- ""
- ],
- [
- "font-weight",
- ""
- ],
- [
- "-moz-force-broken-image-icon",
- ""
- ],
- [
- "grid",
- "layout.css.grid.enabled"
- ],
- [
- "grid-area",
- "layout.css.grid.enabled"
- ],
- [
- "grid-auto-columns",
- "layout.css.grid.enabled"
- ],
- [
- "grid-auto-flow",
- "layout.css.grid.enabled"
- ],
- [
- "grid-auto-rows",
- "layout.css.grid.enabled"
- ],
- [
- "grid-column",
- "layout.css.grid.enabled"
- ],
- [
- "grid-column-end",
- "layout.css.grid.enabled"
- ],
- [
- "grid-column-gap",
- "layout.css.grid.enabled"
- ],
- [
- "grid-column-start",
- "layout.css.grid.enabled"
- ],
- [
- "grid-gap",
- "layout.css.grid.enabled"
- ],
- [
- "grid-row",
- "layout.css.grid.enabled"
- ],
- [
- "grid-row-end",
- "layout.css.grid.enabled"
- ],
- [
- "grid-row-gap",
- "layout.css.grid.enabled"
- ],
- [
- "grid-row-start",
- "layout.css.grid.enabled"
- ],
- [
- "grid-template",
- "layout.css.grid.enabled"
- ],
- [
- "grid-template-areas",
- "layout.css.grid.enabled"
- ],
- [
- "grid-template-columns",
- "layout.css.grid.enabled"
- ],
- [
- "grid-template-rows",
- "layout.css.grid.enabled"
- ],
- [
- "height",
- ""
- ],
- [
- "hyphens",
- ""
- ],
- [
- "initial-letter",
- "layout.css.initial-letter.enabled"
- ],
- [
- "image-orientation",
- "layout.css.image-orientation.enabled"
- ],
- [
- "-moz-image-region",
- ""
- ],
- [
- "image-rendering",
- ""
- ],
- [
- "ime-mode",
- ""
- ],
- [
- "inline-size",
- ""
- ],
- [
- "isolation",
- "layout.css.isolation.enabled"
- ],
- [
- "justify-content",
- ""
- ],
- [
- "justify-items",
- ""
- ],
- [
- "justify-self",
- ""
- ],
- [
- "left",
- ""
- ],
- [
- "letter-spacing",
- ""
- ],
- [
- "lighting-color",
- ""
- ],
- [
- "line-height",
- ""
- ],
- [
- "list-style",
- ""
- ],
- [
- "list-style-image",
- ""
- ],
- [
- "list-style-position",
- ""
- ],
- [
- "list-style-type",
- ""
- ],
- [
- "margin",
- ""
- ],
- [
- "margin-block-end",
- ""
- ],
- [
- "margin-block-start",
- ""
- ],
- [
- "margin-bottom",
- ""
- ],
- [
- "margin-inline-end",
- ""
- ],
- [
- "margin-inline-start",
- ""
- ],
- [
- "margin-left",
- ""
- ],
- [
- "margin-right",
- ""
- ],
- [
- "margin-top",
- ""
- ],
- [
- "marker",
- ""
- ],
- [
- "marker-end",
- ""
- ],
- [
- "marker-mid",
- ""
- ],
- [
- "marker-offset",
- ""
- ],
- [
- "marker-start",
- ""
- ],
- [
- "mask",
- ""
- ],
- [
- "mask-clip",
- ""
- ],
- [
- "mask-composite",
- ""
- ],
- [
- "mask-image",
- ""
- ],
- [
- "mask-mode",
- ""
- ],
- [
- "mask-origin",
- ""
- ],
- [
- "mask-position",
- ""
- ],
- [
- "mask-position-x",
- ""
- ],
- [
- "mask-position-y",
- ""
- ],
- [
- "mask-repeat",
- ""
- ],
- [
- "mask-size",
- ""
- ],
- [
- "mask-type",
- ""
- ],
- [
- "max-block-size",
- ""
- ],
- [
- "max-height",
- ""
- ],
- [
- "max-inline-size",
- ""
- ],
- [
- "max-width",
- ""
- ],
- [
- "min-block-size",
- ""
- ],
- [
- "min-height",
- ""
- ],
- [
- "min-inline-size",
- ""
- ],
- [
- "min-width",
- ""
- ],
- [
- "mix-blend-mode",
- "layout.css.mix-blend-mode.enabled"
- ],
- [
- "object-fit",
- "layout.css.object-fit-and-position.enabled"
- ],
- [
- "object-position",
- "layout.css.object-fit-and-position.enabled"
- ],
- [
- "offset-block-end",
- ""
- ],
- [
- "offset-block-start",
- ""
- ],
- [
- "offset-inline-end",
- ""
- ],
- [
- "offset-inline-start",
- ""
- ],
- [
- "opacity",
- ""
- ],
- [
- "order",
- ""
- ],
- [
- "-moz-orient",
- ""
- ],
- [
- "-moz-osx-font-smoothing",
- "layout.css.osx-font-smoothing.enabled"
- ],
- [
- "outline",
- ""
- ],
- [
- "outline-color",
- ""
- ],
- [
- "outline-offset",
- ""
- ],
- [
- "-moz-outline-radius",
- ""
- ],
- [
- "-moz-outline-radius-bottomleft",
- ""
- ],
- [
- "-moz-outline-radius-bottomright",
- ""
- ],
- [
- "-moz-outline-radius-topleft",
- ""
- ],
- [
- "-moz-outline-radius-topright",
- ""
- ],
- [
- "outline-style",
- ""
- ],
- [
- "outline-width",
- ""
- ],
- [
- "overflow",
- ""
- ],
- [
- "overflow-clip-box",
- "layout.css.overflow-clip-box.enabled"
- ],
- [
- "overflow-x",
- ""
- ],
- [
- "overflow-y",
- ""
- ],
- [
- "padding",
- ""
- ],
- [
- "padding-block-end",
- ""
- ],
- [
- "padding-block-start",
- ""
- ],
- [
- "padding-bottom",
- ""
- ],
- [
- "padding-inline-end",
- ""
- ],
- [
- "padding-inline-start",
- ""
- ],
- [
- "padding-left",
- ""
- ],
- [
- "padding-right",
- ""
- ],
- [
- "padding-top",
- ""
- ],
- [
- "page-break-after",
- ""
- ],
- [
- "page-break-before",
- ""
- ],
- [
- "page-break-inside",
- ""
- ],
- [
- "paint-order",
- "svg.paint-order.enabled"
- ],
- [
- "perspective",
- ""
- ],
- [
- "perspective-origin",
- ""
- ],
- [
- "pointer-events",
- ""
- ],
- [
- "position",
- ""
- ],
- [
- "quotes",
- ""
- ],
- [
- "resize",
- ""
- ],
- [
- "right",
- ""
- ],
- [
- "ruby-align",
- ""
- ],
- [
- "ruby-position",
- ""
- ],
- [
- "scroll-behavior",
- "layout.css.scroll-behavior.property-enabled"
- ],
- [
- "scroll-snap-coordinate",
- "layout.css.scroll-snap.enabled"
- ],
- [
- "scroll-snap-destination",
- "layout.css.scroll-snap.enabled"
- ],
- [
- "scroll-snap-points-x",
- "layout.css.scroll-snap.enabled"
- ],
- [
- "scroll-snap-points-y",
- "layout.css.scroll-snap.enabled"
- ],
- [
- "scroll-snap-type",
- "layout.css.scroll-snap.enabled"
- ],
- [
- "scroll-snap-type-x",
- "layout.css.scroll-snap.enabled"
- ],
- [
- "scroll-snap-type-y",
- "layout.css.scroll-snap.enabled"
- ],
- [
- "shape-outside",
- "layout.css.shape-outside.enabled"
- ],
- [
- "shape-rendering",
- ""
- ],
- [
- "-moz-stack-sizing",
- ""
- ],
- [
- "stop-color",
- ""
- ],
- [
- "stop-opacity",
- ""
- ],
- [
- "stroke",
- ""
- ],
- [
- "stroke-dasharray",
- ""
- ],
- [
- "stroke-dashoffset",
- ""
- ],
- [
- "stroke-linecap",
- ""
- ],
- [
- "stroke-linejoin",
- ""
- ],
- [
- "stroke-miterlimit",
- ""
- ],
- [
- "stroke-opacity",
- ""
- ],
- [
- "stroke-width",
- ""
- ],
- [
- "-moz-tab-size",
- ""
- ],
- [
- "table-layout",
- ""
- ],
- [
- "text-align",
- ""
- ],
- [
- "text-align-last",
- ""
- ],
- [
- "text-anchor",
- ""
- ],
- [
- "text-combine-upright",
- "layout.css.text-combine-upright.enabled"
- ],
- [
- "text-decoration",
- ""
- ],
- [
- "text-decoration-color",
- ""
- ],
- [
- "text-decoration-line",
- ""
- ],
- [
- "text-decoration-style",
- ""
- ],
- [
- "text-emphasis",
- ""
- ],
- [
- "text-emphasis-color",
- ""
- ],
- [
- "text-emphasis-position",
- ""
- ],
- [
- "text-emphasis-style",
- ""
- ],
- [
- "-webkit-text-fill-color",
- "layout.css.prefixes.webkit"
- ],
- [
- "text-indent",
- ""
- ],
- [
- "text-orientation",
- ""
- ],
- [
- "text-overflow",
- ""
- ],
- [
- "text-rendering",
- ""
- ],
- [
- "text-shadow",
- ""
- ],
- [
- "-moz-text-size-adjust",
- ""
- ],
- [
- "-webkit-text-stroke",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-text-stroke-color",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-text-stroke-width",
- "layout.css.prefixes.webkit"
- ],
- [
- "text-transform",
- ""
- ],
- [
- "top",
- ""
- ],
- [
- "touch-action",
- "layout.css.touch_action.enabled"
- ],
- [
- "transform",
- ""
- ],
- [
- "-moz-transform",
- "layout.css.prefixes.transforms"
- ],
- [
- "transform-box",
- "svg.transform-box.enabled"
- ],
- [
- "transform-origin",
- ""
- ],
- [
- "transform-style",
- ""
- ],
- [
- "transition",
- ""
- ],
- [
- "transition-delay",
- ""
- ],
- [
- "transition-duration",
- ""
- ],
- [
- "transition-property",
- ""
- ],
- [
- "transition-timing-function",
- ""
- ],
- [
- "unicode-bidi",
- ""
- ],
- [
- "-moz-user-focus",
- ""
- ],
- [
- "-moz-user-input",
- ""
- ],
- [
- "-moz-user-modify",
- ""
- ],
- [
- "-moz-user-select",
- ""
- ],
- [
- "vector-effect",
- ""
- ],
- [
- "vertical-align",
- ""
- ],
- [
- "visibility",
- ""
- ],
- [
- "white-space",
- ""
- ],
- [
- "width",
- ""
- ],
- [
- "will-change",
- ""
- ],
- [
- "-moz-window-dragging",
- ""
- ],
- [
- "word-break",
- ""
- ],
- [
- "word-spacing",
- ""
- ],
- [
- "overflow-wrap",
- ""
- ],
- [
- "writing-mode",
- ""
- ],
- [
- "z-index",
- ""
- ],
- [
- "word-wrap",
- ""
- ],
- [
- "-moz-transform-origin",
- "layout.css.prefixes.transforms"
- ],
- [
- "-moz-perspective-origin",
- "layout.css.prefixes.transforms"
- ],
- [
- "-moz-perspective",
- "layout.css.prefixes.transforms"
- ],
- [
- "-moz-transform-style",
- "layout.css.prefixes.transforms"
- ],
- [
- "-moz-backface-visibility",
- "layout.css.prefixes.transforms"
- ],
- [
- "-moz-border-image",
- "layout.css.prefixes.border-image"
- ],
- [
- "-moz-transition",
- "layout.css.prefixes.transitions"
- ],
- [
- "-moz-transition-delay",
- "layout.css.prefixes.transitions"
- ],
- [
- "-moz-transition-duration",
- "layout.css.prefixes.transitions"
- ],
- [
- "-moz-transition-property",
- "layout.css.prefixes.transitions"
- ],
- [
- "-moz-transition-timing-function",
- "layout.css.prefixes.transitions"
- ],
- [
- "-moz-animation",
- "layout.css.prefixes.animations"
- ],
- [
- "-moz-animation-delay",
- "layout.css.prefixes.animations"
- ],
- [
- "-moz-animation-direction",
- "layout.css.prefixes.animations"
- ],
- [
- "-moz-animation-duration",
- "layout.css.prefixes.animations"
- ],
- [
- "-moz-animation-fill-mode",
- "layout.css.prefixes.animations"
- ],
- [
- "-moz-animation-iteration-count",
- "layout.css.prefixes.animations"
- ],
- [
- "-moz-animation-name",
- "layout.css.prefixes.animations"
- ],
- [
- "-moz-animation-play-state",
- "layout.css.prefixes.animations"
- ],
- [
- "-moz-animation-timing-function",
- "layout.css.prefixes.animations"
- ],
- [
- "-moz-box-sizing",
- "layout.css.prefixes.box-sizing"
- ],
- [
- "-moz-font-feature-settings",
- "layout.css.prefixes.font-features"
- ],
- [
- "-moz-font-language-override",
- "layout.css.prefixes.font-features"
- ],
- [
- "-moz-padding-end",
- ""
- ],
- [
- "-moz-padding-start",
- ""
- ],
- [
- "-moz-margin-end",
- ""
- ],
- [
- "-moz-margin-start",
- ""
- ],
- [
- "-moz-border-end",
- ""
- ],
- [
- "-moz-border-end-color",
- ""
- ],
- [
- "-moz-border-end-style",
- ""
- ],
- [
- "-moz-border-end-width",
- ""
- ],
- [
- "-moz-border-start",
- ""
- ],
- [
- "-moz-border-start-color",
- ""
- ],
- [
- "-moz-border-start-style",
- ""
- ],
- [
- "-moz-border-start-width",
- ""
- ],
- [
- "-moz-hyphens",
- ""
- ],
- [
- "-moz-text-align-last",
- ""
- ],
- [
- "-moz-column-count",
- ""
- ],
- [
- "-moz-column-fill",
- ""
- ],
- [
- "-moz-column-gap",
- ""
- ],
- [
- "-moz-column-rule",
- ""
- ],
- [
- "-moz-column-rule-color",
- ""
- ],
- [
- "-moz-column-rule-style",
- ""
- ],
- [
- "-moz-column-rule-width",
- ""
- ],
- [
- "-moz-column-width",
- ""
- ],
- [
- "-moz-columns",
- ""
- ],
- [
- "-webkit-animation",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-animation-delay",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-animation-direction",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-animation-duration",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-animation-fill-mode",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-animation-iteration-count",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-animation-name",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-animation-play-state",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-animation-timing-function",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-filter",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-text-size-adjust",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-transform",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-transform-origin",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-transform-style",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-backface-visibility",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-perspective",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-perspective-origin",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-transition",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-transition-delay",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-transition-duration",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-transition-property",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-transition-timing-function",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-border-radius",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-border-top-left-radius",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-border-top-right-radius",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-border-bottom-left-radius",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-border-bottom-right-radius",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-background-clip",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-background-origin",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-background-size",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-border-image",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-box-shadow",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-box-sizing",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-box-flex",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-box-ordinal-group",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-box-orient",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-box-direction",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-box-align",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-box-pack",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-flex-direction",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-flex-wrap",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-flex-flow",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-order",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-flex",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-flex-grow",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-flex-shrink",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-flex-basis",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-justify-content",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-align-items",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-align-self",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-align-content",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-user-select",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-mask",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-mask-clip",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-mask-composite",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-mask-image",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-mask-origin",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-mask-position",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-mask-position-x",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-mask-position-y",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-mask-repeat",
- "layout.css.prefixes.webkit"
- ],
- [
- "-webkit-mask-size",
- "layout.css.prefixes.webkit"
- ]
-];
diff --git a/devtools/shared/css/generated/properties-db.js.in b/devtools/shared/css/generated/properties-db.js.in
index 372e525e9776..370c9199a02d 100644
--- a/devtools/shared/css/generated/properties-db.js.in
+++ b/devtools/shared/css/generated/properties-db.js.in
@@ -18,9 +18,3 @@ exports.CSS_PROPERTIES = ${cssProperties};
* A list of the pseudo elements.
*/
exports.PSEUDO_ELEMENTS = ${pseudoElements};
-
-/**
- * A list of the preferences keys for whether a CSS property is enabled or not. This is
- * exposed for testing purposes.
- */
-exports.PREFERENCES = ${preferences};
diff --git a/devtools/shared/css/properties-db.js b/devtools/shared/css/properties-db.js
index 0e4096a1621f..057a56cbfa0c 100644
--- a/devtools/shared/css/properties-db.js
+++ b/devtools/shared/css/properties-db.js
@@ -10,7 +10,20 @@
* above each list indicates how it should be updated.
*/
-const { CSS_PROPERTIES, PSEUDO_ELEMENTS } = require("devtools/shared/css/generated/properties-db");
+let db;
+
+// Allow this require to fail in case it's been deleted in the process of running
+// `mach devtools-css-db` to regenerate the database.
+try {
+ db = require("devtools/shared/css/generated/properties-db");
+} catch (error) {
+ console.error(`If this error is being displayed and "mach devtools-css-db" is not ` +
+ `being run, then it needs to be fixed.`, error);
+ db = {
+ CSS_PROPERTIES: {},
+ PSEUDO_ELEMENTS: []
+ };
+}
/**
* All CSS types that properties can support. This list can be manually edited.
@@ -57,7 +70,7 @@ exports.ANGLE_TAKING_FUNCTIONS = ["linear-gradient", "-moz-linear-gradient",
*
* This list can be updated with `mach devtools-css-db`.
*/
-exports.PSEUDO_ELEMENTS = PSEUDO_ELEMENTS;
+exports.PSEUDO_ELEMENTS = db.PSEUDO_ELEMENTS;
/**
* A list of CSS Properties and their various characteristics. This is used on the
@@ -69,9 +82,9 @@ exports.PSEUDO_ELEMENTS = PSEUDO_ELEMENTS;
* "supports": [ 7, 9, 10 ]
* }
*/
-exports.CSS_PROPERTIES = CSS_PROPERTIES;
+exports.CSS_PROPERTIES = db.CSS_PROPERTIES;
exports.CSS_PROPERTIES_DB = {
- properties: CSS_PROPERTIES,
- pseudoElements: PSEUDO_ELEMENTS
+ properties: db.CSS_PROPERTIES,
+ pseudoElements: db.PSEUDO_ELEMENTS
};
diff --git a/devtools/shared/tests/unit/test_css-properties-db.js b/devtools/shared/tests/unit/test_css-properties-db.js
index 68aedee267b0..108650a3ed49 100644
--- a/devtools/shared/tests/unit/test_css-properties-db.js
+++ b/devtools/shared/tests/unit/test_css-properties-db.js
@@ -3,11 +3,18 @@
/**
* Test that the devtool's client-side CSS properties database is in sync with the values
- * on the platform. If they are not, then `mach devtools-css-db` needs to be run to
- * make everything up to date. Nightly, aurora, beta, and release may have different
- * preferences for what CSS values are enabled. The static CSS properties database can
- * be slightly different from the target platform as long as there is a preference that
- * exists that turns off that CSS property.
+ * on the platform (in Nightly only). If they are not, then `mach devtools-css-db` needs
+ * to be run to make everything up to date. Nightly, aurora, beta, and release may have
+ * different CSS properties and values. These are based on preferences and compiler flags.
+ *
+ * This test broke uplifts as the database needed to be regenerated every uplift. The
+ * combination of compiler flags and preferences means that it's too difficult to
+ * statically determine which properties are enabled between Firefox releases.
+ *
+ * Because of these difficulties, the database only needs to be up to date with Nightly.
+ * It is a fallback that is only used if the remote debugging protocol doesn't support
+ * providing a CSS database, so it's ok if the provided properties don't exactly match
+ * the inspected target in this particular case.
*/
"use strict";
@@ -15,9 +22,8 @@
const DOMUtils = Components.classes["@mozilla.org/inspector/dom-utils;1"]
.getService(Components.interfaces.inIDOMUtils);
-const {PSEUDO_ELEMENTS, CSS_PROPERTIES, PREFERENCES} = require("devtools/shared/css/generated/properties-db");
+const {PSEUDO_ELEMENTS, CSS_PROPERTIES} = require("devtools/shared/css/generated/properties-db");
const {generateCssProperties} = require("devtools/server/actors/css-properties");
-const { Preferences } = require("resource://gre/modules/Preferences.jsm");
function run_test() {
const propertiesErrorMessage = "If this assertion fails, then the client side CSS " +
@@ -32,9 +38,7 @@ function run_test() {
/**
* Check that the platform and client match for the details on their CSS properties.
- * Enumerate each property to aid in debugging. Sometimes these properties don't
- * completely agree due to differences in preferences. Check the currently set
- * preference for that property to see if it's enabled.
+ * Enumerate each property to aid in debugging.
*/
const platformProperties = generateCssProperties();
@@ -71,14 +75,8 @@ function run_test() {
}
mismatches.forEach(propertyName => {
- if (getPreference(propertyName) === false) {
- ok(true, `The static database and platform do not agree on the property ` +
- `"${propertyName}" This is ok because it is currently disabled through ` +
- `a preference.`);
- } else {
- ok(false, `The static database and platform do not agree on the property ` +
- `"${propertyName}" ${propertiesErrorMessage}`);
- }
+ ok(false, `The static database and platform do not agree on the property ` +
+ `"${propertyName}" ${propertiesErrorMessage}`);
});
}
@@ -119,24 +117,6 @@ function isJsonDeepEqual(a, b) {
return false;
}
-/**
- * Get the preference value of whether this property is enabled. Returns an empty string
- * if no preference exists.
- *
- * @param {String} propertyName
- * @return {Boolean|undefined}
- */
-function getPreference(propertyName) {
- const preference = PREFERENCES.find(([prefPropertyName, preferenceKey]) => {
- return prefPropertyName === propertyName && !!preferenceKey;
- });
-
- if (preference) {
- return Preferences.get(preference[1]);
- }
- return undefined;
-}
-
/**
* Take the keys of two objects, and return the ones that don't match.
*
diff --git a/dom/browser-element/BrowserElementChild.js b/dom/browser-element/BrowserElementChild.js
index d8c3b15bf787..066be66d20a6 100644
--- a/dom/browser-element/BrowserElementChild.js
+++ b/dom/browser-element/BrowserElementChild.js
@@ -59,13 +59,6 @@ if (!BrowserElementIsReady) {
}
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementChildPreload.js");
- } else {
- if (Services.prefs.getIntPref("dom.w3c_touch_events.enabled") != 0) {
- if (docShell.asyncPanZoomEnabled === false) {
- ContentPanningAPZDisabled.init();
- }
- ContentPanning.init();
- }
}
function onDestroy() {
@@ -74,12 +67,6 @@ if (!BrowserElementIsReady) {
if (api) {
api.destroy();
}
- if ("ContentPanning" in this) {
- ContentPanning.destroy();
- }
- if ("ContentPanningAPZDisabled" in this) {
- ContentPanningAPZDisabled.destroy();
- }
if ("CopyPasteAssistent" in this) {
CopyPasteAssistent.destroy();
}
diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp
index 2aa3919e31b1..e92580b331ee 100644
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -72,18 +72,20 @@ using namespace mozilla::media;
#undef SFMT
#undef SLOG
#undef SWARN
+#undef SDUMP
#define FMT(x, ...) "Decoder=%p " x, mDecoderID, ##__VA_ARGS__
-#define DECODER_LOG(...) MOZ_LOG(gMediaDecoderLog, LogLevel::Debug, (FMT(__VA_ARGS__)))
-#define VERBOSE_LOG(...) MOZ_LOG(gMediaDecoderLog, LogLevel::Verbose, (FMT(__VA_ARGS__)))
-#define SAMPLE_LOG(...) MOZ_LOG(gMediaSampleLog, LogLevel::Debug, (FMT(__VA_ARGS__)))
-#define DECODER_WARN(...) NS_WARNING(nsPrintfCString(FMT(__VA_ARGS__)).get())
-#define DUMP_LOG(...) NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString(FMT(__VA_ARGS__)).get(), nullptr, nullptr, -1)
+#define DECODER_LOG(x, ...) MOZ_LOG(gMediaDecoderLog, LogLevel::Debug, (FMT(x, ##__VA_ARGS__)))
+#define VERBOSE_LOG(x, ...) MOZ_LOG(gMediaDecoderLog, LogLevel::Verbose, (FMT(x, ##__VA_ARGS__)))
+#define SAMPLE_LOG(x, ...) MOZ_LOG(gMediaSampleLog, LogLevel::Debug, (FMT(x, ##__VA_ARGS__)))
+#define DECODER_WARN(x, ...) NS_WARNING(nsPrintfCString(FMT(x, ##__VA_ARGS__)).get())
+#define DUMP_LOG(x, ...) NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString(FMT(x, ##__VA_ARGS__)).get(), nullptr, nullptr, -1)
// Used by StateObject and its sub-classes
#define SFMT(x, ...) "Decoder=%p state=%s " x, mMaster->mDecoderID, ToStateStr(GetState()), ##__VA_ARGS__
-#define SLOG(...) MOZ_LOG(gMediaDecoderLog, LogLevel::Debug, (SFMT(__VA_ARGS__)))
-#define SWARN(...) NS_WARNING(nsPrintfCString(SFMT(__VA_ARGS__)).get())
+#define SLOG(x, ...) MOZ_LOG(gMediaDecoderLog, LogLevel::Debug, (SFMT(x, ##__VA_ARGS__)))
+#define SWARN(x, ...) NS_WARNING(nsPrintfCString(SFMT(x, ##__VA_ARGS__)).get())
+#define SDUMP(x, ...) NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString(SFMT(x, ##__VA_ARGS__)).get(), nullptr, nullptr, -1)
// Certain constants get stored as member variables and then adjusted by various
// scale factors on a per-decoder basis. We want to make sure to avoid using these
@@ -221,11 +223,13 @@ public:
virtual bool HandleEndOfStream() { return false; }
- virtual RefPtr HandleSeek(SeekTarget aTarget)
- {
- MOZ_ASSERT(false, "Can't seek in this state");
- return nullptr;
- }
+ virtual bool HandleWaitingForData() { return false; }
+
+ virtual RefPtr HandleSeek(SeekTarget aTarget) = 0;
+
+ virtual bool HandleAudioCaptured() { return false; }
+
+ virtual void DumpDebugInfo() {}
protected:
using Master = MediaDecoderStateMachine;
@@ -286,6 +290,12 @@ public:
return true;
}
+ RefPtr HandleSeek(SeekTarget aTarget) override
+ {
+ MOZ_DIAGNOSTIC_ASSERT(false, "Can't seek while decoding metadata.");
+ return MediaDecoder::SeekPromise::CreateAndReject(true, __func__);
+ }
+
private:
void OnMetadataRead(MetadataHolder* aMetadata)
{
@@ -561,8 +571,7 @@ public:
mDecodeStartTime = TimeStamp::Now();
- mMaster->mIsPrerolling = true;
- mMaster->MaybeStopPrerolling();
+ MaybeStopPrerolling();
// Ensure that we've got tasks enqueued to decode data if we need to.
mMaster->DispatchDecodeTasksIfNeeded();
@@ -576,7 +585,6 @@ public:
TimeDuration decodeDuration = TimeStamp::Now() - mDecodeStartTime;
SLOG("Exiting DECODING, decoded for %.3lfs", decodeDuration.ToSeconds());
}
- mMaster->mIsPrerolling = false;
}
void Step() override
@@ -589,7 +597,9 @@ public:
}
// Start playback if necessary so that the clock can be properly queried.
- mMaster->MaybeStartPlayback();
+ if (!mIsPrerolling) {
+ mMaster->MaybeStartPlayback();
+ }
mMaster->UpdatePlaybackPositionPeriodically();
@@ -608,14 +618,14 @@ public:
bool HandleAudioDecoded(MediaData* aAudio) override
{
mMaster->Push(aAudio, MediaData::AUDIO_DATA);
- mMaster->MaybeStopPrerolling();
+ MaybeStopPrerolling();
return true;
}
bool HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart) override
{
mMaster->Push(aVideo, MediaData::VIDEO_DATA);
- mMaster->MaybeStopPrerolling();
+ MaybeStopPrerolling();
CheckSlowDecoding(aDecodeStart);
return true;
}
@@ -631,6 +641,35 @@ public:
return p.forget();
}
+ bool HandleEndOfStream() override
+ {
+ if (mMaster->CheckIfDecodeComplete()) {
+ SetState(DECODER_STATE_COMPLETED);
+ } else {
+ MaybeStopPrerolling();
+ }
+ return true;
+ }
+
+ bool HandleWaitingForData() override
+ {
+ MaybeStopPrerolling();
+ return true;
+ }
+
+ bool HandleAudioCaptured() override
+ {
+ MaybeStopPrerolling();
+ // MediaSink is changed. Schedule Step() to check if we can start playback.
+ mMaster->ScheduleStateMachine();
+ return true;
+ }
+
+ void DumpDebugInfo() override
+ {
+ SDUMP("mIsPrerolling=%d", mIsPrerolling);
+ }
+
private:
void CheckSlowDecoding(TimeStamp aDecodeStart)
{
@@ -663,16 +702,42 @@ private:
}
}
- bool HandleEndOfStream() override
+ bool DonePrerollingAudio()
{
- if (mMaster->CheckIfDecodeComplete()) {
- SetState(DECODER_STATE_COMPLETED);
+ return !mMaster->IsAudioDecoding() ||
+ mMaster->GetDecodedAudioDuration() >=
+ mMaster->AudioPrerollUsecs() * mMaster->mPlaybackRate;
+ }
+
+ bool DonePrerollingVideo()
+ {
+ return !mMaster->IsVideoDecoding() ||
+ static_cast(mMaster->VideoQueue().GetSize()) >=
+ mMaster->VideoPrerollFrames() * mMaster->mPlaybackRate + 1;
+ }
+
+ void MaybeStopPrerolling()
+ {
+ if (mIsPrerolling &&
+ (DonePrerollingAudio() || Reader()->IsWaitingAudioData()) &&
+ (DonePrerollingVideo() || Reader()->IsWaitingVideoData())) {
+ mIsPrerolling = false;
+ // Check if we can start playback.
+ mMaster->ScheduleStateMachine();
}
- return true;
}
// Time at which we started decoding.
TimeStamp mDecodeStartTime;
+
+ // When we start decoding (either for the first time, or after a pause)
+ // we may be low on decoded data. We don't want our "low data" logic to
+ // kick in and decide that we're low on decoded data because the download
+ // can't keep up with the decode, and cause us to pause playback. So we
+ // have a "preroll" stage, where we ignore the results of our "low data"
+ // logic during the first few frames of our decode. This occurs during
+ // playback.
+ bool mIsPrerolling = true;
};
class MediaDecoderStateMachine::SeekingState
@@ -1109,6 +1174,13 @@ public:
return p.forget();
}
+ bool HandleAudioCaptured() override
+ {
+ // MediaSink is changed. Schedule Step() to check if we can start playback.
+ mMaster->ScheduleStateMachine();
+ return true;
+ }
+
private:
bool mSentPlaybackEndedEvent = false;
};
@@ -1138,6 +1210,12 @@ public:
{
return true;
}
+
+ RefPtr HandleSeek(SeekTarget aTarget) override
+ {
+ MOZ_DIAGNOSTIC_ASSERT(false, "Can't seek in shutdown state.");
+ return MediaDecoder::SeekPromise::CreateAndReject(true, __func__);
+ }
};
#define INIT_WATCHABLE(name, val) \
@@ -1542,7 +1620,7 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
MOZ_ASSERT(mReader->IsWaitForDataSupported(),
"Readers that send WAITING_FOR_DATA need to implement WaitForData");
mReader->WaitForData(aType);
- MaybeStopPrerolling();
+ mStateObj->HandleWaitingForData();
return;
}
@@ -1569,8 +1647,6 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
VideoQueue().Finish();
}
- MaybeStopPrerolling();
-
mStateObj->HandleEndOfStream();
}
@@ -1719,19 +1795,6 @@ void MediaDecoderStateMachine::StopPlayback()
DispatchDecodeTasksIfNeeded();
}
-void
-MediaDecoderStateMachine::MaybeStopPrerolling()
-{
- MOZ_ASSERT(OnTaskQueue());
- if (mIsPrerolling &&
- (DonePrerollingAudio() || mReader->IsWaitingAudioData()) &&
- (DonePrerollingVideo() || mReader->IsWaitingVideoData())) {
- mIsPrerolling = false;
- // Check if we can start playback.
- ScheduleStateMachine();
- }
-}
-
void MediaDecoderStateMachine::MaybeStartPlayback()
{
MOZ_ASSERT(OnTaskQueue());
@@ -1746,10 +1809,10 @@ void MediaDecoderStateMachine::MaybeStartPlayback()
}
bool playStatePermits = mPlayState == MediaDecoder::PLAY_STATE_PLAYING;
- if (!playStatePermits || mIsPrerolling || mAudioOffloading) {
+ if (!playStatePermits || mAudioOffloading) {
DECODER_LOG("Not starting playback [playStatePermits: %d, "
- "mIsPrerolling: %d, mAudioOffloading: %d]",
- playStatePermits, mIsPrerolling, mAudioOffloading);
+ "mAudioOffloading: %d]",
+ playStatePermits, mAudioOffloading);
return;
}
@@ -2987,12 +3050,7 @@ MediaDecoderStateMachine::SetAudioCaptured(bool aCaptured)
// Restore playback parameters.
mMediaSink->SetPlaybackParams(params);
- // We don't need to call StartMediaSink() here because IsPlaying() is now
- // always in sync with the playing state of MediaSink. It will be started in
- // MaybeStartPlayback() in the next cycle if necessary.
-
mAudioCaptured = aCaptured;
- ScheduleStateMachine();
// Don't buffer as much when audio is captured because we don't need to worry
// about high latency audio devices.
@@ -3000,7 +3058,7 @@ MediaDecoderStateMachine::SetAudioCaptured(bool aCaptured)
detail::AMPLE_AUDIO_USECS / 2 :
detail::AMPLE_AUDIO_USECS;
- MaybeStopPrerolling();
+ mStateObj->HandleAudioCaptured();
}
uint32_t MediaDecoderStateMachine::GetAmpleVideoFrames() const
@@ -3020,15 +3078,16 @@ MediaDecoderStateMachine::DumpDebugInfo()
// this function before shutdown begins.
nsCOMPtr r = NS_NewRunnableFunction([this] () {
mMediaSink->DumpDebugInfo();
+ mStateObj->DumpDebugInfo();
DUMP_LOG(
"GetMediaTime=%lld GetClock=%lld mMediaSink=%p "
"mState=%s mPlayState=%d mSentFirstFrameLoadedEvent=%d IsPlaying=%d "
"mAudioStatus=%s mVideoStatus=%s mDecodedAudioEndTime=%lld mDecodedVideoEndTime=%lld "
- "mIsPrerolling=%d mAudioCompleted=%d mVideoCompleted=%d",
+ "mAudioCompleted=%d mVideoCompleted=%d",
GetMediaTime(), mMediaSink->IsStarted() ? GetClock() : -1, mMediaSink.get(),
ToStateStr(), mPlayState.Ref(), mSentFirstFrameLoadedEvent, IsPlaying(),
AudioRequestStatus(), VideoRequestStatus(), mDecodedAudioEndTime, mDecodedVideoEndTime,
- mIsPrerolling, mAudioCompleted.Ref(), mVideoCompleted.Ref());
+ mAudioCompleted.Ref(), mVideoCompleted.Ref());
});
OwnerThread()->DispatchStateChange(r.forget());
diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h
index d525f1f293c7..1cfd37de939e 100644
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -677,32 +677,6 @@ private:
return GetAmpleVideoFrames() / 2;
}
- bool DonePrerollingAudio()
- {
- MOZ_ASSERT(OnTaskQueue());
- return !IsAudioDecoding() ||
- GetDecodedAudioDuration() >= AudioPrerollUsecs() * mPlaybackRate;
- }
-
- bool DonePrerollingVideo()
- {
- MOZ_ASSERT(OnTaskQueue());
- return !IsVideoDecoding() ||
- static_cast(VideoQueue().GetSize()) >=
- VideoPrerollFrames() * mPlaybackRate + 1;
- }
-
- void MaybeStopPrerolling();
-
- // When we start decoding (either for the first time, or after a pause)
- // we may be low on decoded data. We don't want our "low data" logic to
- // kick in and decide that we're low on decoded data because the download
- // can't keep up with the decode, and cause us to pause playback. So we
- // have a "preroll" stage, where we ignore the results of our "low data"
- // logic during the first few frames of our decode. This occurs during
- // playback.
- bool mIsPrerolling = false;
-
// Only one of a given pair of ({Audio,Video}DataPromise, WaitForDataPromise)
// should exist at any given moment.
diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp
index 177523e830ef..0f7fec5b3358 100644
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -1513,18 +1513,13 @@ public:
}
if (errorMsg) {
LOG(("%s %d", errorMsg, rv));
- switch (rv) {
- case NS_ERROR_NOT_AVAILABLE: {
- MOZ_ASSERT(badConstraint);
- Fail(NS_LITERAL_STRING("OverconstrainedError"),
- NS_LITERAL_STRING(""),
- NS_ConvertUTF8toUTF16(badConstraint));
- break;
- }
- default:
- Fail(NS_LITERAL_STRING("NotReadableError"),
- NS_ConvertUTF8toUTF16(errorMsg));
- break;
+ if (badConstraint) {
+ Fail(NS_LITERAL_STRING("OverconstrainedError"),
+ NS_LITERAL_STRING(""),
+ NS_ConvertUTF8toUTF16(badConstraint));
+ } else {
+ Fail(NS_LITERAL_STRING("NotReadableError"),
+ NS_ConvertUTF8toUTF16(errorMsg));
}
return NS_OK;
}
@@ -3520,7 +3515,7 @@ GetUserMediaCallbackMediaStreamListener::ApplyConstraintsToTrack(
} else {
auto* window = nsGlobalWindow::GetInnerWindowWithId(windowId);
if (window) {
- if (rv == NS_ERROR_NOT_AVAILABLE) {
+ if (badConstraint) {
nsString constraint;
constraint.AssignASCII(badConstraint);
RefPtr error =
diff --git a/dom/media/mediasink/VideoSink.cpp b/dom/media/mediasink/VideoSink.cpp
index 474b8899490d..0f849838ef2f 100644
--- a/dom/media/mediasink/VideoSink.cpp
+++ b/dom/media/mediasink/VideoSink.cpp
@@ -16,9 +16,9 @@ extern LazyLogModule gMediaDecoderLog;
#undef DUMP_LOG
#define FMT(x, ...) "VideoSink=%p " x, this, ##__VA_ARGS__
-#define VSINK_LOG(...) MOZ_LOG(gMediaDecoderLog, LogLevel::Debug, (FMT(__VA_ARGS__)))
-#define VSINK_LOG_V(...) MOZ_LOG(gMediaDecoderLog, LogLevel::Verbose, (FMT(__VA_ARGS__)))
-#define DUMP_LOG(...) NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString(FMT(__VA_ARGS__)).get(), nullptr, nullptr, -1)
+#define VSINK_LOG(x, ...) MOZ_LOG(gMediaDecoderLog, LogLevel::Debug, (FMT(x, ##__VA_ARGS__)))
+#define VSINK_LOG_V(x, ...) MOZ_LOG(gMediaDecoderLog, LogLevel::Verbose, (FMT(x, ##__VA_ARGS__)))
+#define DUMP_LOG(x, ...) NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString(FMT(x, ##__VA_ARGS__)).get(), nullptr, nullptr, -1)
using namespace mozilla::layers;
diff --git a/dom/media/tests/mochitest/head.js b/dom/media/tests/mochitest/head.js
index 8ad6c4b8b2a9..0a2310ff83ed 100644
--- a/dom/media/tests/mochitest/head.js
+++ b/dom/media/tests/mochitest/head.js
@@ -66,7 +66,8 @@ AudioStreamAnalyser.prototype = {
*/
enableDebugCanvas: function() {
var cvs = this.debugCanvas = document.createElement("canvas");
- document.getElementById("content").appendChild(cvs);
+ const content = document.getElementById("content");
+ content.insertBefore(cvs, content.children[0]);
// Easy: 1px per bin
cvs.width = this.analyser.frequencyBinCount;
diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
index febe3df213d3..88ec6b0e4f5d 100644
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -2562,7 +2562,7 @@ WorkerPrivateParent::Freeze(nsPIDOMWindowInner* aWindow)
if ((IsSharedWorker() || IsServiceWorker()) && !mSharedWorkers.IsEmpty()) {
AssertIsOnMainThread();
- bool allFrozen = false;
+ bool allFrozen = true;
for (uint32_t i = 0; i < mSharedWorkers.Length(); ++i) {
if (aWindow && mSharedWorkers[i]->GetOwner() == aWindow) {
diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp
index 0105c0d45734..061afb85aefa 100644
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -597,7 +597,7 @@ JS_FRIEND_API(bool)
js::ZoneGlobalsAreAllGray(JS::Zone* zone)
{
for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next()) {
- JSObject* obj = comp->maybeGlobal();
+ JSObject* obj = comp->unsafeUnbarrieredMaybeGlobal();
if (!obj || !JS::ObjectIsMarkedGray(obj))
return false;
}
diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp
index 14212c90e80a..4c9a2f81a869 100644
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -2781,11 +2781,15 @@ CrossAxisPositionTracker::
// XXX strip of the bit until we implement that
mAlignContent &= ~NS_STYLE_ALIGN_FLAG_BITS;
- if (!aFirstLine->getNext()) {
+ const bool isSingleLine =
+ NS_STYLE_FLEX_WRAP_NOWRAP == aReflowInput.mStylePosition->mFlexWrap;
+ if (isSingleLine) {
+ MOZ_ASSERT(!aFirstLine->getNext(),
+ "If we're styled as single-line, we should only have 1 line");
// "If the flex container is single-line and has a definite cross size, the
// cross size of the flex line is the flex container's inner cross size."
//
- // SOURCE: http://dev.w3.org/csswg/css-flexbox/#algo-line-break
+ // SOURCE: https://drafts.csswg.org/css-flexbox/#algo-cross-line
// NOTE: This means (by definition) that there's no packing space, which
// means we don't need to be concerned with "align-conent" at all and we
// can return early. This is handy, because this is the usual case (for
diff --git a/layout/reftests/font-face/src-list-local-full-quotes.html b/layout/reftests/font-face/src-list-local-full-quotes.html
index 3e75b0aa012f..c63e6f40196d 100644
--- a/layout/reftests/font-face/src-list-local-full-quotes.html
+++ b/layout/reftests/font-face/src-list-local-full-quotes.html
@@ -15,18 +15,18 @@ body {
@font-face {
font-family: test-regular;
- src: local("Helvetica Neue"), local("Bitstream Vera Sans"), local("Bitstream Vera Sans Roman"), local("FreeSans"), local("Free Sans"), local("SwissA"), local("DejaVu Sans"), local("Arial");
+ src: local("Helvetica Neue"), local("Bitstream Vera Sans"), local("Bitstream Vera Sans Roman"), local("DejaVu Sans"), local("FreeSans"), local("Free Sans"), local("SwissA"), local("Arial");
}
/* use Helvetica on the Mac, since Futura has no bold face on 10.4, 10.5 */
@font-face {
font-family: test-bold;
- src: local("Helvetica Neue Bold"), local("Bitstream Vera Sans Bold"), local("FreeSans Bold"), local("Free Sans Bold"), local("SwissA Bold"), local("DejaVu Sans Bold"), local("Arial Bold");
+ src: local("Helvetica Neue Bold"), local("Bitstream Vera Sans Bold"), local("DejaVu Sans Bold"), local("FreeSans Bold"), local("Free Sans Bold"), local("SwissA Bold"), local("Arial Bold");
}
@font-face {
font-family: test-italic;
- src: local("Helvetica Neue Italic"), local("Bitstream Vera Sans Oblique"), local("FreeSans Oblique"), local("Free Sans Oblique"), local("SwissA Italic"), local("DejaVu Sans Oblique"), local("Arial Italic");
+ src: local("Helvetica Neue Italic"), local("Bitstream Vera Sans Oblique"), local("DejaVu Sans Oblique"), local("FreeSans Oblique"), local("Free Sans Oblique"), local("SwissA Italic"), local("Arial Italic");
}
.regular { font-family: test-regular, serif; }
diff --git a/layout/reftests/font-face/src-list-local-full-ref.html b/layout/reftests/font-face/src-list-local-full-ref.html
index d221bcc7e8ad..4d357f8a2cfa 100644
--- a/layout/reftests/font-face/src-list-local-full-ref.html
+++ b/layout/reftests/font-face/src-list-local-full-ref.html
@@ -11,9 +11,10 @@ body {
font-size: 24pt;
}
-/* use full names */
+/* Bitstream Vera must be adjacent to DejaVu to because the latter is picked
+ up by fontconfig aliases for the former. */
-p { font-family: Helvetica Neue, Bitstream Vera Sans, FreeSans, SwissA, DejaVu Sans, Arial, serif; }
+p { font-family: Helvetica Neue, Bitstream Vera Sans, DejaVu Sans, FreeSans, SwissA, Arial, serif; }
.regular { }
.bold { font-weight: bold; }
diff --git a/layout/reftests/font-face/src-list-local-full.html b/layout/reftests/font-face/src-list-local-full.html
index ca730e62b0a9..c4aafdfa1e19 100644
--- a/layout/reftests/font-face/src-list-local-full.html
+++ b/layout/reftests/font-face/src-list-local-full.html
@@ -15,18 +15,18 @@ body {
@font-face {
font-family: test-regular;
- src: local(Helvetica Neue), local(Bitstream Vera Sans), local(Bitstream Vera Sans Roman), local(FreeSans), local(Free Sans), local(SwissA), local(DejaVu Sans), local(Arial);
+ src: local(Helvetica Neue), local(Bitstream Vera Sans), local(Bitstream Vera Sans Roman), local(DejaVu Sans), local(FreeSans), local(Free Sans), local(SwissA), local(Arial);
}
/* use Helvetica on the Mac, since Futura has no bold face on 10.4, 10.5 */
@font-face {
font-family: test-bold;
- src: local(Helvetica Neue Bold), local(Bitstream Vera Sans Bold), local(FreeSans Bold), local(Free Sans Bold), local(SwissA Bold), local(DejaVu Sans Bold), local(Arial Bold);
+ src: local(Helvetica Neue Bold), local(Bitstream Vera Sans Bold), local(DejaVu Sans Bold), local(FreeSans Bold), local(Free Sans Bold), local(SwissA Bold), local(Arial Bold);
}
@font-face {
font-family: test-italic;
- src: local(Helvetica Neue Italic), local(Bitstream Vera Sans Oblique), local(FreeSans Oblique), local(Free Sans Oblique), local(SwissA Italic), local(DejaVu Sans Oblique), local(Arial Italic);
+ src: local(Helvetica Neue Italic), local(Bitstream Vera Sans Oblique), local(DejaVu Sans Oblique), local(FreeSans Oblique), local(Free Sans Oblique), local(SwissA Italic), local(Arial Italic);
}
.regular { font-family: test-regular, serif; }
diff --git a/layout/reftests/w3c-css/submitted/flexbox/flexbox-align-content-horiz-001-ref.xhtml b/layout/reftests/w3c-css/submitted/flexbox/flexbox-align-content-horiz-001-ref.xhtml
index af82e40b2471..d2cb6a0b6305 100644
--- a/layout/reftests/w3c-css/submitted/flexbox/flexbox-align-content-horiz-001-ref.xhtml
+++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-align-content-horiz-001-ref.xhtml
@@ -71,7 +71,7 @@
@@ -85,7 +85,7 @@
@@ -113,7 +113,7 @@
diff --git a/layout/reftests/w3c-css/submitted/flexbox/flexbox-align-content-vert-001-ref.xhtml b/layout/reftests/w3c-css/submitted/flexbox/flexbox-align-content-vert-001-ref.xhtml
index e82d0e2738a5..8113c1c10525 100644
--- a/layout/reftests/w3c-css/submitted/flexbox/flexbox-align-content-vert-001-ref.xhtml
+++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-align-content-vert-001-ref.xhtml
@@ -74,7 +74,7 @@
@@ -88,7 +88,7 @@
@@ -116,7 +116,7 @@
@@ -144,7 +144,7 @@
diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js
index ec582291d045..9ecaa05a1307 100644
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1455,13 +1455,11 @@ pref("network.http.sendRefererHeader", 2);
pref("network.http.referer.spoofSource", false);
// 0=full URI, 1=scheme+host+port+path, 2=scheme+host+port
pref("network.http.referer.trimmingPolicy", 0);
+// 0=full URI, 1=scheme+host+port+path, 2=scheme+host+port
+pref("network.http.referer.XOriginTrimmingPolicy", 0);
// 0=always send, 1=send iff base domains match, 2=send iff hosts match
pref("network.http.referer.XOriginPolicy", 0);
-// Controls whether we send HTTPS referres to other HTTPS sites.
-// By default this is enabled for compatibility (see bug 141641)
-pref("network.http.sendSecureXSiteReferrer", true);
-
// Controls whether referrer attributes in
, , ,