Merge mozilla central to inbound

This commit is contained in:
arthur.iakab 2018-08-15 01:05:50 +03:00
commit 34ad5ebaac
108 changed files with 1435 additions and 1483 deletions

View File

@ -767,8 +767,7 @@ var gHistorySwipeAnimation = {
* @return the newly created element.
*/
_createElement: function HSA__createElement(aID, aTagName) {
let XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let element = document.createElementNS(XULNS, aTagName);
let element = document.createXULElement(aTagName);
element.id = aID;
return element;
},

View File

@ -653,8 +653,7 @@ var gPluginHandler = {
iconURL, priority, buttons);
// Add the "learn more" link.
let XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let link = notification.ownerDocument.createElementNS(XULNS, "label");
let link = notification.ownerDocument.createXULElement("label");
link.className = "text-link";
link.setAttribute("value", gNavigatorBundle.getString("crashedpluginsMessage.learnMore"));
let crashurl = formatURL("app.support.baseURL", true);

View File

@ -66,14 +66,6 @@ searchbar {
min-width: 25px;
}
.browserStack > browser {
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-browser");
}
.browserStack > browser[remote="true"] {
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-remote-browser");
}
toolbar[customizable="true"] {
-moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#toolbar");
}

View File

@ -8073,8 +8073,7 @@ TabModalPromptBox.prototype = {
},
appendPrompt(args, onCloseCallback) {
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let newPrompt = document.createElementNS(XUL_NS, "tabmodalprompt");
let newPrompt = document.createXULElement("tabmodalprompt");
let browser = this.browser;
browser.parentNode.insertBefore(newPrompt, browser.nextElementSibling);
browser.setAttribute("tabmodalPromptShowing", true);
@ -8096,9 +8095,9 @@ TabModalPromptBox.prototype = {
hostForAllowFocusCheckbox = principalToAllowFocusFor.URI.host;
} catch (ex) { /* Ignore exceptions for host-less URIs */ }
if (hostForAllowFocusCheckbox) {
let allowFocusRow = document.createElementNS(XUL_NS, "row");
allowFocusCheckbox = document.createElementNS(XUL_NS, "checkbox");
let spacer = document.createElementNS(XUL_NS, "spacer");
let allowFocusRow = document.createXULElement("row");
allowFocusCheckbox = document.createXULElement("checkbox");
let spacer = document.createXULElement("spacer");
allowFocusRow.appendChild(spacer);
let label = gTabBrowserBundle.formatStringFromName("tabs.allowTabFocusByPromptForSite",
[hostForAllowFocusCheckbox], 1);

View File

@ -831,6 +831,7 @@ nsContextMenu.prototype = {
let referrer = gContextMenuContentData.referrer;
openLinkIn(gContextMenuContentData.docLocation, "tab",
{ charset: gContextMenuContentData.charSet,
triggeringPrincipal: this.browser.contentPrincipal,
referrerURI: referrer ? makeURI(referrer) : null });
},

View File

@ -258,7 +258,7 @@ window._gBrowser = {
}
let stack = this.selectedBrowser.parentNode;
// Create an anchor for the popup
let popupAnchor = document.createElementNS(this._XUL_NS, "hbox");
let popupAnchor = document.createXULElement("hbox");
popupAnchor.className = "popup-anchor";
popupAnchor.hidden = true;
stack.appendChild(popupAnchor);
@ -293,6 +293,7 @@ window._gBrowser = {
browser.permanentKey = {};
browser.droppedLinkHandler = handleDroppedLink;
browser.loadURI = _loadURI.bind(null, browser);
let autoScrollPopup = browser._createAutoScrollPopup();
autoScrollPopup.id = "autoscroller";
@ -513,7 +514,7 @@ window._gBrowser = {
* @return the created findbar, or null if the window or tab is closed/closing.
*/
async _createFindBar(aTab) {
let findBar = document.createElementNS(this._XUL_NS, "findbar");
let findBar = document.createXULElement("findbar");
let browser = this.getBrowserForTab(aTab);
let browserContainer = this.getBrowserContainer(browser);
browserContainer.appendChild(findBar);
@ -1799,7 +1800,7 @@ window._gBrowser = {
uriIsAboutBlank,
userContextId,
} = {}) {
let b = document.createElementNS(this._XUL_NS, "browser");
let b = document.createXULElement("browser");
b.permanentKey = {};
for (let attribute in this._defaultBrowserAttributes) {
@ -1874,25 +1875,25 @@ window._gBrowser = {
}
// Create the browserStack container
let stack = document.createElementNS(this._XUL_NS, "stack");
let stack = document.createXULElement("stack");
stack.className = "browserStack";
stack.appendChild(b);
stack.setAttribute("flex", "1");
// Create the browserContainer
let browserContainer = document.createElementNS(this._XUL_NS, "vbox");
let browserContainer = document.createXULElement("vbox");
browserContainer.className = "browserContainer";
browserContainer.appendChild(stack);
browserContainer.setAttribute("flex", "10000");
// Create the sidebar container
let browserSidebarContainer = document.createElementNS(this._XUL_NS, "hbox");
let browserSidebarContainer = document.createXULElement("hbox");
browserSidebarContainer.className = "browserSidebarContainer";
browserSidebarContainer.appendChild(browserContainer);
browserSidebarContainer.setAttribute("flex", "10000");
// Add the Message and the Browser to the box
let notificationbox = document.createElementNS(this._XUL_NS, "notificationbox");
let notificationbox = document.createXULElement("notificationbox");
notificationbox.setAttribute("flex", "1");
notificationbox.setAttribute("notificationside", "top");
notificationbox.appendChild(browserSidebarContainer);
@ -2040,6 +2041,7 @@ window._gBrowser = {
this._tabFilters.set(aTab, filter);
browser.droppedLinkHandler = handleDroppedLink;
browser.loadURI = _loadURI.bind(null, browser);
// Most of the time, we start our browser's docShells out as inactive,
// and then maintain activeness in the tab switcher. Preloaded about:newtab's
@ -2233,7 +2235,7 @@ window._gBrowser = {
let openerTab = ((openerBrowser && this.getTabForBrowser(openerBrowser)) ||
(relatedToCurrent && this.selectedTab));
var t = document.createElementNS(this._XUL_NS, "tab");
var t = document.createXULElement("tab");
t.openerTab = openerTab;
@ -3724,6 +3726,7 @@ window._gBrowser = {
}
aTab.setAttribute("multiselected", "true");
aTab.setAttribute("aria-selected", "true");
this._multiSelectedTabsSet.add(aTab);
this._startMultiSelectChange();
if (this._multiSelectChangeRemovals.has(aTab)) {
@ -3763,6 +3766,7 @@ window._gBrowser = {
return;
}
aTab.removeAttribute("multiselected");
aTab.removeAttribute("aria-selected");
this._multiSelectedTabsSet.delete(aTab);
this._startMultiSelectChange();
if (this._multiSelectChangeAdditions.has(aTab)) {

View File

@ -128,6 +128,11 @@
this._tabMinWidth = this._tabMinWidthPref;
XPCOMUtils.defineLazyPreferenceGetter(this, "_multiselectEnabledPref",
"browser.tabs.multiselect", null,
(pref, prevValue, newValue) => this._multiselectEnabled = newValue);
this._multiselectEnabled = this._multiselectEnabledPref;
this._setPositionalAttributes();
CustomizableUI.addListener(this);
@ -172,6 +177,17 @@
</setter>
</property>
<property name="_multiselectEnabled">
<setter>
// Unlike boolean HTML attributes, the value of boolean ARIA attributes actually matters.
this.setAttribute("aria-multiselectable", !!val);
return val;
</setter>
<getter>
return this.getAttribute("aria-multiselectable") == "true";
</getter>
</property>
<method name="observe">
<parameter name="aSubject"/>
<parameter name="aTopic"/>
@ -2069,7 +2085,7 @@
} else {
// When browser.tabs.multiselect config is set to false,
// then we ignore the state of multi-selection keys (Ctrl/Cmd).
const tabSelectionToggled = Services.prefs.getBoolPref("browser.tabs.multiselect") &&
const tabSelectionToggled = tabContainer._multiselectEnabled &&
(event.getModifierState("Accel") || event.shiftKey);
if (this.mOverCloseButton || this._overPlayingIcon || tabSelectionToggled) {
@ -2092,7 +2108,8 @@
</handler>
<handler event="click" button="0"><![CDATA[
if (Services.prefs.getBoolPref("browser.tabs.multiselect")) {
let tabContainer = this.parentNode;
if (tabContainer._multiselectEnabled) {
let shiftKey = event.shiftKey;
let accelKey = event.getModifierState("Accel");
if (shiftKey) {
@ -2188,41 +2205,4 @@
</handler>
</handlers>
</binding>
<binding id="tabbrowser-browser"
extends="chrome://global/content/bindings/browser.xml#browser">
<implementation>
<field name="tabModalPromptBox">null</field>
<!-- throws exception for unknown schemes -->
<method name="loadURI">
<parameter name="aURI"/>
<parameter name="aParams"/>
<body>
<![CDATA[
_loadURI(this, aURI, aParams);
]]>
</body>
</method>
</implementation>
</binding>
<binding id="tabbrowser-remote-browser"
extends="chrome://global/content/bindings/remote-browser.xml#remote-browser">
<implementation>
<field name="tabModalPromptBox">null</field>
<!-- throws exception for unknown schemes -->
<method name="loadURI">
<parameter name="aURI"/>
<parameter name="aParams"/>
<body>
<![CDATA[
_loadURI(this, aURI, aParams);
]]>
</body>
</method>
</implementation>
</binding>
</bindings>

View File

@ -7,6 +7,9 @@ support-files =
[browser_contextmenu_touch.js]
skip-if = !(os == 'win' && os_version == '10.0')
[browser_contextmenu_linkopen.js]
[browser_contextmenu_iframe.js]
support-files =
test_contextmenu_iframe.html
[browser_utilityOverlay.js]
skip-if = os == "linux" || os == "mac" #Bug 1444631
[browser_utilityOverlayPrincipal.js]

View File

@ -0,0 +1,47 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const TEST_LINK = "https://example.com/";
const RESOURCE_LINK = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "https://example.com") + "test_contextmenu_iframe.html";
/* This test checks that a context menu can open up
* a frame into it's own tab. */
add_task(async function test_open_iframe() {
let testTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, RESOURCE_LINK);
const selector = "#iframe";
const openPromise = BrowserTestUtils.waitForNewTab(gBrowser, TEST_LINK, false);
const contextMenu = document.getElementById("contentAreaContextMenu");
is(contextMenu.state, "closed", "checking if popup is closed");
let awaitPopupShown = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
await BrowserTestUtils.synthesizeMouseAtCenter(selector, {
type: "contextmenu",
button: 2,
centered: true,
},
gBrowser.selectedBrowser);
await awaitPopupShown;
info("Popup Shown");
const awaitPopupHidden = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden");
// Open frame submenu
const menuPopup = contextMenu.querySelector("#frame").menupopup;
const menuPopupPromise = BrowserTestUtils.waitForEvent(menuPopup, "popupshown");
menuPopup.openPopup();
await menuPopupPromise;
let domItem = contextMenu.querySelector("#context-openframeintab");
info("Going to click item " + domItem.id);
ok(BrowserTestUtils.is_visible(domItem), "DOM context menu item tab should be visible");
ok(!domItem.disabled, "DOM context menu item tab shouldn't be disabled");
domItem.click();
let openedTab = await openPromise;
contextMenu.hidePopup();
await awaitPopupHidden;
await BrowserTestUtils.removeTab(openedTab);
BrowserTestUtils.removeTab(testTab);
});

View File

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Subtest for browser context menu iframes</title>
</head>
<body>
Browser context menu iframe subtest.
<iframe src="https://example.com/" id="iframe"></iframe>
</body>
</html>

View File

@ -12,6 +12,8 @@ add_task(async function() {
});
function testSelectedTabs(tabs) {
is(gBrowser.tabContainer.getAttribute("aria-multiselectable"), "true",
"tabbrowser should be marked as aria-multiselectable");
gBrowser.selectedTabs = tabs;
let {selectedTab, selectedTabs, _multiSelectedTabsSet} = gBrowser;
is(selectedTab, tabs[0], "The selected tab should be the expected one");
@ -20,12 +22,15 @@ add_task(async function() {
ok(!_multiSelectedTabsSet.has(selectedTab), "Selected tab shouldn't be in _multiSelectedTabsSet");
is(selectedTabs.length, 1, "selectedTabs should contain a single tab");
is(selectedTabs[0], selectedTab, "selectedTabs should contain the selected tab");
ok(!selectedTab.hasAttribute("aria-selected"),
"Selected tab shouldn't be marked as aria-selected when only one tab is selected");
} else {
ok(selectedTabs.length, tabs.length, "Check number of selected tabs");
for (let tab of tabs) {
ok(tab.multiselected, "Tab should be multi-selected");
ok(_multiSelectedTabsSet.has(tab), "Tab should be in _multiSelectedTabsSet");
ok(selectedTabs.includes(tab), "Tab should be in selectedTabs");
is(tab.getAttribute("aria-selected"), "true", "Selected tab should be marked as aria-selected");
}
}
}

View File

@ -2642,9 +2642,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
child.style.display;
child.style.display = "none";
}
let XUL_NS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let iframe = document.createElementNS(XUL_NS, "iframe");
let iframe = document.createXULElement("iframe");
iframe.setAttribute("type", "content");
iframe.setAttribute("flex", "1");
iframe.style.transition = "height 100ms";

View File

@ -25,10 +25,10 @@ function getBrowser(sidebar) {
return Promise.resolve(browser);
}
let stack = document.createElementNS(XUL_NS, "stack");
let stack = document.createXULElement("stack");
stack.setAttribute("flex", "1");
browser = document.createElementNS(XUL_NS, "browser");
browser = document.createXULElement("browser");
browser.setAttribute("id", "webext-panels-browser");
browser.setAttribute("type", "content");
browser.setAttribute("flex", "1");

View File

@ -28,8 +28,6 @@ XPCOMUtils.defineLazyGetter(this, "gWidgetsBundle", function() {
XPCOMUtils.defineLazyServiceGetter(this, "gELS",
"@mozilla.org/eventlistenerservice;1", "nsIEventListenerService");
const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const kSpecialWidgetPfx = "customizableui-special-";
const kPrefCustomizationState = "browser.uiCustomization.state";
@ -1364,7 +1362,7 @@ var CustomizableUIInternal = {
createSpecialWidget(aId, aDocument) {
let nodeName = "toolbar" + aId.match(/spring|spacer|separator/)[0];
let node = aDocument.createElementNS(kNSXUL, nodeName);
let node = aDocument.createXULElement(nodeName);
node.className = "chromeclass-toolbar-additional";
node.id = this.ensureSpecialWidgetId(aId);
return node;
@ -1459,7 +1457,7 @@ var CustomizableUIInternal = {
if (aWidget.onBeforeCreated) {
aWidget.onBeforeCreated(aDocument);
}
node = aDocument.createElementNS(kNSXUL, "toolbarbutton");
node = aDocument.createXULElement("toolbarbutton");
node.setAttribute("id", aWidget.id);
node.setAttribute("widget-id", aWidget.id);
@ -3906,9 +3904,9 @@ var CustomizableUI = {
if (!fragment.lastElementChild || fragment.lastElementChild.localName == "menuseparator") {
continue;
}
subviewItem = doc.createElementNS(kNSXUL, "menuseparator");
subviewItem = doc.createXULElement("menuseparator");
} else if (menuChild.localName == "menuitem") {
subviewItem = doc.createElementNS(kNSXUL, "toolbarbutton");
subviewItem = doc.createXULElement("toolbarbutton");
CustomizableUI.addShortcut(menuChild, subviewItem);
let item = menuChild;

View File

@ -26,7 +26,6 @@ XPCOMUtils.defineLazyGetter(this, "CharsetBundle", function() {
return Services.strings.createBundle(kCharsetBundle);
});
const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const kPrefCustomizationDebug = "browser.uiCustomization.debug";
XPCOMUtils.defineLazyGetter(this, "log", () => {
@ -196,10 +195,10 @@ const CustomizableWidgets = [
onCreated(aNode) {
// Add an observer so the button is checked while the sidebar is open
let doc = aNode.ownerDocument;
let obChecked = doc.createElementNS(kNSXUL, "observes");
let obChecked = doc.createXULElement("observes");
obChecked.setAttribute("element", "sidebar-box");
obChecked.setAttribute("attribute", "checked");
let obPosition = doc.createElementNS(kNSXUL, "observes");
let obPosition = doc.createXULElement("observes");
obPosition.setAttribute("element", "sidebar-box");
obPosition.setAttribute("attribute", "positionend");
@ -244,7 +243,7 @@ const CustomizableWidgets = [
"class": "toolbarbutton-1 toolbarbutton-combined",
}];
let node = aDocument.createElementNS(kNSXUL, "toolbaritem");
let node = aDocument.createXULElement("toolbaritem");
node.setAttribute("id", "zoom-controls");
node.setAttribute("label", CustomizableUI.getLocalizedProperty(this, "label"));
node.setAttribute("title", CustomizableUI.getLocalizedProperty(this, "tooltiptext"));
@ -255,8 +254,8 @@ const CustomizableWidgets = [
buttons.forEach(function(aButton, aIndex) {
if (aIndex != 0)
node.appendChild(aDocument.createElementNS(kNSXUL, "separator"));
let btnNode = aDocument.createElementNS(kNSXUL, "toolbarbutton");
node.appendChild(aDocument.createXULElement("separator"));
let btnNode = aDocument.createXULElement("toolbarbutton");
setAttributes(btnNode, aButton);
node.appendChild(btnNode);
});
@ -290,7 +289,7 @@ const CustomizableWidgets = [
"class": "toolbarbutton-1 toolbarbutton-combined",
}];
let node = aDocument.createElementNS(kNSXUL, "toolbaritem");
let node = aDocument.createXULElement("toolbaritem");
node.setAttribute("id", "edit-controls");
node.setAttribute("label", CustomizableUI.getLocalizedProperty(this, "label"));
node.setAttribute("title", CustomizableUI.getLocalizedProperty(this, "tooltiptext"));
@ -301,8 +300,8 @@ const CustomizableWidgets = [
buttons.forEach(function(aButton, aIndex) {
if (aIndex != 0)
node.appendChild(aDocument.createElementNS(kNSXUL, "separator"));
let btnNode = aDocument.createElementNS(kNSXUL, "toolbarbutton");
node.appendChild(aDocument.createXULElement("separator"));
let btnNode = aDocument.createXULElement("toolbarbutton");
setAttributes(btnNode, aButton);
node.appendChild(btnNode);
});
@ -386,7 +385,7 @@ const CustomizableWidgets = [
let list = this.charsetInfo[aSection];
for (let item of list) {
let elem = aDocument.createElementNS(kNSXUL, "toolbarbutton");
let elem = aDocument.createXULElement("toolbarbutton");
elem.setAttribute("label", item.label);
elem.setAttribute("type", "checkbox");
elem.section = aSection;
@ -644,7 +643,7 @@ if (Services.prefs.getBoolPref("identity.fxaccounts.enabled")) {
for (let client of clients) {
// add a menu separator for all clients other than the first.
if (fragment.lastElementChild) {
let separator = doc.createElementNS(kNSXUL, "menuseparator");
let separator = doc.createXULElement("menuseparator");
fragment.appendChild(separator);
}
if (paginationInfo && paginationInfo.clientId == client.id) {
@ -678,7 +677,7 @@ if (Services.prefs.getBoolPref("identity.fxaccounts.enabled")) {
}
let message = this._tabsList.getAttribute(messageAttr);
let doc = this._tabsList.ownerDocument;
let messageLabel = doc.createElementNS(kNSXUL, "label");
let messageLabel = doc.createXULElement("label");
messageLabel.textContent = message;
appendTo.appendChild(messageLabel);
return messageLabel;
@ -686,7 +685,7 @@ if (Services.prefs.getBoolPref("identity.fxaccounts.enabled")) {
_appendClient(client, attachFragment, maxTabs = this.TABS_PER_PAGE) {
let doc = attachFragment.ownerDocument;
// Create the element for the remote client.
let clientItem = doc.createElementNS(kNSXUL, "label");
let clientItem = doc.createXULElement("label");
clientItem.setAttribute("itemtype", "client");
let window = doc.defaultView;
clientItem.setAttribute("tooltiptext",
@ -726,7 +725,7 @@ if (Services.prefs.getBoolPref("identity.fxaccounts.enabled")) {
}
},
_createTabElement(doc, tabInfo) {
let item = doc.createElementNS(kNSXUL, "toolbarbutton");
let item = doc.createXULElement("toolbarbutton");
let tooltipText = (tabInfo.title ? tabInfo.title + "\n" : "") + tabInfo.url;
item.setAttribute("itemtype", "tab");
item.setAttribute("class", "subviewbutton");
@ -758,7 +757,7 @@ if (Services.prefs.getBoolPref("identity.fxaccounts.enabled")) {
labelAttr = "showMoreLabel";
tooltipAttr = "showMoreTooltipText";
}
let showAllItem = doc.createElementNS(kNSXUL, "toolbarbutton");
let showAllItem = doc.createXULElement("toolbarbutton");
showAllItem.setAttribute("itemtype", "showmorebutton");
showAllItem.setAttribute("class", "subviewbutton");
let label = this._tabsList.getAttribute(labelAttr);

View File

@ -623,7 +623,6 @@ const PanelUI = {
let helpMenu = document.getElementById("menu_HelpPopup");
let items = this.getElementsByTagName("vbox")[0];
let attrs = ["oncommand", "onclick", "label", "key", "disabled"];
let NSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
// Remove all buttons from the view
while (items.firstChild) {
@ -636,7 +635,7 @@ const PanelUI = {
for (let node of menuItems) {
if (node.hidden)
continue;
let button = document.createElementNS(NSXUL, "toolbarbutton");
let button = document.createXULElement("toolbarbutton");
// Copy specific attributes from a menuitem of the Help menu
for (let attrName of attrs) {
if (!node.hasAttribute(attrName))

View File

@ -33,8 +33,6 @@ const {
const POPUP_LOAD_TIMEOUT_MS = 200;
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
function promisePopupShown(popup) {
return new Promise(resolve => {
if (popup.state == "open") {
@ -239,10 +237,10 @@ class BasePopup {
createBrowser(viewNode, popupURL = null) {
let document = viewNode.ownerDocument;
let stack = document.createElementNS(XUL_NS, "stack");
let stack = document.createXULElement("stack");
stack.setAttribute("class", "webextension-popup-stack");
let browser = document.createElementNS(XUL_NS, "browser");
let browser = document.createXULElement("browser");
browser.setAttribute("type", "content");
browser.setAttribute("disableglobalhistory", "true");
browser.setAttribute("transparent", "true");

View File

@ -31,8 +31,6 @@ const POPUP_PRELOAD_TIMEOUT_MS = 200;
const POPUP_OPEN_MS_HISTOGRAM = "WEBEXT_BROWSERACTION_POPUP_OPEN_MS";
const POPUP_RESULT_HISTOGRAM = "WEBEXT_BROWSERACTION_POPUP_PRELOAD_RESULT_COUNT";
var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
// WeakMap[Extension -> BrowserAction]
const browserActionMap = new WeakMap();
@ -143,7 +141,7 @@ this.browserAction = class extends ExtensionAPI {
localized: false,
onBeforeCreated: document => {
let view = document.createElementNS(XUL_NS, "panelview");
let view = document.createXULElement("panelview");
view.id = this.viewId;
view.setAttribute("flex", "1");
view.setAttribute("extension", true);

View File

@ -12,8 +12,6 @@ var {
ExtensionError,
} = ExtensionUtils;
var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const EXECUTE_PAGE_ACTION = "_execute_page_action";
const EXECUTE_BROWSER_ACTION = "_execute_browser_action";
const EXECUTE_SIDEBAR_ACTION = "_execute_sidebar_action";
@ -154,7 +152,7 @@ this.commands = class extends ExtensionAPI {
*/
registerKeysToDocument(window, commands) {
let doc = window.document;
let keyset = doc.createElementNS(XUL_NS, "keyset");
let keyset = doc.createXULElement("keyset");
keyset.id = `ext-keyset-id-${this.id}`;
if (this.keysetsMap.has(window)) {
this.keysetsMap.get(window).remove();
@ -232,7 +230,7 @@ this.commands = class extends ExtensionAPI {
* @returns {Document} The newly created Key element.
*/
buildKeyFromShortcut(doc, name, shortcut) {
let keyElement = doc.createElementNS(XUL_NS, "key");
let keyElement = doc.createXULElement("key");
let parts = shortcut.split("+");

View File

@ -16,8 +16,6 @@ var {
promiseEvent,
} = ExtensionUtils;
var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
/**
* Represents an addon devtools panel in the main process.
*
@ -218,13 +216,13 @@ class ParentDevToolsPanel {
// extension sidebar pages).
let stack = document.getElementById("webext-panels-stack");
if (!stack) {
stack = document.createElementNS(XUL_NS, "stack");
stack = document.createXULElement("stack");
stack.setAttribute("flex", "1");
stack.setAttribute("id", "webext-panels-stack");
document.documentElement.appendChild(stack);
}
const browser = document.createElementNS(XUL_NS, "browser");
const browser = document.createXULElement("browser");
browser.setAttribute("id", "webext-panels-browser");
browser.setAttribute("type", "content");
browser.setAttribute("disableglobalhistory", "true");

View File

@ -12,8 +12,6 @@ var {
IconDetails,
} = ExtensionParent;
var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
// WeakMap[Extension -> SidebarAction]
let sidebarActionMap = new WeakMap();
@ -149,7 +147,7 @@ this.sidebarAction = class extends ExtensionAPI {
// Use of the broadcaster allows browser-sidebar.js to properly manage the
// checkmarks in the menus.
let broadcaster = document.createElementNS(XUL_NS, "broadcaster");
let broadcaster = document.createXULElement("broadcaster");
broadcaster.setAttribute("id", this.id);
broadcaster.setAttribute("autoCheck", "false");
broadcaster.setAttribute("type", "checkbox");
@ -172,14 +170,14 @@ this.sidebarAction = class extends ExtensionAPI {
header.addEventListener("SidebarShown", this.updateHeader);
// Insert a menuitem for View->Show Sidebars.
let menuitem = document.createElementNS(XUL_NS, "menuitem");
let menuitem = document.createXULElement("menuitem");
menuitem.setAttribute("id", this.menuId);
menuitem.setAttribute("observes", this.id);
menuitem.setAttribute("class", "menuitem-iconic webextension-menuitem");
this.setMenuIcon(menuitem, details);
// Insert a toolbarbutton for the sidebar dropdown selector.
let toolbarbutton = document.createElementNS(XUL_NS, "toolbarbutton");
let toolbarbutton = document.createXULElement("toolbarbutton");
toolbarbutton.setAttribute("id", this.buttonId);
toolbarbutton.setAttribute("observes", this.id);
toolbarbutton.setAttribute("class", "subviewbutton subviewbutton-iconic webextension-menuitem");

View File

@ -127,7 +127,7 @@ this.AboutPreferences = class AboutPreferences {
renderPreferences({document, Preferences, gHomePane}, strings, prefStructure) {
// Helper to create a new element and append it
const createAppend = (tag, parent) => parent.appendChild(
document.createElementNS(XUL_NS, tag));
document.createXULElement(tag));
// Helper to get strings and format with values if necessary
const formatString = id => {

View File

@ -530,14 +530,12 @@
<method name="initContextMenu">
<parameter name="aMenu"/>
<body><![CDATA[
const kXULNS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let stringBundle = document.getBindingParent(this)._stringBundle;
let pasteAndSearch, suggestMenuItem;
let element, label, akey;
element = document.createElementNS(kXULNS, "menuseparator");
element = document.createXULElement("menuseparator");
aMenu.appendChild(element);
let insertLocation = aMenu.firstElementChild;
@ -545,7 +543,7 @@
insertLocation.getAttribute("cmd") != "cmd_paste")
insertLocation = insertLocation.nextElementSibling;
if (insertLocation) {
element = document.createElementNS(kXULNS, "menuitem");
element = document.createXULElement("menuitem");
label = stringBundle.getString("cmd_pasteAndSearch");
element.setAttribute("label", label);
element.setAttribute("anonid", "paste-and-search");
@ -554,7 +552,7 @@
pasteAndSearch = element;
}
element = document.createElementNS(kXULNS, "menuitem");
element = document.createXULElement("menuitem");
label = stringBundle.getString("cmd_clearHistory");
akey = stringBundle.getString("cmd_clearHistory_accesskey");
element.setAttribute("label", label);
@ -562,7 +560,7 @@
element.setAttribute("cmd", "cmd_clearhistory");
aMenu.appendChild(element);
element = document.createElementNS(kXULNS, "menuitem");
element = document.createXULElement("menuitem");
label = stringBundle.getString("cmd_showSuggestions");
akey = stringBundle.getString("cmd_showSuggestions_accesskey");
element.setAttribute("anonid", "toggle-suggest-item");
@ -1508,13 +1506,10 @@
this.settingsButton.id = origin + "-anon-search-settings";
this.settingsButtonCompact.id = origin + "-anon-search-settings-compact";
const kXULNS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let dummyItems = enginesPerRow - (oneOffCount % enginesPerRow || enginesPerRow);
for (let i = 0; i < engines.length; ++i) {
let engine = engines[i];
let button = document.createElementNS(kXULNS, "button");
let button = document.createXULElement("button");
button.id = this._buttonIDForEngine(engine);
let uri = "chrome://browser/skin/search-engine-placeholder.png";
if (engine.iconURI) {
@ -1540,7 +1535,7 @@
let hasDummyItems = !!dummyItems;
while (dummyItems) {
let button = document.createElementNS(kXULNS, "button");
let button = document.createXULElement("button");
button.setAttribute("class", "searchbar-engine-one-off-item dummy last-row");
button.setAttribute("width", buttonWidth);
@ -1589,15 +1584,12 @@
return;
}
const kXULNS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let engines = gBrowser.selectedBrowser.engines;
let tooManyEngines = engines.length > this._addEngineMenuThreshold;
if (tooManyEngines) {
// Make the top-level menu button.
let button = document.createElementNS(kXULNS, "toolbarbutton");
let button = document.createXULElement("toolbarbutton");
list.appendChild(button);
button.classList.add("addengine-item", "badged-button");
button.setAttribute("anonid", "addengine-menu-button");
@ -1616,7 +1608,7 @@
}
// Now make the button's child menupopup.
list = document.createElementNS(kXULNS, "menupopup");
list = document.createXULElement("menupopup");
button.appendChild(list);
list.setAttribute("anonid", "addengine-menu");
list.setAttribute("position", "topright topleft");
@ -1643,7 +1635,7 @@
// handling for free inside menupopups.
let eltType = tooManyEngines ? "menuitem" : "toolbarbutton";
for (let engine of engines) {
let button = document.createElementNS(kXULNS, eltType);
let button = document.createXULElement(eltType);
button.classList.add("addengine-item");
if (!tooManyEngines) {
button.classList.add("badged-button");

View File

@ -4,8 +4,6 @@
var EXPORTED_SYMBOLS = ["RecentlyClosedTabsAndWindowsMenuUtils"];
const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.defineModuleGetter(this, "PluralForm",
@ -138,7 +136,7 @@ function setImage(aItem, aElement) {
*/
function createEntry(aTagName, aIsWindowsFragment, aIndex, aClosedTab,
aDocument, aMenuLabel, aFragment) {
let element = aDocument.createElementNS(kNSXUL, aTagName);
let element = aDocument.createXULElement(aTagName);
element.setAttribute("label", aMenuLabel);
if (aClosedTab.image) {
@ -196,7 +194,7 @@ function createEntry(aTagName, aIsWindowsFragment, aIndex, aClosedTab,
function createRestoreAllEntry(aDocument, aFragment, aPrefixRestoreAll,
aIsWindowsFragment, aRestoreAllLabel,
aEntryCount, aTagName) {
let restoreAllElements = aDocument.createElementNS(kNSXUL, aTagName);
let restoreAllElements = aDocument.createXULElement(aTagName);
restoreAllElements.classList.add("restoreallitem");
restoreAllElements.setAttribute("label", navigatorBundle.GetStringFromName(aRestoreAllLabel));
restoreAllElements.setAttribute("oncommand",
@ -205,7 +203,7 @@ function createRestoreAllEntry(aDocument, aFragment, aPrefixRestoreAll,
if (aPrefixRestoreAll) {
aFragment.insertBefore(restoreAllElements, aFragment.firstChild);
} else {
aFragment.appendChild(aDocument.createElementNS(kNSXUL, "menuseparator"));
aFragment.appendChild(aDocument.createXULElement("menuseparator"));
aFragment.appendChild(restoreAllElements);
}
}

View File

@ -15,7 +15,6 @@ var EXPORTED_SYMBOLS = ["FormAutofillPreferences"];
const BUNDLE_URI = "chrome://formautofill/locale/formautofill.properties";
const MANAGE_ADDRESSES_URL = "chrome://formautofill/content/manageAddresses.xhtml";
const MANAGE_CREDITCARDS_URL = "chrome://formautofill/content/manageCreditCards.xhtml";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://formautofill/FormAutofill.jsm");
@ -68,17 +67,17 @@ FormAutofillPreferences.prototype = {
*/
createPreferenceGroup(document) {
let learnMoreURL = Services.urlFormatter.formatURLPref("app.support.baseURL") + "autofill-card-address";
let formAutofillGroup = document.createElementNS(XUL_NS, "vbox");
let addressAutofill = document.createElementNS(XUL_NS, "hbox");
let addressAutofillCheckboxGroup = document.createElementNS(XUL_NS, "hbox");
let addressAutofillCheckbox = document.createElementNS(XUL_NS, "checkbox");
let addressAutofillCheckboxLabel = document.createElementNS(XUL_NS, "label");
let addressAutofillCheckboxLabelSpacer = document.createElementNS(XUL_NS, "spacer");
let addressAutofillLearnMore = document.createElementNS(XUL_NS, "label");
let savedAddressesBtn = document.createElementNS(XUL_NS, "button");
let formAutofillGroup = document.createXULElement("vbox");
let addressAutofill = document.createXULElement("hbox");
let addressAutofillCheckboxGroup = document.createXULElement("hbox");
let addressAutofillCheckbox = document.createXULElement("checkbox");
let addressAutofillCheckboxLabel = document.createXULElement("label");
let addressAutofillCheckboxLabelSpacer = document.createXULElement("spacer");
let addressAutofillLearnMore = document.createXULElement("label");
let savedAddressesBtn = document.createXULElement("button");
// Wrappers are used to properly compute the search tooltip positions
let savedAddressesBtnWrapper = document.createElementNS(XUL_NS, "hbox");
let savedCreditCardsBtnWrapper = document.createElementNS(XUL_NS, "hbox");
let savedAddressesBtnWrapper = document.createXULElement("hbox");
let savedCreditCardsBtnWrapper = document.createXULElement("hbox");
savedAddressesBtn.className = "accessory-button";
addressAutofillCheckboxLabelSpacer.className = "tail-with-learn-more";
@ -129,13 +128,13 @@ FormAutofillPreferences.prototype = {
};
if (FormAutofill.isAutofillCreditCardsAvailable) {
let creditCardAutofill = document.createElementNS(XUL_NS, "hbox");
let creditCardAutofillCheckboxGroup = document.createElementNS(XUL_NS, "hbox");
let creditCardAutofillCheckbox = document.createElementNS(XUL_NS, "checkbox");
let creditCardAutofillCheckboxLabel = document.createElementNS(XUL_NS, "label");
let creditCardAutofillCheckboxLabelSpacer = document.createElementNS(XUL_NS, "spacer");
let creditCardAutofillLearnMore = document.createElementNS(XUL_NS, "label");
let savedCreditCardsBtn = document.createElementNS(XUL_NS, "button");
let creditCardAutofill = document.createXULElement("hbox");
let creditCardAutofillCheckboxGroup = document.createXULElement("hbox");
let creditCardAutofillCheckbox = document.createXULElement("checkbox");
let creditCardAutofillCheckboxLabel = document.createXULElement("label");
let creditCardAutofillCheckboxLabelSpacer = document.createXULElement("spacer");
let creditCardAutofillLearnMore = document.createXULElement("label");
let savedCreditCardsBtn = document.createXULElement("button");
savedCreditCardsBtn.className = "accessory-button";
creditCardAutofillCheckboxLabelSpacer.className = "tail-with-learn-more";
creditCardAutofillLearnMore.className = "learnMore text-link";

View File

@ -8,7 +8,6 @@ ChromeUtils.defineModuleGetter(this, "PanelMultiView",
"resource:///modules/PanelMultiView.jsm");
var EXPORTED_SYMBOLS = ["TabsPanel"];
const NSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
function setAttributes(element, attrs) {
for (let [name, value] of Object.entries(attrs)) {
@ -216,7 +215,7 @@ class TabsPanel extends TabsListBase {
_createRow(tab) {
let {doc} = this;
let row = doc.createElementNS(NSXUL, "toolbaritem");
let row = doc.createXULElement("toolbaritem");
row.setAttribute("class", "all-tabs-item");
if (this.className) {
row.classList.add(this.className);
@ -225,7 +224,7 @@ class TabsPanel extends TabsListBase {
row.addEventListener("command", this);
this.tabToElement.set(tab, row);
let button = doc.createElementNS(NSXUL, "toolbarbutton");
let button = doc.createXULElement("toolbarbutton");
button.setAttribute("class", "all-tabs-button subviewbutton subviewbutton-iconic");
button.setAttribute("flex", "1");
button.setAttribute("crop", "right");
@ -233,7 +232,7 @@ class TabsPanel extends TabsListBase {
row.appendChild(button);
let secondaryButton = doc.createElementNS(NSXUL, "toolbarbutton");
let secondaryButton = doc.createXULElement("toolbarbutton");
secondaryButton.setAttribute(
"class", "all-tabs-secondary-button subviewbutton subviewbutton-iconic");
secondaryButton.setAttribute("closemenu", "none");

View File

@ -30,10 +30,6 @@
background: transparent;
}
.sidebar-placesTreechildren::-moz-tree-row {
min-height: 24px;
}
:root[uidensity=touch] #search-box,
:root[uidensity=touch] .sidebar-placesTreechildren::-moz-tree-row {
min-height: 32px;
@ -56,8 +52,3 @@
/* Trees */
%include ../../shared/places/tree-icons.inc.css
treechildren:-moz-tree-image(container,selected),
treechildren:-moz-tree-image(selected,focus) {
fill: HighlightText;
}

View File

@ -50,26 +50,3 @@ html {
.textbox-search-clear:not([disabled]) {
cursor: pointer;
}
.item-twisty-container {
background-size: contain;
background-repeat: no-repeat;
background-position: center;
min-width: 9px; /* The image's width is 9 pixels */
height: 9px;
margin: auto;
}
.item.client .item-twisty-container {
background-image: url("chrome://global/skin/tree/twisty-expanded.svg");
-moz-context-properties: fill;
fill: currentColor;
}
.item.client.closed .item-twisty-container {
background-image: url("chrome://global/skin/tree/twisty-collapsed.svg");
}
.item.client.closed .item-twisty-container:dir(rtl) {
background-image: url("chrome://global/skin/tree/twisty-collapsed-rtl.svg");
}

View File

@ -5,14 +5,10 @@
/* Places Organizer Sidebars */
#placesList > treechildren::-moz-tree-row {
background-color: transparent;
border-color: transparent;
padding-bottom: 1px;
height: 24px;
}
#placesList > treechildren::-moz-tree-cell-text {
font-size: 12px;
margin-inline-end: 6px;
}
@ -47,27 +43,6 @@
font-weight: bold;
}
#placesList > treechildren::-moz-tree-twisty {
-moz-appearance: none;
padding: 0 2px;
list-style-image: url("chrome://global/skin/tree/arrow-collapsed.svg");
-moz-context-properties: fill, fill-opacity;
fill: currentColor;
fill-opacity: 0.6;
}
#placesList > treechildren::-moz-tree-twisty(selected) {
fill: currentColor;
}
#placesList > treechildren::-moz-tree-twisty(open) {
list-style-image: url("chrome://global/skin/tree/arrow-expanded.svg");
}
#placesList > treechildren:-moz-locale-dir(rtl)::-moz-tree-twisty(closed) {
list-style-image: url("chrome://global/skin/tree/arrow-collapsed-rtl.svg");
}
@media (-moz-mac-yosemite-theme) {
#placesList > treechildren::-moz-tree-twisty(selected),
#placesList > treechildren::-moz-tree-cell-text(selected) {

View File

@ -50,7 +50,6 @@
.sidebar-placesTreechildren::-moz-tree-twisty(selected),
.sidebar-placesTreechildren::-moz-tree-cell-text(selected) {
color: #fff;
fill-opacity: 1;
font-weight: bold;
}
@ -60,39 +59,16 @@
padding: 4px;
}
.sidebar-placesTreechildren::-moz-tree-twisty {
-moz-appearance: none;
padding: 0 2px;
list-style-image: url("chrome://global/skin/tree/arrow-collapsed.svg");
-moz-context-properties: fill, fill-opacity;
fill: currentColor;
fill-opacity: 0.6;
}
.sidebar-placesTreechildren::-moz-tree-twisty(selected) {
fill: currentColor;
}
.sidebar-placesTreechildren::-moz-tree-twisty(open) {
list-style-image: url("chrome://global/skin/tree/arrow-expanded.svg");
}
.sidebar-placesTreechildren:-moz-locale-dir(rtl)::-moz-tree-twisty(closed) {
list-style-image: url("chrome://global/skin/tree/arrow-collapsed-rtl.svg");
}
@media (-moz-mac-yosemite-theme) {
.sidebar-placesTreechildren::-moz-tree-twisty(selected),
.sidebar-placesTreechildren::-moz-tree-cell-text(selected) {
color: -moz-dialogtext;
fill-opacity: 0.6;
font-weight: 500;
}
.sidebar-placesTreechildren::-moz-tree-twisty(selected, focus),
.sidebar-placesTreechildren::-moz-tree-cell-text(selected, focus) {
color: #fff;
fill-opacity: 1;
}
}
@ -110,7 +86,3 @@
/* Trees */
%include ../../shared/places/tree-icons.inc.css
treechildren:-moz-tree-image(selected,focus) {
fill: HighlightText;
}

View File

@ -37,34 +37,6 @@
-moz-font-smoothing-background-color: -moz-mac-active-source-list-selection;
}
.item.client .item-twisty-container {
min-width: 16px;
height: 16px;
background-image: url("chrome://global/skin/tree/arrow-expanded.svg");
-moz-context-properties: fill, fill-opacity;
fill: currentColor;
fill-opacity: 1;
}
.item.client.closed .item-twisty-container {
background-image: url("chrome://global/skin/tree/arrow-collapsed.svg");
}
.item.client.closed .item-twisty-container:dir(rtl) {
background-image: url("chrome://global/skin/tree/arrow-collapsed-rtl.svg");
}
.item.client.selected:focus .item-twisty-container {
fill-opacity: 1;
}
@media (-moz-mac-yosemite-theme: 0) {
.item.client.selected .item-twisty-container {
fill-opacity: 1;
}
}
@media (-moz-mac-yosemite-theme) {
.item.selected > .item-title-container {
color: -moz-dialogtext;

View File

@ -4,7 +4,6 @@
treechildren:-moz-tree-image {
-moz-context-properties: fill, fill-opacity;
fill: -moz-FieldText;
fill-opacity: 0.7;
}

View File

@ -80,6 +80,23 @@ body {
color: HighlightText;
}
.item.client .item-twisty-container {
min-width: 8px;
height: 8px;
background-image: url("chrome://global/skin/icons/twisty-expanded.svg");
-moz-context-properties: fill, fill-opacity;
fill: currentColor;
fill-opacity: 1;
}
.item.client.closed .item-twisty-container {
background-image: url("chrome://global/skin/icons/twisty-collapsed.svg");
}
.item.client.closed .item-twisty-container:dir(rtl) {
background-image: url("chrome://global/skin/icons/twisty-collapsed-rtl.svg");
}
.client .item.tab > .item-title-container {
padding-inline-start: 35px;
}
@ -90,11 +107,7 @@ body {
.item.client[clientType] > .item-title-container > .item-icon-container {
-moz-context-properties: fill;
fill: #4d4d4d;
}
.item.client[clientType].selected:focus > .item-title-container > .item-icon-container {
fill: white;
fill: currentColor;
}
.item.client[clientType=phone] > .item-title-container > .item-icon-container {
@ -133,6 +146,7 @@ body {
flex-flow: row;
overflow: hidden;
flex-grow: 1;
align-items: center;
padding: 4px;
}

View File

@ -75,35 +75,3 @@
background-repeat: no-repeat;
background-position: center;
}
.item-twisty-container {
background-size: contain;
background-repeat: no-repeat;
background-position: center;
min-width: 9px; /* The image's width is 9 pixels */
height: 9px;
margin: auto;
}
.item.client .item-twisty-container {
background-image: url("chrome://global/skin/tree/twisty-expanded.svg");
-moz-context-properties: fill;
fill: #636363;
}
.item.client.closed .item-twisty-container {
background-image: url("chrome://global/skin/tree/twisty-collapsed.svg");
fill: #b6b6b6;
}
.item.client.closed .item-twisty-container:dir(rtl) {
background-image: url("chrome://global/skin/tree/twisty-collapsed-rtl.svg");
}
.item.client .item-twisty-container:hover {
fill: #4ed0f9;
}
.item.client.selected .item-twisty-container:not(:hover) {
fill: currentColor;
}

View File

@ -6,7 +6,6 @@
"use strict";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const EventEmitter = require("devtools/shared/event-emitter");
const { getCurrentZoom } = require("devtools/shared/layout/utils");
@ -84,7 +83,7 @@ Menu.prototype.popup = function(screenX, screenY, toolbox) {
let popupset = doc.querySelector("popupset");
if (!popupset) {
popupset = doc.createElementNS(XUL_NS, "popupset");
popupset = doc.createXULElement("popupset");
doc.documentElement.appendChild(popupset);
}
// See bug 1285229, on Windows, opening the same popup multiple times in a
@ -96,7 +95,7 @@ Menu.prototype.popup = function(screenX, screenY, toolbox) {
popup.hidePopup();
}
popup = doc.createElementNS(XUL_NS, "menupopup");
popup = doc.createXULElement("menupopup");
popup.setAttribute("menu-api", "true");
popup.setAttribute("consumeoutsideclicks", "true");
@ -131,18 +130,18 @@ Menu.prototype._createMenuItems = function(parent) {
}
if (item.submenu) {
const menupopup = doc.createElementNS(XUL_NS, "menupopup");
const menupopup = doc.createXULElement("menupopup");
item.submenu._createMenuItems(menupopup);
const menu = doc.createElementNS(XUL_NS, "menu");
const menu = doc.createXULElement("menu");
menu.appendChild(menupopup);
applyItemAttributesToNode(item, menu);
parent.appendChild(menu);
} else if (item.type === "separator") {
const menusep = doc.createElementNS(XUL_NS, "menuseparator");
const menusep = doc.createXULElement("menuseparator");
parent.appendChild(menusep);
} else {
const menuitem = doc.createElementNS(XUL_NS, "menuitem");
const menuitem = doc.createXULElement("menuitem");
applyItemAttributesToNode(item, menuitem);
menuitem.addEventListener("command", () => {

View File

@ -11,8 +11,6 @@ var Telemetry = require("devtools/client/shared/telemetry");
const {LocalizationHelper} = require("devtools/shared/l10n");
const L10N = new LocalizationHelper("devtools/client/locales/toolbox.properties");
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
/**
* ToolSidebar provides methods to register tabs in the sidebar.
* It's assumed that the sidebar contains a xul:tabbox.
@ -118,7 +116,7 @@ ToolSidebar.prototype = {
const tabs = this._tabbox.tabs;
// Create a container and insert it first in the tabbox
const allTabsContainer = this._panelDoc.createElementNS(XULNS, "stack");
const allTabsContainer = this._panelDoc.createXULElement("stack");
this._tabbox.insertBefore(allTabsContainer, tabs);
// Move the tabs inside and make them flex
@ -126,7 +124,7 @@ ToolSidebar.prototype = {
tabs.setAttribute("flex", "1");
// Create the dropdown menu next to the tabs
this._allTabsBtn = this._panelDoc.createElementNS(XULNS, "toolbarbutton");
this._allTabsBtn = this._panelDoc.createXULElement("toolbarbutton");
this._allTabsBtn.setAttribute("class", "devtools-sidebar-alltabs");
this._allTabsBtn.setAttribute("end", "0");
this._allTabsBtn.setAttribute("top", "0");
@ -137,7 +135,7 @@ ToolSidebar.prototype = {
this._allTabsBtn.setAttribute("hidden", "true");
allTabsContainer.appendChild(this._allTabsBtn);
const menuPopup = this._panelDoc.createElementNS(XULNS, "menupopup");
const menuPopup = this._panelDoc.createXULElement("menupopup");
this._allTabsBtn.appendChild(menuPopup);
// Listening to tabs overflow event to toggle the alltabs button
@ -189,7 +187,7 @@ ToolSidebar.prototype = {
return;
}
const item = this._panelDoc.createElementNS(XULNS, "menuitem");
const item = this._panelDoc.createXULElement("menuitem");
const idPrefix = "sidebar-alltabs-item-";
item.setAttribute("id", idPrefix + id);
item.setAttribute("label", tab.getAttribute("label"));
@ -230,14 +228,14 @@ ToolSidebar.prototype = {
* tabbox, pass the ID of an existing tab to insert it before that tab instead.
*/
addTab: function(id, url, options = {}) {
const iframe = this._panelDoc.createElementNS(XULNS, "iframe");
const iframe = this._panelDoc.createXULElement("iframe");
iframe.className = "iframe-" + id;
iframe.setAttribute("flex", "1");
iframe.setAttribute("src", url);
iframe.tooltip = "aHTMLTooltip";
// Creating the tab and adding it to the tabbox
const tab = this._panelDoc.createElementNS(XULNS, "tab");
const tab = this._panelDoc.createXULElement("tab");
tab.setAttribute("id", this.TAB_ID_PREFIX + id);
tab.setAttribute("crop", "end");
@ -272,7 +270,7 @@ ToolSidebar.prototype = {
iframe.addEventListener("load", onIFrameLoaded, true);
const tabpanel = this._panelDoc.createElementNS(XULNS, "tabpanel");
const tabpanel = this._panelDoc.createXULElement("tabpanel");
tabpanel.setAttribute("id", this.TABPANEL_ID_PREFIX + id);
tabpanel.appendChild(iframe);
@ -283,7 +281,7 @@ ToolSidebar.prototype = {
this._tabbox.tabpanels.appendChild(tabpanel);
}
this._tooltip = this._panelDoc.createElementNS(XULNS, "tooltip");
this._tooltip = this._panelDoc.createXULElement("tooltip");
this._tooltip.id = "aHTMLTooltip";
tabpanel.appendChild(this._tooltip);
this._tooltip.page = true;

View File

@ -10,12 +10,13 @@ const {
TOGGLE_REQUEST_FILTER_TYPE,
ENABLE_REQUEST_FILTER_TYPE_ONLY,
SET_REQUEST_FILTER_TEXT,
SELECT_DETAILS_PANEL_TAB,
} = require("../constants");
/**
* Event telemetry middleware is responsible for logging
* specific filter events to telemetry. This telemetry
* helps to track Net panel filtering usage.
* various events to telemetry. This helps to track Network
* panel usage.
*/
function eventTelemetryMiddleware(connector, telemetry) {
return store => next => action => {
@ -27,6 +28,7 @@ function eventTelemetryMiddleware(connector, telemetry) {
}
const state = store.getState();
const sessionId = toolbox.sessionId;
const filterChangeActions = [
TOGGLE_REQUEST_FILTER_TYPE,
@ -34,13 +36,25 @@ function eventTelemetryMiddleware(connector, telemetry) {
SET_REQUEST_FILTER_TEXT,
];
// Record telemetry event when filter changes.
if (filterChangeActions.includes(action.type)) {
filterChange({
action,
state,
oldState,
telemetry,
sessionId: toolbox.sessionId,
sessionId,
});
}
// Record telemetry event when side panel is selected.
if (action.type == SELECT_DETAILS_PANEL_TAB) {
sidePanelChange({
action,
state,
oldState,
telemetry,
sessionId,
});
}
@ -48,6 +62,10 @@ function eventTelemetryMiddleware(connector, telemetry) {
};
}
/**
* This helper function is executed when filter related action is fired.
* It's responsible for recording "filters_changed" telemetry event.
*/
function filterChange({action, state, oldState, telemetry, sessionId}) {
const oldFilterState = oldState.filters;
const filterState = state.filters;
@ -79,7 +97,20 @@ function filterChange({action, state, oldState, telemetry, sessionId}) {
"trigger": trigger,
"active": activeFilters.join(","),
"inactive": inactiveFilters.join(","),
"session_id": sessionId
"session_id": sessionId,
});
}
/**
* This helper function is executed when side panel is selected.
* It's responsible for recording "sidepanel_tool_changed"
* telemetry event.
*/
function sidePanelChange({action, state, oldState, telemetry, sessionId}) {
telemetry.recordEvent("devtools.main", "sidepanel_changed", "netmonitor", null, {
"oldpanel": oldState.ui.detailsPanelSelectedTab,
"newpanel": state.ui.detailsPanelSelectedTab,
"session_id": sessionId,
});
}

View File

@ -186,6 +186,7 @@ skip-if = true # Bug 1373558
[browser_net_status-codes.js]
[browser_net_streaming-response.js]
[browser_net_telemetry_filters_changed.js]
[browser_net_telemetry_sidepanel_changed.js]
[browser_net_throttle.js]
[browser_net_timeline_ticks.js]
skip-if = true # TODO: fix the test

View File

@ -42,6 +42,8 @@ add_task(async function() {
trigger: "html",
active: "html",
inactive: "all,css,js,xhr,fonts,images,media,ws,other",
}, {
method: "filters_changed"
});
info("Click on the 'CSS' filter");
@ -52,6 +54,8 @@ add_task(async function() {
trigger: "css",
active: "html,css",
inactive: "all,js,xhr,fonts,images,media,ws,other",
}, {
method: "filters_changed"
});
info("Filter the output using the text filter input");
@ -64,6 +68,8 @@ add_task(async function() {
trigger: "text",
active: "html,css",
inactive: "all,js,xhr,fonts,images,media,ws,other",
}, {
method: "filters_changed"
});
return teardown(monitor);
@ -80,30 +86,3 @@ function setFreetextFilter(monitor, value) {
EventUtils.synthesizeKey(ch, {}, monitor.panelWin);
}
}
function checkTelemetryEvent(expectedEvent) {
const events = getFiltersChangedEventsExtra();
is(events.length, 1, "There was only 1 event logged");
const [event] = events;
ok(event.session_id > 0, "There is a valid session_id in the logged event");
const f = e => JSON.stringify(e, null, 2);
is(f(event), f({
...expectedEvent,
"session_id": event.session_id
}), "The event has the expected data");
}
function getFiltersChangedEventsExtra() {
// Retrieve and clear telemetry events.
const snapshot = Services.telemetry.snapshotEvents(OPTOUT, true);
const filtersChangedEvents = snapshot.parent.filter(event =>
event[1] === "devtools.main" &&
event[2] === "filters_changed" &&
event[3] === "netmonitor"
);
// Since we already know we have the correct event, we only return the `extra` field
// that was passed to it (which is event[5] here).
return filtersChangedEvents.map(event => event[5]);
}

View File

@ -0,0 +1,55 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* 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";
const OPTOUT = Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTOUT;
/**
* Test the sidepanel_changed telemetry event.
*/
add_task(async function() {
const { tab, monitor } = await initNetMonitor(SIMPLE_URL);
info("Starting test... ");
const { document, store, windowRequire } = monitor.panelWin;
const Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
store.dispatch(Actions.batchEnable(false));
// Remove all telemetry events (you can check about:telemetry).
Services.telemetry.clearEvents();
// Ensure no events have been logged
const snapshot = Services.telemetry.snapshotEvents(OPTOUT, true);
ok(!snapshot.parent, "No events have been logged for the main process");
// Reload to have one request in the list.
const waitForEvents = waitForNetworkEvents(monitor, 1);
tab.linkedBrowser.loadURI(SIMPLE_URL);
await waitForEvents;
// Click on a request and wait till the default "Headers" side panel is opened.
info("Click on a request");
const waitForHeaders = waitUntil(() => document.querySelector(".headers-overview"));
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll(".request-list-item")[0]);
await waitForHeaders;
await waitForRequestData(store, ["requestHeaders", "responseHeaders"]);
// Click on the Cookies panel and wait till it's opened.
info("Click on the Cookies panel");
EventUtils.sendMouseEvent({ type: "click" },
document.querySelector("#cookies-tab"));
await waitForRequestData(store, ["requestCookies", "responseCookies"]);
checkTelemetryEvent({
oldpanel: "headers",
newpanel: "cookies",
}, {
method: "sidepanel_changed"
});
return teardown(monitor);
});

View File

@ -799,3 +799,42 @@ function waitForRequestData(store, fields, id) {
return true;
});
}
// Telemetry
/**
* Helper for verifying telemetry event.
*
* @param Object expectedEvent object representing expected event data.
* @param Object query fields specifying category, method and object
* of the target telemetry event.
*/
function checkTelemetryEvent(expectedEvent, query) {
const events = queryTelemetryEvents(query);
is(events.length, 1, "There was only 1 event logged");
const [event] = events;
ok(event.session_id > 0, "There is a valid session_id in the logged event");
const f = e => JSON.stringify(e, null, 2);
is(f(event), f({
...expectedEvent,
"session_id": event.session_id
}), "The event has the expected data");
}
function queryTelemetryEvents(query) {
const OPTOUT = Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTOUT;
const snapshot = Services.telemetry.snapshotEvents(OPTOUT, true);
const category = query.category || "devtools.main";
const object = query.object || "netmonitor";
const filtersChangedEvents = snapshot.parent.filter(event =>
event[1] === category &&
event[2] === query.method &&
event[3] === object
);
// Return the `extra` field (which is event[5]e).
return filtersChangedEvents.map(event => event[5]);
}

View File

@ -12,7 +12,6 @@ loader.lazyRequireGetter(this, "naturalSortCaseInsensitive",
"devtools/client/shared/natural-sort", true);
const {KeyCodes} = require("devtools/client/shared/keycodes");
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const HTML_NS = "http://www.w3.org/1999/xhtml";
const AFTER_SCROLL_DELAY = 100;
@ -77,7 +76,7 @@ function TableWidget(node, options = {}) {
this.removableColumns = removableColumns !== false;
this.cellContextMenuId = cellContextMenuId;
this.tbody = this.document.createElementNS(XUL_NS, "hbox");
this.tbody = this.document.createXULElement("hbox");
this.tbody.className = "table-widget-body theme-body";
this.tbody.setAttribute("flex", "1");
this.tbody.setAttribute("tabindex", "0");
@ -85,7 +84,7 @@ function TableWidget(node, options = {}) {
this.afterScroll = this.afterScroll.bind(this);
this.tbody.addEventListener("scroll", this.onScroll.bind(this));
this.placeholder = this.document.createElementNS(XUL_NS, "label");
this.placeholder = this.document.createXULElement("label");
this.placeholder.className = "plain table-widget-empty-text";
this.placeholder.setAttribute("flex", "1");
this._parent.appendChild(this.placeholder);
@ -644,11 +643,11 @@ TableWidget.prototype = {
setupHeadersContextMenu: function() {
let popupset = this.document.getElementsByTagName("popupset")[0];
if (!popupset) {
popupset = this.document.createElementNS(XUL_NS, "popupset");
popupset = this.document.createXULElement("popupset");
this.document.documentElement.appendChild(popupset);
}
this.menupopup = this.document.createElementNS(XUL_NS, "menupopup");
this.menupopup = this.document.createXULElement("menupopup");
this.menupopup.id = "table-widget-column-select";
this.menupopup.addEventListener("command", this.onPopupCommand);
popupset.appendChild(this.menupopup);
@ -678,7 +677,7 @@ TableWidget.prototype = {
continue;
}
const menuitem = this.document.createElementNS(XUL_NS, "menuitem");
const menuitem = this.document.createXULElement("menuitem");
menuitem.setAttribute("label", column.header.getAttribute("value"));
menuitem.setAttribute("data-id", column.id);
menuitem.setAttribute("type", "checkbox");
@ -1045,13 +1044,13 @@ function Column(table, id, header) {
// This wrapping element is required solely so that position:sticky works on
// the headers of the columns.
this.wrapper = this.document.createElementNS(XUL_NS, "vbox");
this.wrapper = this.document.createXULElement("vbox");
this.wrapper.className = "table-widget-wrapper";
this.wrapper.setAttribute("flex", "1");
this.wrapper.setAttribute("tabindex", "0");
this.tbody.appendChild(this.wrapper);
this.splitter = this.document.createElementNS(XUL_NS, "splitter");
this.splitter = this.document.createXULElement("splitter");
this.splitter.className = "devtools-side-splitter";
this.tbody.appendChild(this.splitter);
@ -1060,7 +1059,7 @@ function Column(table, id, header) {
this.column.className = "table-widget-column";
this.wrapper.appendChild(this.column);
this.header = this.document.createElementNS(XUL_NS, "label");
this.header = this.document.createXULElement("label");
this.header.className = "devtools-toolbar table-widget-column-header";
this.header.setAttribute("value", header);
this.column.appendChild(this.header);
@ -1565,7 +1564,7 @@ function Cell(column, item, nextCell) {
const document = column.document;
this.wrapTextInElements = column.wrapTextInElements;
this.label = document.createElementNS(XUL_NS, "label");
this.label = document.createXULElement("label");
this.label.setAttribute("crop", "end");
this.label.className = "plain table-widget-cell";
@ -1737,7 +1736,7 @@ EditableFieldsEngine.prototype = {
get textbox() {
if (!this._textbox) {
const doc = this.root.ownerDocument;
this._textbox = doc.createElementNS(XUL_NS, "textbox");
this._textbox = doc.createXULElement("textbox");
this._textbox.id = this.INPUT_ID;
this._textbox.setAttribute("flex", "1");

View File

@ -878,7 +878,7 @@ HTMLTooltip.prototype = {
},
_createXulPanelWrapper: function() {
const panel = this.doc.createElementNS(XUL_NS, "panel");
const panel = this.doc.createXULElement("panel");
// XUL panel is only a way to display DOM elements outside of the document viewport,
// so disable all features that impact the behavior.

View File

@ -1180,9 +1180,10 @@ WebConsoleActor.prototype =
matches = result.matches || [];
matchProp = result.matchProp;
// We consider '$' as alphanumerc because it is used in the names of some
// helper functions.
const lastNonAlphaIsDot = /[.][a-zA-Z0-9$]*$/.test(reqText);
// We consider '$' as alphanumeric because it is used in the names of some
// helper functions; we also consider whitespace as alphanum since it should not
// be seen as break in the evaled string.
const lastNonAlphaIsDot = /[.][a-zA-Z0-9$\s]*$/.test(reqText);
if (!lastNonAlphaIsDot) {
matches = matches.concat(this._getWebConsoleCommandsCache().filter(n =>
// filter out `screenshot` command as it is inaccessible without

View File

@ -51,7 +51,7 @@ function hasArrayIndex(str) {
*
* {
* state: STATE_NORMAL|STATE_QUOTE|STATE_DQUOTE,
* startPos: index of where the last statement begins
* lastStatement: the last statement in the string
* }
*/
function findCompletionBeginning(str) {
@ -60,8 +60,11 @@ function findCompletionBeginning(str) {
let state = STATE_NORMAL;
let start = 0;
let c;
for (let i = 0; i < str.length; i++) {
c = str[i];
// Use an array in order to handle character with a length > 2 (e.g. 😎).
const characters = Array.from(str);
for (let i = 0; i < characters.length; i++) {
c = characters[i];
switch (state) {
// Normal JS state.
@ -73,7 +76,33 @@ function findCompletionBeginning(str) {
} else if (c == ";") {
start = i + 1;
} else if (c == " ") {
start = i + 1;
const before = characters.slice(0, i);
const after = characters.slice(i + 1);
const trimmedBefore = Array.from(before.join("").trimRight());
const trimmedAfter = Array.from(after.join("").trimLeft());
const nextNonSpaceChar = trimmedAfter[0];
const nextNonSpaceCharIndex = after.indexOf(nextNonSpaceChar);
const previousNonSpaceChar = trimmedBefore[trimmedBefore.length - 1];
// If the previous meaningful char was a dot and there is no meaningful char
// after, we can break out of the loop.
if (previousNonSpaceChar === "." && !nextNonSpaceChar) {
break;
}
if (nextNonSpaceChar) {
// If the previous char wasn't a dot, and the next one isn't a dot either,
// update the start pos.
if (previousNonSpaceChar !== "." && nextNonSpaceChar !== ".") {
start = i + nextNonSpaceCharIndex;
}
// Let's jump to handle the next non-space char.
i = i + nextNonSpaceCharIndex;
} else {
// There's only spaces after that, so we can break out of the loop.
break;
}
} else if (OPEN_BODY.includes(c)) {
bodyStack.push({
token: c,
@ -125,7 +154,7 @@ function findCompletionBeginning(str) {
return {
state: state,
startPos: start
lastStatement: characters.slice(start).join("")
};
}
@ -165,20 +194,20 @@ function JSPropertyProvider(dbgObject, anEnvironment, inputValue, cursor) {
// Analyse the inputValue and find the beginning of the last part that
// should be completed.
const beginning = findCompletionBeginning(inputValue);
const {err, state, lastStatement} = findCompletionBeginning(inputValue);
// There was an error analysing the string.
if (beginning.err) {
if (err) {
return null;
}
// If the current state is not STATE_NORMAL, then we are inside of an string
// which means that no completion is possible.
if (beginning.state != STATE_NORMAL) {
if (state != STATE_NORMAL) {
return null;
}
const completionPart = inputValue.substring(beginning.startPos);
const completionPart = lastStatement;
const lastDot = completionPart.lastIndexOf(".");
// Don't complete on just an empty string.
@ -201,7 +230,7 @@ function JSPropertyProvider(dbgObject, anEnvironment, inputValue, cursor) {
// If there were parse errors this won't exist.
if (lastBody) {
const expression = lastBody.expression;
const matchProp = completionPart.slice(lastDot + 1);
const matchProp = completionPart.slice(lastDot + 1).trimLeft();
if (expression.type === "ArrayExpression") {
return getMatchedProps(Array.prototype, matchProp);
} else if (expression.type === "Literal" &&

View File

@ -12,214 +12,236 @@
<p>Test for JavaScript terminal autocomplete functionality</p>
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForExplicitFinish();
const {
MAX_AUTOCOMPLETE_ATTEMPTS,
MAX_AUTOCOMPLETIONS
} = require("devtools/shared/webconsole/js-property-provider");
let gState;
let {MAX_AUTOCOMPLETE_ATTEMPTS,MAX_AUTOCOMPLETIONS} = require("devtools/shared/webconsole/js-property-provider");
addEventListener("load", startTest);
function evaluateJS(input, options = {}) {
return new Promise((resolve, reject) => {
gState.client.evaluateJSAsync(input, resolve, options);
});
}
async function startTest() {
// First run the tests with a tab as a target.
let state = await new Promise(resolve => attachConsoleToTab(["PageError"], resolve));
await performTests({state, isWorker: false});
function autocompletePromise(str, cursor = str.length, frameActor) {
return gState.client.autocomplete(str, cursor, frameActor);
}
// Then run the tests with a worker as a target.
state = await new Promise(resolve => attachConsoleToWorker(["PageError"], resolve));
await performTests({state, isWorker: true});
// This test runs all of its assertions twice - once with
// the tab as a target and once with a worker
let runningInTab = true;
function startTest({worker}) {
if (worker) {
attachConsoleToWorker(["PageError"], onAttach.bind(null, true));
} else {
attachConsoleToTab(["PageError"], onAttach.bind(null, false));
}
};
let onAttach = async function (isWorker, aState, response) {
gState = aState;
let longStrLength = DebuggerServer.LONG_STRING_LENGTH;
// Set up the global variables needed to test autocompletion
// in the target.
let script = `
// This is for workers so autocomplete acts the same
if (!this.window) {
window = this;
}
window.foobarObject = Object.create(null);
window.foobarObject.foo = 1;
window.foobarObject.foobar = 2;
window.foobarObject.foobaz = 3;
window.foobarObject.omg = 4;
window.foobarObject.omgfoo = 5;
window.foobarObject.strfoo = "foobarz";
window.foobarObject.omgstr = "foobarz" +
(new Array(${longStrLength})).join("abb");
window.largeObject1 = Object.create(null);
for (let i = 0; i < ${MAX_AUTOCOMPLETE_ATTEMPTS + 1}; i++) {
window.largeObject1['a' + i] = i;
}
window.largeObject2 = Object.create(null);
for (let i = 0; i < ${MAX_AUTOCOMPLETIONS * 2}; i++) {
window.largeObject2['a' + i] = i;
}
window.proxy1 = new Proxy({foo: 1}, {
getPrototypeOf() { throw new Error() }
});
window.proxy2 = new Proxy(Object.create(Object.create(null, {foo:{}})), {
ownKeys() { throw new Error() }
});
`;
await evaluateJS(script);
let tests = [doAutocomplete1, doAutocomplete2, doAutocomplete3,
doAutocomplete4, doAutocompleteLarge1,
doAutocompleteLarge2, doAutocompleteProxyThrowsPrototype,
doAutocompleteProxyThrowsOwnKeys];
if (!isWorker) {
// `Cu` is not defined in workers, then we can't test `Cu.Sandbox`
tests.push(doAutocompleteSandbox);
SimpleTest.finish();
}
runTests(tests, testEnd);
};
async function performTests({state, isWorker}) {
// Set up the global variables needed to test autocompletion in the target.
const script = `
// This is for workers so autocomplete acts the same
if (!this.window) {
window = this;
}
async function doAutocomplete1() {
info("test autocomplete for 'window.foo'");
let response = await autocompletePromise("window.foo");
let matches = response.matches;
window.foobarObject = Object.create(null);
window.foobarObject.foo = 1;
window.foobarObject.foobar = 2;
window.foobarObject.foobaz = 3;
window.foobarObject.omg = 4;
window.foobarObject.omgfoo = 5;
window.foobarObject.strfoo = "foobarz";
window.foobarObject.omgstr = "foobarz" +
(new Array(${DebuggerServer.LONG_STRING_LENGTH})).join("abb");
window.largeObject1 = Object.create(null);
for (let i = 0; i < ${MAX_AUTOCOMPLETE_ATTEMPTS + 1}; i++) {
window.largeObject1['a' + i] = i;
}
is(response.matchProp, "foo", "matchProp");
is(matches.length, 1, "matches.length");
is(matches[0], "foobarObject", "matches[0]");
window.largeObject2 = Object.create(null);
for (let i = 0; i < ${MAX_AUTOCOMPLETIONS * 2}; i++) {
window.largeObject2['a' + i] = i;
}
nextTest();
}
async function doAutocomplete2() {
info("test autocomplete for 'window.foobarObject.'");
let response = await autocompletePromise("window.foobarObject.");
let matches = response.matches;
ok(!response.matchProp, "matchProp");
is(matches.length, 7, "matches.length");
checkObject(matches,
["foo", "foobar", "foobaz", "omg", "omgfoo", "omgstr", "strfoo"]);
nextTest();
}
async function doAutocomplete3() {
// Check that completion suggestions are offered inside the string.
info("test autocomplete for 'dump(window.foobarObject.)'");
let response = await autocompletePromise("dump(window.foobarObject.)", 25);
let matches = response.matches;
ok(!response.matchProp, "matchProp");
is(matches.length, 7, "matches.length");
checkObject(matches,
["foo", "foobar", "foobaz", "omg", "omgfoo", "omgstr", "strfoo"]);
nextTest();
}
async function doAutocomplete4() {
// Check that completion requests can have no suggestions.
info("test autocomplete for 'dump(window.foobarObject.)'");
let response = await autocompletePromise("dump(window.foobarObject.)");
ok(!response.matchProp, "matchProp");
is(response.matches.length, 0, "matches.length");
nextTest();
}
async function doAutocompleteLarge1() {
// Check that completion requests with too large objects will
// have no suggestions.
info("test autocomplete for 'window.largeObject1.'");
let response = await autocompletePromise("window.largeObject1.");
ok(!response.matchProp, "matchProp");
info (response.matches.join("|"));
is(response.matches.length, 0, "Bailed out with too many properties");
nextTest();
}
async function doAutocompleteLarge2() {
// Check that completion requests with pretty large objects will
// have MAX_AUTOCOMPLETIONS suggestions
info("test autocomplete for 'window.largeObject2.'");
let response = await autocompletePromise("window.largeObject2.");
ok(!response.matchProp, "matchProp");
is(response.matches.length, MAX_AUTOCOMPLETIONS, "matches.length is MAX_AUTOCOMPLETIONS");
nextTest();
}
async function doAutocompleteProxyThrowsPrototype() {
// Check that completion provides own properties even if [[GetPrototypeOf]] throws.
info("test autocomplete for 'window.proxy1.'");
let response = await autocompletePromise("window.proxy1.");
ok(!response.matchProp, "matchProp");
is(response.matches.length, 1, "matches.length");
checkObject(response.matches, ["foo"]);
nextTest();
}
async function doAutocompleteProxyThrowsOwnKeys() {
// Check that completion provides inherited properties even if [[OwnPropertyKeys]] throws.
info("test autocomplete for 'window.proxy2.'");
let response = await autocompletePromise("window.proxy2.");
ok(!response.matchProp, "matchProp");
is(response.matches.length, 1, "matches.length");
checkObject(response.matches, ["foo"]);
nextTest();
}
async function doAutocompleteSandbox() {
// Check that completion provides inherited properties even if [[OwnPropertyKeys]] throws.
info("test autocomplete for 'Cu.Sandbox.'");
let response = await autocompletePromise("Cu.Sandbox.");
ok(!response.matchProp, "matchProp");
let keys = Object.getOwnPropertyNames(Object.prototype).sort();
is(response.matches.length, keys.length, "matches.length");
checkObject(response.matches, keys);
nextTest();
}
function testEnd()
{
// If this is the first run, reload the page and do it again
// in a worker. Otherwise, end the test.
closeDebugger(gState, function() {
gState = null;
if (runningInTab) {
runningInTab = false;
startTest({
worker: true
window.proxy1 = new Proxy({foo: 1}, {
getPrototypeOf() { throw new Error() }
});
} else {
SimpleTest.finish();
}
});
}
window.proxy2 = new Proxy(Object.create(Object.create(null, {foo:{}})), {
ownKeys() { throw new Error() }
});
window.emojiObject = Object.create(null);
window.emojiObject["😎"] = "😎";
`;
await state.client.evaluateJSAsync(script);
addEventListener("load", () => {
startTest({
worker: false
});
});
const tests = [
doAutocomplete1,
doAutocomplete2,
doAutocomplete3,
doAutocomplete4,
doAutocompleteLarge1,
doAutocompleteLarge2,
doAutocompleteProxyThrowsPrototype,
doAutocompleteProxyThrowsOwnKeys,
doAutocompleteDotSurroundedBySpaces,
doAutocompleteAfterOr,
];
if (!isWorker) {
// `Cu` is not defined in workers, then we can't test `Cu.Sandbox`
tests.push(doAutocompleteSandbox);
// Array literal completion isn't handled in Workers yet.
tests.push(doAutocompleteArray);
}
for (const test of tests) {
await test(state.client);
}
await closeDebugger(state);
}
async function doAutocomplete1(client) {
info("test autocomplete for 'window.foo'");
let response = await client.autocomplete("window.foo");
let matches = response.matches;
is(response.matchProp, "foo", "matchProp");
is(matches.length, 1, "matches.length");
is(matches[0], "foobarObject", "matches[0]");
}
async function doAutocomplete2(client) {
info("test autocomplete for 'window.foobarObject.'");
let response = await client.autocomplete("window.foobarObject.");
let matches = response.matches;
ok(!response.matchProp, "matchProp");
is(matches.length, 7, "matches.length");
checkObject(matches,
["foo", "foobar", "foobaz", "omg", "omgfoo", "omgstr", "strfoo"]);
}
async function doAutocomplete3(client) {
// Check that completion suggestions are offered inside the string.
info("test autocomplete for 'dump(window.foobarObject.)'");
let response = await client.autocomplete("dump(window.foobarObject.)", 25);
let matches = response.matches;
ok(!response.matchProp, "matchProp");
is(matches.length, 7, "matches.length");
checkObject(matches,
["foo", "foobar", "foobaz", "omg", "omgfoo", "omgstr", "strfoo"]);
}
async function doAutocomplete4(client) {
// Check that completion requests can have no suggestions.
info("test autocomplete for 'dump(window.foobarObject.)'");
let response = await client.autocomplete("dump(window.foobarObject.)");
ok(!response.matchProp, "matchProp");
is(response.matches.length, 0, "matches.length");
}
async function doAutocompleteLarge1(client) {
// Check that completion requests with too large objects will
// have no suggestions.
info("test autocomplete for 'window.largeObject1.'");
let response = await client.autocomplete("window.largeObject1.");
ok(!response.matchProp, "matchProp");
info (response.matches.join("|"));
is(response.matches.length, 0, "Bailed out with too many properties");
}
async function doAutocompleteLarge2(client) {
// Check that completion requests with pretty large objects will
// have MAX_AUTOCOMPLETIONS suggestions
info("test autocomplete for 'window.largeObject2.'");
let response = await client.autocomplete("window.largeObject2.");
ok(!response.matchProp, "matchProp");
is(response.matches.length, MAX_AUTOCOMPLETIONS, "matches.length is MAX_AUTOCOMPLETIONS");
}
async function doAutocompleteProxyThrowsPrototype(client) {
// Check that completion provides own properties even if [[GetPrototypeOf]] throws.
info("test autocomplete for 'window.proxy1.'");
let response = await client.autocomplete("window.proxy1.");
ok(!response.matchProp, "matchProp");
is(response.matches.length, 1, "matches.length");
checkObject(response.matches, ["foo"]);
}
async function doAutocompleteProxyThrowsOwnKeys(client) {
// Check that completion provides inherited properties even if [[OwnPropertyKeys]] throws.
info("test autocomplete for 'window.proxy2.'");
let response = await client.autocomplete("window.proxy2.");
ok(!response.matchProp, "matchProp");
is(response.matches.length, 1, "matches.length");
checkObject(response.matches, ["foo"]);
}
async function doAutocompleteSandbox(client) {
// Check that completion provides inherited properties even if [[OwnPropertyKeys]] throws.
info("test autocomplete for 'Cu.Sandbox.'");
let response = await client.autocomplete("Cu.Sandbox.");
ok(!response.matchProp, "matchProp");
let keys = Object.getOwnPropertyNames(Object.prototype).sort();
is(response.matches.length, keys.length, "matches.length");
checkObject(response.matches, keys);
}
async function doAutocompleteArray(client) {
info("test autocomplete for [1,2,3]");
let response = await client.autocomplete("[1,2,3].");
let {matches} = response;
ok(matches.length > 0, "There are completion results for the array");
ok(matches.includes("length") && matches.includes("filter"),
"Array autocomplete contains expected results");
info("test autocomplete for '[] . '");
matches = (await client.autocomplete("[] . ")).matches;
ok(matches.length > 1);
ok(matches.includes("length") && matches.includes("filter"),
"Array autocomplete contains expected results");
ok(!matches.includes("copy"), "Array autocomplete does not contain helpers");
}
async function doAutocompleteDotSurroundedBySpaces(client) {
info("test autocomplete for 'window.foobarObject\n .'");
let {matches} = await client.autocomplete("window.foobarObject\n .");
is(matches.length, 7);
checkObject(matches,
["foo", "foobar", "foobaz", "omg", "omgfoo", "omgstr", "strfoo"]);
info("test autocomplete for 'window.foobarObject\n .o'");
matches = (await client.autocomplete("window.foobarObject\n .o")).matches;
is(matches.length, 3);
checkObject(matches, ["omg", "omgfoo", "omgstr"]);
info("test autocomplete for 'window.foobarObject\n .\n s'");
matches = (await client.autocomplete("window.foobarObject\n .\n s")).matches;
is(matches.length, 1);
checkObject(matches, ["strfoo"]);
info("test autocomplete for 'window.foobarObject\n . '");
matches = (await client.autocomplete("window.foobarObject\n . ")).matches;
is(matches.length, 7);
checkObject(matches,
["foo", "foobar", "foobaz", "omg", "omgfoo", "omgstr", "strfoo"]);
matches =
(await client.autocomplete("window.foobarObject. foo ; window.foo")).matches;
is(matches.length, 1);
checkObject(matches, ["foobarObject"]);
matches =
(await client.autocomplete("window.emojiObject . ")).matches;
is(matches.length, 1);
checkObject(matches, ["😎"]);
}
async function doAutocompleteAfterOr(client) {
info("test autocomplete for 'true || foo'");
const {matches} = await client.autocomplete("true || foobar");
is(matches.length, 1, "autocomplete returns expected results");
is(matches.join("-"), "foobarObject");
}
</script>
</body>
</html>

View File

@ -2362,13 +2362,20 @@ nsRange::CloneParentsBetween(nsINode *aAncestor,
if (aAncestor == aNode)
return NS_OK;
nsCOMPtr<nsINode> firstParent, lastParent;
nsCOMPtr<nsINode> parent = aNode->GetParentNode();
AutoTArray<nsCOMPtr<nsINode>, 16> parentStack;
nsCOMPtr<nsINode> parent = aNode->GetParentNode();
while(parent && parent != aAncestor)
{
parentStack.AppendElement(parent);
parent = parent->GetParentNode();
}
nsCOMPtr<nsINode> firstParent;
nsCOMPtr<nsINode> lastParent;
for (int32_t i = parentStack.Length() - 1; i >= 0; i--) {
ErrorResult rv;
nsCOMPtr<nsINode> clone = parent->CloneNode(false, rv);
nsCOMPtr<nsINode> clone = parentStack[i]->CloneNode(false, rv);
if (rv.Failed()) {
return rv.StealNSResult();
@ -2377,23 +2384,20 @@ nsRange::CloneParentsBetween(nsINode *aAncestor,
return NS_ERROR_FAILURE;
}
if (! firstParent) {
firstParent = lastParent = clone;
} else {
clone->AppendChild(*lastParent, rv);
if (rv.Failed()) return rv.StealNSResult();
if (!lastParent) {
lastParent = clone;
} else {
firstParent->AppendChild(*clone, rv);
if (rv.Failed()) {
return rv.StealNSResult();
}
}
parent = parent->GetParentNode();
firstParent = clone;
}
*aClosestAncestor = firstParent;
NS_IF_ADDREF(*aClosestAncestor);
*aFarthestAncestor = lastParent;
NS_IF_ADDREF(*aFarthestAncestor);
firstParent.forget(aClosestAncestor);
lastParent.forget(aFarthestAncestor);
return NS_OK;
}

View File

@ -848,6 +848,7 @@ ParserBase::ParserBase(JSContext* cx, LifoAlloc& alloc,
#endif
isUnexpectedEOF_(false),
awaitHandling_(AwaitIsName),
inParametersOfAsyncFunction_(false),
parseGoal_(uint8_t(parseGoal))
{
cx->frontendCollectionPool().addActiveCompilation();
@ -932,6 +933,29 @@ GeneralParser<ParseHandler, CharT>::setAwaitHandling(AwaitHandling awaitHandling
asFinalParser()->setAwaitHandling(awaitHandling);
}
template <typename CharT>
void
Parser<SyntaxParseHandler, CharT>::setInParametersOfAsyncFunction(bool inParameters)
{
this->inParametersOfAsyncFunction_ = inParameters;
}
template <typename CharT>
void
Parser<FullParseHandler, CharT>::setInParametersOfAsyncFunction(bool inParameters)
{
this->inParametersOfAsyncFunction_ = inParameters;
if (SyntaxParser* syntaxParser = getSyntaxParser())
syntaxParser->setInParametersOfAsyncFunction(inParameters);
}
template <class ParseHandler, typename CharT>
inline void
GeneralParser<ParseHandler, CharT>::setInParametersOfAsyncFunction(bool inParameters)
{
asFinalParser()->setInParametersOfAsyncFunction(inParameters);
}
ObjectBox*
ParserBase::newObjectBox(JSObject* obj)
{
@ -3822,6 +3846,7 @@ GeneralParser<ParseHandler, CharT>::functionFormalParametersAndBody(InHandling i
? AwaitIsKeyword
: AwaitIsName;
AutoAwaitIsKeyword<ParseHandler, CharT> awaitIsKeyword(this, awaitHandling);
AutoInParametersOfAsyncFunction<ParseHandler, CharT> inParameters(this, funbox->isAsync());
if (!functionArguments(yieldHandling, kind, *pn))
return false;
}
@ -3883,6 +3908,7 @@ GeneralParser<ParseHandler, CharT>::functionFormalParametersAndBody(InHandling i
Node body;
{
AutoAwaitIsKeyword<ParseHandler, CharT> awaitIsKeyword(this, bodyAwaitHandling);
AutoInParametersOfAsyncFunction<ParseHandler, CharT> inParameters(this, false);
body = functionBody(inHandling, bodyYieldHandling, kind, bodyType);
if (!body)
return false;
@ -8586,6 +8612,10 @@ GeneralParser<ParseHandler, CharT>::unaryExpr(YieldHandling yieldHandling,
case TokenKind::Await: {
if (pc->isAsync()) {
if (inParametersOfAsyncFunction()) {
error(JSMSG_AWAIT_IN_DEFAULT);
return null();
}
Node kid = unaryExpr(yieldHandling, tripledotHandling, possibleError, invoked);
if (!kid)
return null();

View File

@ -249,6 +249,9 @@ enum AwaitHandling : uint8_t { AwaitIsName, AwaitIsKeyword, AwaitIsModuleKeyword
template <class ParseHandler, typename CharT>
class AutoAwaitIsKeyword;
template <class ParseHandler, typename CharT>
class AutoInParametersOfAsyncFunction;
class MOZ_STACK_CLASS ParserBase
: public StrictModeGetter,
private JS::AutoGCRooter
@ -297,6 +300,8 @@ class MOZ_STACK_CLASS ParserBase
/* AwaitHandling */ uint8_t awaitHandling_:2;
bool inParametersOfAsyncFunction_:1;
/* ParseGoal */ uint8_t parseGoal_:1;
public:
@ -304,11 +309,16 @@ class MOZ_STACK_CLASS ParserBase
return awaitHandling_ != AwaitIsName;
}
bool inParametersOfAsyncFunction() const {
return inParametersOfAsyncFunction_;
}
ParseGoal parseGoal() const {
return ParseGoal(parseGoal_);
}
template<class, typename> friend class AutoAwaitIsKeyword;
template<class, typename> friend class AutoInParametersOfAsyncFunction;
ParserBase(JSContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
bool foldConstants, UsedNameTracker& usedNames,
@ -690,6 +700,7 @@ class MOZ_STACK_CLASS GeneralParser
using Base::alloc;
using Base::awaitIsKeyword;
using Base::inParametersOfAsyncFunction;
using Base::parseGoal;
#if DEBUG
using Base::checkOptionsCalled;
@ -896,6 +907,7 @@ class MOZ_STACK_CLASS GeneralParser
ParseGoal parseGoal);
inline void setAwaitHandling(AwaitHandling awaitHandling);
inline void setInParametersOfAsyncFunction(bool inParameters);
/*
* Parse a top-level JS script.
@ -1355,6 +1367,7 @@ class MOZ_STACK_CLASS Parser<SyntaxParseHandler, CharT> final
// Functions present in both Parser<ParseHandler, CharT> specializations.
inline void setAwaitHandling(AwaitHandling awaitHandling);
inline void setInParametersOfAsyncFunction(bool inParameters);
Node newRegExp();
@ -1473,6 +1486,9 @@ class MOZ_STACK_CLASS Parser<FullParseHandler, CharT> final
friend class AutoAwaitIsKeyword<SyntaxParseHandler, CharT>;
inline void setAwaitHandling(AwaitHandling awaitHandling);
friend class AutoInParametersOfAsyncFunction<SyntaxParseHandler, CharT>;
inline void setInParametersOfAsyncFunction(bool inParameters);
Node newRegExp();
// Parse a module.
@ -1612,6 +1628,27 @@ class MOZ_STACK_CLASS AutoAwaitIsKeyword
}
};
template <class ParseHandler, typename CharT>
class MOZ_STACK_CLASS AutoInParametersOfAsyncFunction
{
using GeneralParser = frontend::GeneralParser<ParseHandler, CharT>;
private:
GeneralParser* parser_;
bool oldInParametersOfAsyncFunction_;
public:
AutoInParametersOfAsyncFunction(GeneralParser* parser, bool inParameters) {
parser_ = parser;
oldInParametersOfAsyncFunction_ = parser_->inParametersOfAsyncFunction_;
parser_->setInParametersOfAsyncFunction(inParameters);
}
~AutoInParametersOfAsyncFunction() {
parser_->setInParametersOfAsyncFunction(oldInParametersOfAsyncFunction_);
}
};
template <typename Scope>
extern typename Scope::Data*
NewEmptyBindingData(JSContext* cx, LifoAlloc& alloc, uint32_t numBindings);

View File

@ -0,0 +1,67 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
* Contributor:
*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 1478910;
var summary = 'JSMSG_AWAIT_IN_DEFAULT error for incomplete await expr in async function/generator parameter';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
printBugNumber(BUGNUMBER);
printStatus(summary);
let testAwaitInDefaultExprOfAsyncFunc = (code) => {
assertThrowsInstanceOf(() => eval(code), SyntaxError, "await can't be used in default expression");
};
let testNoException = (code) => {
assertEq(completesNormally(code), true);
};
// https://www.ecma-international.org/ecma-262/9.0/
// Async Generator Function Definitions : AsyncGeneratorDeclaration & AsyncGeneratorExpression
// async function* f() {}
// f = async function*() {}
testAwaitInDefaultExprOfAsyncFunc("async function* f(a = await) {}");
testAwaitInDefaultExprOfAsyncFunc("let f = async function*(a = await) {}");
testAwaitInDefaultExprOfAsyncFunc("function f(a = async function*(a = await) {}) {}");
testAwaitInDefaultExprOfAsyncFunc("function f() { a = async function*(a = await) {}; }");
testAwaitInDefaultExprOfAsyncFunc("async function* f() { a = async function*(a = await) {}; }");
testNoException("async function* f() { let a = function(a = await) {}; }");
testNoException("async function* f(a = async function*() { await 1; }) {}");
// Async Function Definitions : AsyncFunctionDeclaration & AsyncFunctionExpression
// async function f() {}
// f = async function() {}
testAwaitInDefaultExprOfAsyncFunc("async function f(a = await) {}");
testAwaitInDefaultExprOfAsyncFunc("let f = async function(a = await) {}");
testAwaitInDefaultExprOfAsyncFunc("function f(a = async function(a = await) {}) {}");
testAwaitInDefaultExprOfAsyncFunc("function f() { a = async function(a = await) {}; }");
testAwaitInDefaultExprOfAsyncFunc("async function f() { a = async function(a = await) {}; }");
testNoException("async function f() { let a = function(a = await) {}; }");
testNoException("async function f(a = async function() { await 1; }) {}");
// Async Arrow Function Definitions : AsyncArrowFunction
// async () => {}
testAwaitInDefaultExprOfAsyncFunc("async (a = await) => {}");
testNoException("async (a = async () => { await 1; }) => {}");
reportCompare(true, true, summary);
}

View File

@ -1685,7 +1685,7 @@ fuzzy-if(skiaContent,0-1,0-65536) == 654950-1.html 654950-1-ref.html # Quartz al
!= 656875.html about:blank
== 658952.html 658952-ref.html
fuzzy-if(skiaContent,0-10,0-919) fuzzy-if(webrender&&cocoaWidget,54-54,831-831) == 660682-1.html 660682-1-ref.html
pref(layout.css.xul-tree-pseudos.content.enabled,true) fuzzy-if(d2d,0-1,0-256) skip-if(Android) fuzzy-if(skiaContent,0-1,0-68000) fuzzy-if(webrender&&cocoaWidget,2-2,256-256) == 664127-1.xul 664127-1-ref.xul # Android: Intermittent failures - bug 1019131
pref(layout.css.xul-tree-pseudos.content.enabled,true) fuzzy-if(d2d,0-1,0-256) skip-if(Android) fuzzy-if(skiaContent,0-1,0-68000) == 664127-1.xul 664127-1-ref.xul # Android: Intermittent failures - bug 1019131
== 665597-1.html 665597-1-ref.html
== 665597-2.html 665597-2-ref.html
== 667079-1.html 667079-1-ref.html

View File

@ -7,7 +7,7 @@ random-if(Android) == menulist-shrinkwrap-2.xul menulist-shrinkwrap-2-ref.xul
== textbox-overflow-1.xul textbox-overflow-1-ref.xul # for bug 749658
# accesskeys are not normally displayed on Mac, so skip this test
skip-if(cocoaWidget) == accesskey.xul accesskey-ref.xul
pref(layout.css.xul-tree-pseudos.content.enabled,true) fails-if(cocoaWidget) fuzzy-if(xulRuntime.widgetToolkit=="gtk3",0-1,0-11) == tree-row-outline-1.xul tree-row-outline-1-ref.xul # win8: bug 1254832
pref(layout.css.xul-tree-pseudos.content.enabled,true) fuzzy-if(xulRuntime.widgetToolkit=="gtk3",0-1,0-11) == tree-row-outline-1.xul tree-row-outline-1-ref.xul # win8: bug 1254832
skip-if(!cocoaWidget) fails-if(webrender&&cocoaWidget) == mac-tab-toolbar.xul mac-tab-toolbar-ref.xul
pref(layout.css.xul-tree-pseudos.content.enabled,true) != tree-row-outline-1.xul tree-row-outline-1-notref.xul
== text-crop.xul text-crop-ref.xul

View File

@ -16,5 +16,52 @@
// bug 1338260, directv.com
"directv.com": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
// bug 1385206, rakuten.co.jp
"rakuten.co.jp": "Firefox.+$#"
"rakuten.co.jp": "Firefox.+$#",
// bug 1483233, ebay.com, m.ebay.com, and localized versions
"ebay.at": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.at": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.be": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.be": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.ca": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.ca": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.ch": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.ch": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.cn": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.cn": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.co.th": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.co.th": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.co.uk": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.co.uk": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.com": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.com": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.com.au": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.com.au": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.com.hk": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.com.hk": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.com.my": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.com.my": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.com.sg": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.com.sg": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.com.tw": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.com.tw": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.de": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.de": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.es": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.es": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.fr": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.fr": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.ie": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.ie": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.in": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.in": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.it": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.it": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.nl": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.nl": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.ph": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.ph": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.pl": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.pl": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"ebay.vn": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"m.ebay.vn": "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36"
}

View File

@ -418,7 +418,7 @@ public class GeckoMediaControlAgent {
if (!AppConstants.Versions.preO) {
notificationBuilder.setChannelId(NotificationHelper.getInstance(mContext)
.getNotificationChannel(NotificationHelper.Channel.DEFAULT).getId());
.getNotificationChannel(NotificationHelper.Channel.MEDIA).getId());
}
return notificationBuilder.build();

View File

@ -97,7 +97,11 @@ public final class NotificationHelper implements BundleEventListener {
/**
* Mozilla Location Services notification channel.
*/
DOWNLOAD
DOWNLOAD,
/**
* Media notification channel
*/
MEDIA
}
private final Map<Channel, String> mDefinedNotificationChannels = new HashMap<Channel, String>() {{
@ -109,6 +113,10 @@ public final class NotificationHelper implements BundleEventListener {
final String DOWNLOAD_NOTIFICATION_TAG = "download-notification-channel";
put(Channel.DOWNLOAD, DOWNLOAD_NOTIFICATION_TAG);
final String MEDIA_CHANNEL_TAG = "media-notification-channel";
put(Channel.MEDIA, MEDIA_CHANNEL_TAG);
}};
// Holds a list of notifications that should be cleared if the Fennec Activity is shut down.
@ -176,6 +184,12 @@ public final class NotificationHelper implements BundleEventListener {
}
break;
case MEDIA: {
channel = new NotificationChannel(mDefinedNotificationChannels.get(definedChannel),
mContext.getString(R.string.media_notification_channel), NotificationManager.IMPORTANCE_LOW);
}
break;
case DEFAULT:
default: {

View File

@ -897,4 +897,5 @@ Picture-in-picture mini window -->
<!-- Notification channels names -->
<!ENTITY default_notification_channel "&brandShortName;">
<!ENTITY mls_notification_channel "&vendorShortName; Location Service">
<!ENTITY download_notification_channel "Downloads">
<!ENTITY download_notification_channel "Downloads">
<!ENTITY media_notification_channel "Media playback">

View File

@ -650,5 +650,6 @@
<string name="default_notification_channel">&default_notification_channel;</string>
<string name="mls_notification_channel">&mls_notification_channel;</string>
<string name="media_notification_channel">&media_notification_channel;</string>
<string name="download_notification_channel">&download_notification_channel;</string>
</resources>

View File

@ -10,7 +10,10 @@ export AR="$topsrcdir/clang/bin/llvm-ar"
export NM="$topsrcdir/clang/bin/llvm-nm"
export RANLIB="$topsrcdir/clang/bin/llvm-ranlib"
ac_add_options --enable-lto
# Enable LTO if the NDK is available.
if [ -z "$NO_NDK" ]; then
ac_add_options --enable-lto
fi
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1

View File

@ -20,6 +20,9 @@ export AR="$topsrcdir/clang/bin/llvm-ar"
export NM="$topsrcdir/clang/bin/llvm-nm"
export RANLIB="$topsrcdir/clang/bin/llvm-ranlib"
ac_add_options --enable-lto
# Enable LTO if the NDK is available.
if [ -z "$NO_NDK" ]; then
ac_add_options --enable-lto
fi
. "$topsrcdir/mobile/android/config/mozconfigs/common.override"

View File

@ -18,6 +18,9 @@ export AR="$topsrcdir/clang/bin/llvm-ar"
export NM="$topsrcdir/clang/bin/llvm-nm"
export RANLIB="$topsrcdir/clang/bin/llvm-ranlib"
ac_add_options --enable-lto
# Enable LTO if the NDK is available.
if [ -z "$NO_NDK" ]; then
ac_add_options --enable-lto
fi
. "$topsrcdir/mobile/android/config/mozconfigs/common.override"

View File

@ -42,30 +42,32 @@ const CACHE_LINE: usize = 64;
const CACHE_LINE_MASK: usize = CACHE_LINE - 1;
/// Returns true if the string is both longer than a cache line
/// and the first cache line is ASCII.
#[inline(always)]
fn starts_with_ascii(buffer: &[u8]) -> bool {
fn long_string_starts_with_ascii(buffer: &[u8]) -> bool {
// We examine data only up to the end of the cache line
// to make this check minimally disruptive.
let bound = if buffer.len() <= CACHE_LINE {
buffer.len()
} else {
CACHE_LINE - ((buffer.as_ptr() as usize) & CACHE_LINE_MASK)
};
if buffer.len() <= CACHE_LINE {
return false;
}
let bound = CACHE_LINE - ((buffer.as_ptr() as usize) & CACHE_LINE_MASK);
is_ascii(&buffer[..bound])
}
/// Returns true if the string is both longer than two cache lines
/// and the first two cache lines are Basic Latin.
#[inline(always)]
fn starts_with_basic_latin(buffer: &[u16]) -> bool {
fn long_string_stars_with_basic_latin(buffer: &[u16]) -> bool {
// We look at two cache lines with code unit size of two. There is need
// to look at more than one cache line in the UTF-16 case, because looking
// at just one cache line wouldn't catch non-ASCII Latin with high enough
// probability with Latin-script languages that have relatively infrequent
// non-ASCII characters.
let bound = if buffer.len() <= CACHE_LINE {
buffer.len()
} else {
(CACHE_LINE * 2 - ((buffer.as_ptr() as usize) & CACHE_LINE_MASK)) / 2
};
if buffer.len() <= CACHE_LINE {
return false;
}
let bound = (CACHE_LINE * 2 - ((buffer.as_ptr() as usize) & CACHE_LINE_MASK)) / 2;
is_basic_latin(&buffer[..bound])
}
@ -118,7 +120,8 @@ macro_rules! shrinking_conversion {
self.bulk_write(old_len.checked_add(needed).ok_or(())?, old_len, false)?
};
let written = $convert(other, &mut handle.as_mut_slice()[old_len..]);
Ok(handle.finish(old_len + written, true))
let new_len = old_len + written;
Ok(handle.finish(new_len, new_len > CACHE_LINE))
}
)
}
@ -313,9 +316,22 @@ impl nsACString {
other: &[u16],
old_len: usize,
) -> Result<BulkWriteOk, ()> {
// We first size the buffer for ASCII if the first cache line is ASCII. If that turns out not to
// be enough, we size for the worst case given the length of the remaining input at that point.
let (filled, num_ascii, mut handle) = if starts_with_basic_latin(other) {
// We first size the buffer for ASCII if the first two cache lines are ASCII. If that turns out
// not to be enough, we size for the worst case given the length of the remaining input at that
// point. BUT if the worst case fits inside the inline capacity of an autostring, we skip
// the ASCII stuff.
let worst_case_needed = if let Some(inline_capacity) = self.inline_capacity() {
let worst_case = times_three_plus_one(other.len()).ok_or(())?;
if worst_case <= inline_capacity {
Some(worst_case)
} else {
None
}
} else {
None
};
let (filled, num_ascii, mut handle) = if worst_case_needed.is_none() &&
long_string_stars_with_basic_latin(other) {
let new_len_with_ascii = old_len.checked_add(other.len()).ok_or(())?;
let mut handle = unsafe { self.bulk_write(new_len_with_ascii, old_len, false)? };
let num_ascii = copy_basic_latin_to_ascii(other, &mut handle.as_mut_slice()[old_len..]);
@ -332,7 +348,11 @@ impl nsACString {
(filled, num_ascii, handle)
} else {
// Started with non-ASCII. Compute worst case
let needed = times_three_plus_one(other.len()).ok_or(())?;
let needed = if let Some(n) = worst_case_needed {
n
} else {
times_three_plus_one(other.len()).ok_or(())?
};
let new_len = old_len.checked_add(needed).ok_or(())?;
let mut handle = unsafe { self.bulk_write(new_len, old_len, false)? };
(old_len, 0, handle)
@ -568,31 +588,47 @@ impl nsACString {
(&mut handle.as_mut_slice()[old_len..filled]).copy_from_slice(&other[..num_ascii]);
}
(filled, num_ascii, handle)
} else if starts_with_ascii(other) {
// Wrapper didn't check for ASCII, so let's see if `other` starts with ASCII
// `other` starts with ASCII, so let's first size the buffer
// with optimism that it's ASCII-only.
let new_len_with_ascii = old_len.checked_add(other.len()).ok_or(())?;
let mut handle = unsafe { self.bulk_write(new_len_with_ascii, old_len, false)? };
let num_ascii = copy_ascii_to_ascii(other, &mut handle.as_mut_slice()[old_len..]);
let left = other.len() - num_ascii;
let filled = old_len + num_ascii;
if left == 0 {
// `other` was all ASCII
return Ok(handle.finish(filled, true));
}
let needed = left.checked_mul(2).ok_or(())?;
let new_len = filled.checked_add(needed).ok_or(())?;
unsafe {
handle.restart_bulk_write(new_len, filled, false)?;
}
(filled, num_ascii, handle)
} else {
// Started with non-ASCII. Assume worst case.
let needed = other.len().checked_mul(2).ok_or(())?;
let new_len = old_len.checked_add(needed).ok_or(())?;
let mut handle = unsafe { self.bulk_write(new_len, old_len, false)? };
(old_len, 0, handle)
let worst_case_needed = if let Some(inline_capacity) = self.inline_capacity() {
let worst_case = other.len().checked_mul(2).ok_or(())?;
if worst_case <= inline_capacity {
Some(worst_case)
} else {
None
}
} else {
None
};
if worst_case_needed.is_none() && long_string_starts_with_ascii(other) {
// Wrapper didn't check for ASCII, so let's see if `other` starts with ASCII
// `other` starts with ASCII, so let's first size the buffer
// with optimism that it's ASCII-only.
let new_len_with_ascii = old_len.checked_add(other.len()).ok_or(())?;
let mut handle = unsafe { self.bulk_write(new_len_with_ascii, old_len, false)? };
let num_ascii = copy_ascii_to_ascii(other, &mut handle.as_mut_slice()[old_len..]);
let left = other.len() - num_ascii;
let filled = old_len + num_ascii;
if left == 0 {
// `other` was all ASCII
return Ok(handle.finish(filled, true));
}
let needed = left.checked_mul(2).ok_or(())?;
let new_len = filled.checked_add(needed).ok_or(())?;
unsafe {
handle.restart_bulk_write(new_len, filled, false)?;
}
(filled, num_ascii, handle)
} else {
// Started with non-ASCII. Assume worst case.
let needed = if let Some(n) = worst_case_needed {
n
} else {
other.len().checked_mul(2).ok_or(())?
};
let new_len = old_len.checked_add(needed).ok_or(())?;
let mut handle = unsafe { self.bulk_write(new_len, old_len, false)? };
(old_len, 0, handle)
}
};
let written =
convert_latin1_to_utf8(&other[num_ascii..], &mut handle.as_mut_slice()[filled..]);

View File

@ -144,6 +144,11 @@ pub use self::conversions::nsstring_fallible_append_utf8_impl;
/// this type!
pub struct BulkWriteOk;
/// Semi-arbitrary threshold below which we don't care about shrinking
/// buffers to size. Currently matches `CACHE_LINE` in the `conversions`
/// module.
const SHRINKING_THRESHOLD: usize = 64;
///////////////////////////////////
// Internal Implementation Flags //
///////////////////////////////////
@ -336,6 +341,7 @@ macro_rules! define_string_types {
StringAdapter = $StringAdapter: ident;
StringRepr = $StringRepr: ident;
AutoStringRepr = $AutoStringRepr: ident;
BulkWriteHandle = $BulkWriteHandle: ident;
@ -395,6 +401,13 @@ macro_rules! define_string_types {
}
}
#[repr(C)]
#[derive(Debug)]
pub struct $AutoStringRepr {
super_repr: $StringRepr,
inline_capacity: u32,
}
pub struct $BulkWriteHandle<'a> {
string: &'a mut $AString,
capacity: usize,
@ -430,7 +443,7 @@ macro_rules! define_string_types {
mem::forget(self); // Don't run the failure path in drop()
return BulkWriteOk{};
}
if allow_shrinking {
if allow_shrinking && length > SHRINKING_THRESHOLD {
unsafe {
let _ = self.restart_bulk_write(length, length, true);
}
@ -622,7 +635,7 @@ macro_rules! define_string_types {
let rounded = $start_bulk_write(self,
capacity32,
units_to_preserve as u32,
allow_shrinking);
allow_shrinking && capacity > SHRINKING_THRESHOLD);
if rounded == u32::max_value() {
return Err(())
}
@ -633,6 +646,27 @@ macro_rules! define_string_types {
fn as_repr(&mut self) -> ptr::NonNull<$StringRepr> {
unsafe { ptr::NonNull::new_unchecked(self as *mut _ as *mut $StringRepr)}
}
/// If this is an autostring, returns the capacity (excluding the zero
/// terminator) of the inline buffer within `Some()`. Otherwise returns
/// `None`.
pub fn inline_capacity(&self) -> Option<usize> {
if unsafe {
// All $AString values point to a struct prefix which is
// identical to $StringRepr, this we can transmute `self`
// into $StringRepr to get the reference to the underlying
// data.
let this: &$StringRepr = mem::transmute(self);
this.classflags.contains(ClassFlags::INLINE)
} {
unsafe {
let this: &$AutoStringRepr = mem::transmute(self);
Some(this.inline_capacity as usize)
}
} else {
None
}
}
}
impl Deref for $AString {
@ -1016,6 +1050,7 @@ define_string_types! {
StringAdapter = nsCStringAdapter;
StringRepr = nsCStringRepr;
AutoStringRepr = nsAutoCStringRepr;
BulkWriteHandle = nsACStringBulkWriteHandle;
@ -1146,6 +1181,7 @@ define_string_types! {
StringAdapter = nsStringAdapter;
StringRepr = nsStringRepr;
AutoStringRepr = nsAutoStringRepr;
BulkWriteHandle = nsAStringBulkWriteHandle;
@ -1259,6 +1295,7 @@ pub mod test_helpers {
//! It is public to ensure that these testing functions are avaliable to
//! gtest code.
use super::{nsACString, nsAString};
use super::{nsCStr, nsCString, nsCStringRepr};
use super::{nsStr, nsString, nsStringRepr};
use super::{ClassFlags, DataFlags};
@ -1400,4 +1437,16 @@ pub mod test_helpers {
*f_class_null_terminated = ClassFlags::NULL_TERMINATED.bits();
}
}
#[no_mangle]
#[allow(non_snake_case)]
pub extern fn Rust_InlineCapacityFromRust(cstring: *const nsACString,
string: *const nsAString,
cstring_capacity: *mut usize,
string_capacity: *mut usize) {
unsafe {
*cstring_capacity = (*cstring).inline_capacity().unwrap();
*string_capacity = (*string).inline_capacity().unwrap();
}
}
}

View File

@ -221,3 +221,32 @@ raptor-unity-webgl-chrome:
fetches:
fetch:
- unity-webgl
raptor-assorted-dom-firefox:
description: "Raptor Assorted-Dom on Firefox"
try-name: raptor-assorted-dom-firefox
treeherder-symbol: Rap(dom)
run-on-projects: ['try', 'mozilla-central']
tier: 3
max-run-time: 1500
mozharness:
extra-options:
- --test=raptor-assorted-dom
fetches:
fetch:
- assorted-dom
raptor-assorted-dom-chrome:
description: "Raptor Assorted-Dom on Chrome"
try-name: raptor-assorted-dom-chrome
treeherder-symbol: Rap-C(dom)
run-on-projects: ['try', 'mozilla-central']
tier: 3
max-run-time: 1500
mozharness:
extra-options:
- --test=raptor-assorted-dom
- --app=chrome
fetches:
fetch:
- assorted-dom

View File

@ -90,6 +90,7 @@ raptor-firefox:
- raptor-webaudio-firefox
- raptor-gdocs-firefox
- raptor-sunspider-firefox
- raptor-assorted-dom-firefox
raptor-chrome:
- raptor-tp6-chrome
@ -100,6 +101,7 @@ raptor-chrome:
- raptor-webaudio-chrome
- raptor-gdocs-chrome
- raptor-sunspider-chrome
- raptor-assorted-dom-chrome
# Fetch tasks are only supported on Linux for now,
# so these need to be separate sets.

View File

@ -11,18 +11,18 @@ from __future__ import absolute_import, print_function, unicode_literals
import os
import sys
import json
import shutil
import socket
import subprocess
import mozfile
from mach.decorators import CommandProvider, Command
from mozboot.util import get_state_dir
from mozbuild.base import MozbuildObject, MachCommandBase
from mozpack.copier import FileCopier
from mozpack.manifests import InstallManifest
HERE = os.path.dirname(os.path.realpath(__file__))
BENCHMARK_REPOSITORY = 'https://github.com/mozilla/perf-automation'
BENCHMARK_REVISION = '6beb3d3e22abce8cf8e2e89bc45acd4152258f12'
BENCHMARK_REVISION = '4befd28725c687b91ce749420eab29352ecbcab4'
class RaptorRunner(MozbuildObject):
@ -74,24 +74,30 @@ class RaptorRunner(MozbuildObject):
subprocess.check_call(['git', 'checkout', BENCHMARK_REVISION], cwd=external_repo_path)
# Link benchmarks to the objdir
# Link or copy benchmarks to the objdir
benchmark_paths = (
os.path.join(external_repo_path, 'benchmarks'),
os.path.join(self.topsrcdir, 'third_party', 'webkit', 'PerformanceTests'),
)
manifest = InstallManifest()
benchmark_dest = os.path.join(self.topobjdir, 'testing', 'raptor', 'benchmarks')
if not os.path.isdir(benchmark_dest):
os.makedirs(benchmark_dest)
for benchmark_path in benchmark_paths:
for path in os.listdir(benchmark_path):
abspath = os.path.join(benchmark_path, path)
if not os.path.isdir(abspath) or path.startswith('.'):
for name in os.listdir(benchmark_path):
path = os.path.join(benchmark_path, name)
dest = os.path.join(benchmark_dest, name)
if not os.path.isdir(path) or name.startswith('.'):
continue
manifest.add_link(abspath, path)
copier = FileCopier()
manifest.populate_registry(copier)
copier.copy(os.path.join(self.topobjdir, 'testing', 'raptor', 'benchmarks'))
if hasattr(os, 'symlink'):
if not os.path.exists(dest):
os.symlink(path, dest)
else:
# Clobber the benchmark in case a recent update removed any files.
mozfile.remove(dest)
shutil.copytree(path, dest)
def make_config(self):
default_actions = ['populate-webroot', 'install-chrome', 'create-virtualenv', 'run-tests']

View File

@ -97,6 +97,8 @@ class Output(object):
subtests, vals = self.parseWebaudioOutput(test)
elif 'unity-webgl' in test.measurements:
subtests, vals = self.parseUnityWebGLOutput(test)
elif 'assorted-dom' in test.measurements:
subtests, vals = self.parseAssortedDomOutput(test)
suite['subtests'] = subtests
else:
@ -342,6 +344,47 @@ class Output(object):
return subtests, vals
def parseAssortedDomOutput(self, test):
# each benchmark 'index' becomes a subtest; each pagecycle / iteration
# of the test has multiple values
# this is the format we receive the results in from the benchmark
# i.e. this is ONE pagecycle of assorted-dom ('test' is a valid subtest name btw):
# {u'worker-getname-performance-getter': 5.9, u'window-getname-performance-getter': 6.1,
# u'window-getprop-performance-getter': 6.1, u'worker-getprop-performance-getter': 6.1,
# u'test': 5.8, u'total': 30}
# the 'total' is provided for us from the benchmark; the overall score will be the mean of
# the totals from all pagecycles; but keep all the subtest values for the logs/json
_subtests = {}
data = test.measurements['assorted-dom']
for pagecycle in data:
for _sub, _value in pagecycle[0].iteritems():
# build a list of subtests and append all related replicates
if _sub not in _subtests.keys():
# subtest not added yet, first pagecycle, so add new one
_subtests[_sub] = {'unit': test.unit,
'alertThreshold': float(test.alert_threshold),
'lowerIsBetter': test.lower_is_better,
'name': _sub,
'replicates': []}
_subtests[_sub]['replicates'].extend([_value])
vals = []
subtests = []
names = _subtests.keys()
names.sort(reverse=True)
for name in names:
_subtests[name]['value'] = round(filter.median(_subtests[name]['replicates']), 2)
subtests.append(_subtests[name])
# only use the 'total's to compute the overall result
if name == 'total':
vals.append([_subtests[name]['value'], name])
return subtests, vals
def output(self):
"""output to file and perfherder data json """
if self.summarized_results == {}:
@ -477,6 +520,11 @@ class Output(object):
results = [i for i, j in val_list]
return sum(results)
@classmethod
def assorted_dom_score(cls, val_list):
results = [i for i, j in val_list]
return round(filter.geometric_mean(results), 2)
def construct_summary(self, vals, testname):
if testname.startswith('raptor-v8_7'):
return self.v8_Metric(vals)
@ -494,6 +542,8 @@ class Output(object):
return self.unity_webgl_score(vals)
elif testname.startswith('raptor-webaudio'):
return self.webaudio_score(vals)
elif testname.startswith('raptor-assorted-dom'):
return self.assorted_dom_score(vals)
elif len(vals) > 1:
return round(filter.geometric_mean([i for i, j in vals]), 2)
else:

View File

@ -8,3 +8,4 @@
[include:tests/raptor-unity-webgl.ini]
[include:tests/raptor-webaudio.ini]
[include:tests/raptor-gdocs.ini]
[include:tests/raptor-assorted-dom.ini]

View File

@ -0,0 +1,14 @@
[DEFAULT]
type = benchmark
test_url = http://localhost:<port>/assorted-dom/assorted/driver.html?raptor
page_cycles = 10
page_timeout = 60000
unit = ms
lower_is_better = true
alert_threshold = 2.0
[raptor-assorted-dom-firefox]
apps = firefox
[raptor-assorted-dom-chrome]
apps = chrome

View File

@ -25,7 +25,8 @@
"*://*/MotionMark/*",
"*://*/SunSpider/*",
"*://*/webaudio/*",
"*://*/unity-webgl/index.html*"],
"*://*/unity-webgl/index.html*",
"*://*/assorted-dom/assorted/results.html*"],
"js": ["benchmark-relay.js"]
}
],

View File

@ -338365,6 +338365,12 @@
{}
]
],
"custom-elements/range-and-constructors.html": [
[
"/custom-elements/range-and-constructors.html",
{}
]
],
"custom-elements/reaction-timing.html": [
[
"/custom-elements/reaction-timing.html",
@ -578532,6 +578538,10 @@
"60d88cffb517c0062db338e5ba89e98f7748c280",
"testharness"
],
"custom-elements/range-and-constructors.html": [
"d17c3b71480aa9dd2a75ccbc2cccfd362060eb3c",
"testharness"
],
"custom-elements/reaction-timing.html": [
"9e5bafbedfec42d28eb94c95ed84396941bc61ac",
"testharness"

View File

@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<title>Custom elements: Range APIs should invoke constructor in tree order</title>
<meta name="author" title="Edgar Chen" href="mailto:echen@mozilla.com">
<link rel="help" href="https://html.spec.whatwg.org/multipage/scripting.html#concept-upgrade-an-element">
<link rel="help" href="https://dom.spec.whatwg.org/#concept-create-element">
<line rel="help" href="https://dom.spec.whatwg.org/#concept-range-extract">
<line rel="help" href="https://dom.spec.whatwg.org/#concept-range-clone">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<div id="log"></div>
<c-e data-index="root">
<c-e data-index="root-0">
<c-e data-index="root-0-0">
<c-e data-index="root-0-0-0"></c-e>
<span id="start"></span>
</c-e>
</c-e>
<c-e data-index="root-1"></c-e>
<span id="end"></span>
</c-e>
<script>
var logs = [];
class CE extends HTMLElement {
constructor() {
super();
logs.push(this.dataset.index);
}
}
customElements.define('c-e', CE);
function getRange() {
const range = new Range();
range.setStart(document.getElementById('start'), 0);
range.setEnd(document.getElementById('end'), 0);
return range;
}
test(function () {
// Clear log for testing.
logs = [];
getRange().cloneContents();
assert_array_equals(logs, ['root-0', 'root-0-0', 'root-1']);
}, 'Range.cloneContents should invoke constructor in tree order');
test(function () {
// Clear log for testing.
logs = [];
getRange().extractContents();
assert_array_equals(logs, ['root-0', 'root-0-0']);
}, 'Range.extractContents should invoke constructor in tree order');
</script>
</body>
</html>

View File

@ -207,7 +207,7 @@ var listener = {
},
onWindowLoaded() {
let browser = this.win.document.createElementNS(XUL_NS, "browser");
let browser = this.win.document.createXULElement("browser");
browser.setAttribute("type", "content");
browser.setAttribute("disableglobalhistory", "true");

View File

@ -543,10 +543,7 @@ var PrintUtils = {
// show the toolbar after we go into print preview mode so
// that we can initialize the toolbar with total num pages
const XUL_NS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
printPreviewTB = document.createElementNS(XUL_NS, "toolbar",
printPreviewTB = document.createXULElement("toolbar",
{ is: "printpreview-toolbar" });
printPreviewTB.setAttribute("fullscreentoolbar", true);
printPreviewTB.id = "print-preview-toolbar";

View File

@ -23,7 +23,9 @@ activity_stream:
"PREVIEW_REQUEST",
"SAVE_TO_POCKET",
"SEARCH",
"SEARCH_EDIT_ADD",
"SEARCH_EDIT_CLOSE",
"SEARCH_EDIT_DELETE",
"SKIPPED_SIGNIN",
"SUBMIT_EMAIL",
"DISCLAIMER_ACKED",
@ -526,8 +528,8 @@ devtools.main:
extra_keys:
session_id: The start time of the session in milliseconds since epoch (Unix Timestamp) e.g. 1396381378123.
sidepanel_changed:
objects: ["inspector"]
bug_numbers: [1463083]
objects: ["inspector", "netmonitor"]
bug_numbers: [1463083, 1463169]
notification_emails: ["dev-developer-tools@lists.mozilla.org", "hkirschner@mozilla.com"]
record_in_processes: ["main"]
description: User has switched sidepanel tabs.

View File

@ -106,7 +106,8 @@ Preferences
``toolkit.telemetry.log.level``
This sets the Telemetry logging verbosity per ``Log.jsm``, with ``Trace`` or ``0`` being the most verbose and the default being ``Warn``.
This sets the Telemetry logging verbosity per ``Log.jsm``. The available levels, in descending order of verbosity, are ``Trace``, ``Debug``, ``Config``, ``Info``, ``Warn``, ``Error`` and ``Fatal`` with the default being ``Warn``.
By default logging goes only the console service.
``toolkit.telemetry.log.dump``

View File

@ -12,8 +12,6 @@ const FRAME_SCRIPT_URL = "chrome://global/content/backgroundPageThumbsContent.js
const TELEMETRY_HISTOGRAM_ID_PREFIX = "FX_THUMBNAILS_BG_";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const ABOUT_NEWTAB_SEGREGATION_PREF = "privacy.usercontext.about_newtab_segregation.enabled";
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", this);
@ -256,7 +254,7 @@ const BackgroundPageThumbs = {
this._destroyBrowser();
this._renewThumbBrowser = false;
let browser = this._parentWin.document.createElementNS(XUL_NS, "browser");
let browser = this._parentWin.document.createXULElement("browser");
browser.setAttribute("type", "content");
browser.setAttribute("remote", "true");
browser.setAttribute("disableglobalhistory", "true");

View File

@ -979,7 +979,7 @@
} else {
// need to create a new item
item = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "richlistitem");
item = document.createXULElement("richlistitem");
}
item.setAttribute("dir", this.style.direction);

View File

@ -1113,8 +1113,7 @@
<method name="_createAutoScrollPopup">
<body>
<![CDATA[
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var popup = document.createElementNS(XUL_NS, "panel");
var popup = document.createXULElement("panel");
popup.className = "autoscroller";
// We set this attribute on the element so that mousemove
// events can be handled by browser-content.js.

View File

@ -64,16 +64,13 @@
<parameter name="aLabel"/>
<parameter name="aValue"/>
<body>
const XUL_NS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var menupopup = this.menupopup;
if (!menupopup) {
menupopup = this.ownerDocument.createElementNS(XUL_NS, "menupopup");
menupopup = this.ownerDocument.createXULElement("menupopup");
this.appendChild(menupopup);
}
var menuitem = this.ownerDocument.createElementNS(XUL_NS, "menuitem");
var menuitem = this.ownerDocument.createXULElement("menuitem");
menuitem.setAttribute("label", aLabel);
menuitem.setAttribute("value", aValue);

View File

@ -318,10 +318,9 @@
<parameter name="description"/>
<body>
<![CDATA[
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var popup = this.menupopup ||
this.appendChild(document.createElementNS(XULNS, "menupopup"));
var item = document.createElementNS(XULNS, "menuitem");
this.appendChild(document.createXULElement("menupopup"));
var item = document.createXULElement("menuitem");
item.setAttribute("label", label);
item.setAttribute("value", value);
if (description)

View File

@ -112,8 +112,7 @@
insertPos = notifications[n];
}
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var newitem = document.createElementNS(XULNS, "notification");
var newitem = document.createXULElement("notification");
// Can't use instanceof in case this was created from a different document:
let labelIsDocFragment = aLabel && typeof aLabel == "object" && aLabel.nodeType &&
aLabel.nodeType == aLabel.DOCUMENT_FRAGMENT_NODE;
@ -133,7 +132,7 @@
for (var b = 0; b < aButtons.length; b++) {
var button = aButtons[b];
var buttonElem = document.createElementNS(XULNS, "button");
var buttonElem = document.createXULElement("button");
buttonElem.setAttribute("label", button.label);
if (typeof button.accessKey == "string")
buttonElem.setAttribute("accesskey", button.accessKey);

View File

@ -306,8 +306,7 @@
<parameter name="value"/>
<body>
<![CDATA[
var XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var radio = document.createElementNS(XULNS, "radio");
var radio = document.createXULElement("radio");
radio.setAttribute("label", label);
radio.setAttribute("value", value);
this.appendChild(radio);

View File

@ -117,14 +117,11 @@
<parameter name="aLabel"/>
<parameter name="aValue"/>
<body>
const XULNS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var item =
this.ownerDocument.createElementNS(XULNS, "richlistitem");
this.ownerDocument.createXULElement("richlistitem");
item.setAttribute("value", aValue);
var label = this.ownerDocument.createElementNS(XULNS, "label");
var label = this.ownerDocument.createXULElement("label");
label.setAttribute("value", aLabel);
label.setAttribute("flex", "1");
label.setAttribute("crop", "end");

View File

@ -506,8 +506,7 @@
<parameter name="value"/>
<body>
<![CDATA[
var XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var tab = document.createElementNS(XULNS, "tab");
var tab = document.createXULElement("tab");
tab.setAttribute("label", label);
tab.setAttribute("value", value);
this.appendChild(tab);

View File

@ -787,8 +787,6 @@ PopupNotifications.prototype = {
_refreshPanel: function PopupNotifications_refreshPanel(notificationsToShow) {
this._clearPanel();
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
notificationsToShow.forEach(function(n) {
let doc = this.window.document;
@ -802,7 +800,7 @@ PopupNotifications.prototype = {
if (popupnotification)
gNotificationParents.set(popupnotification, popupnotification.parentNode);
else
popupnotification = doc.createElementNS(XUL_NS, "popupnotification");
popupnotification = doc.createXULElement("popupnotification");
// Create the notification description element.
let desc = this._formatDescriptionMessage(n);
@ -884,7 +882,7 @@ PopupNotifications.prototype = {
for (let i = 1; i < n.secondaryActions.length; i++) {
let action = n.secondaryActions[i];
let item = doc.createElementNS(XUL_NS, "menuitem");
let item = doc.createXULElement("menuitem");
item.setAttribute("label", action.label);
item.setAttribute("accesskey", action.accessKey);
item.notification = n;

View File

@ -3,8 +3,6 @@
* 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/. */
const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var gUpdateHistory = {
_view: null,
@ -35,7 +33,7 @@ var gUpdateHistory = {
if (!update.statusText)
continue;
var element = document.createElementNS(NS_XUL, "richlistitem");
var element = document.createXULElement("richlistitem");
element.className = "update";
this._view.appendChild(element);
element.name = bundle.getFormattedString("updateFullName",

View File

@ -72,12 +72,12 @@ button.plain {
button[type="disclosure"] {
margin: 0;
-moz-appearance: none;
list-style-image: url("chrome://global/skin/tree/twisty-collapsed.svg");
list-style-image: url("chrome://global/skin/icons/twisty-collapsed.svg");
-moz-context-properties: fill;
fill: currentColor;
min-width: 0;
}
button[type="disclosure"][open="true"] {
list-style-image: url("chrome://global/skin/tree/twisty-expanded.svg");
list-style-image: url("chrome://global/skin/icons/twisty-expanded.svg");
}

View File

@ -29,7 +29,7 @@ toolkit.jar:
skin/classic/global/toolbar.css
skin/classic/global/toolbarbutton.css
skin/classic/global/tooltip.css
skin/classic/global/tree.css
* skin/classic/global/tree.css
* skin/classic/global/alerts/alert.css (alerts/alert.css)
skin/classic/global/icons/Authentication.png (icons/Authentication.png)
@ -42,6 +42,3 @@ toolkit.jar:
* skin/classic/global/in-content/common.css (in-content/common.css)
* skin/classic/global/in-content/info-pages.css (in-content/info-pages.css)
skin/classic/global/tree/twisty-collapsed.svg (tree/twisty-collapsed.svg)
skin/classic/global/tree/twisty-collapsed-rtl.svg (tree/twisty-collapsed-rtl.svg)
skin/classic/global/tree/twisty-expanded.svg (tree/twisty-expanded.svg)

View File

@ -2,215 +2,10 @@
* 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/. */
/* ===== tree.css ===================================================
== Styles used by the XUL outline element.
======================================================================= */
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
/* ::::: tree ::::: */
tree {
margin: 0 4px;
background-color: -moz-Field;
color: -moz-FieldText;
-moz-appearance: listbox;
}
/* ::::: tree focusring ::::: */
.focusring > .tree-stack > .tree-rows > .tree-bodybox {
border: 1px solid transparent;
}
.focusring:focus > .tree-stack > .tree-rows > .tree-bodybox {
border: 1px solid #000000;
}
/* ::::: tree rows ::::: */
treechildren::-moz-tree-row {
border: 1px solid transparent;
min-height: 18px;
height: 1.3em;
}
treechildren::-moz-tree-row(multicol, odd) {
background-color: -moz-oddtreerow;
}
treechildren::-moz-tree-row(selected) {
background-color: -moz-cellhighlight;
}
treechildren::-moz-tree-row(selected, focus) {
background-color: Highlight;
}
treechildren::-moz-tree-row(current, focus) {
border: 1px dotted Highlight;
}
treechildren::-moz-tree-row(selected, current, focus) {
border: 1px dotted #F3D982;
}
/* ::::: tree cells ::::: */
treechildren::-moz-tree-cell {
padding: 0 2px;
}
treechildren::-moz-tree-cell-text {
color: inherit;
}
treechildren::-moz-tree-cell-text(selected) {
color: -moz-cellhighlighttext;
}
treechildren::-moz-tree-cell-text(selected, focus) {
color: HighlightText;
}
/* ::::: lines connecting cells ::::: */
treechildren::-moz-tree-line {
border: 1px dotted ThreeDShadow;
}
treechildren::-moz-tree-line(selected, focus) {
border: 1px dotted HighlightText;
}
/* ::::: tree separator ::::: */
treechildren::-moz-tree-separator {
border-top: 1px solid ThreeDShadow;
border-bottom: 1px solid ThreeDHighlight;
}
/* ::::: drop feedback ::::: */
treechildren::-moz-tree-cell-text(primary, dropOn) {
background-color: Highlight;
color: HighlightText;
}
treechildren::-moz-tree-drop-feedback {
background-color: Highlight;
width: 50px;
height: 2px;
margin-inline-start: 5px;
}
/* ::::: tree columns ::::: */
treecol,
treecolpicker {
-moz-appearance: treeheadercell;
-moz-box-align: center;
-moz-box-pack: center;
color: -moz-DialogText;
}
treecol:hover,
treecolpicker:hover {
color: -moz-buttonhovertext;
}
.treecol-image {
padding: 0 1px;
}
.treecol-text {
margin: 0 !important;
}
treecol[hideheader="true"] {
-moz-appearance: none;
}
/* ::::: column drag and drop styles ::::: */
treecol[dragging="true"] {
color: Graytext;
}
treechildren::-moz-tree-column(insertbefore) {
border-inline-start: 1px solid ThreeDShadow;
}
treechildren::-moz-tree-column(insertafter) {
border-inline-end: 1px solid ThreeDShadow;
}
%include ../../shared/tree.inc.css
/* ::::: sort direction indicator ::::: */
.treecol-sortdirection {
-moz-appearance: treeheadersortarrow;
}
/* ::::: column picker ::::: */
.tree-columnpicker-icon {
list-style-image: url("chrome://global/skin/tree/columnpicker.gif");
}
/* ::::: twisty ::::: */
treechildren::-moz-tree-twisty {
padding-inline-end: 4px;
padding-top: 1px;
width: 9px; /* The image's width is 9 pixels */
list-style-image: url("chrome://global/skin/tree/twisty-collapsed.svg");
-moz-context-properties: fill;
fill: currentColor;
}
treechildren:-moz-locale-dir(rtl)::-moz-tree-twisty(closed) {
list-style-image: url("chrome://global/skin/tree/twisty-collapsed-rtl.svg");
}
treechildren::-moz-tree-twisty(open) {
list-style-image: url("chrome://global/skin/tree/twisty-expanded.svg");
}
treechildren::-moz-tree-twisty(selected) {
fill: -moz-cellhighlighttext;
}
treechildren::-moz-tree-indentation {
width: 18px;
}
/* ::::: editable tree ::::: */
treechildren::-moz-tree-row(selected, editing) {
background-color: transparent;
border: none;
}
treechildren::-moz-tree-cell-text(selected, editing) {
color: inherit;
}
treechildren::-moz-tree-cell(active, selected, focus, editing) {
background-color: transparent;
border: none;
}
treechildren::-moz-tree-cell-text(active, selected, editing) {
opacity: 0;
}
.tree-input {
-moz-appearance: none;
border: 1px solid Highlight;
margin: 0;
margin-inline-start: -4px;
padding: 1px;
}

View File

@ -1,6 +0,0 @@
<!-- 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/. -->
<svg width="9" height="9" xmlns="http://www.w3.org/2000/svg" stroke="context-fill" stroke-width="1.6" fill="none">
<path d="m 8.5,2.5 -4,4 -4,-4"/>
</svg>

Before

Width:  |  Height:  |  Size: 369 B

View File

@ -72,7 +72,4 @@ toolkit.jar:
skin/classic/global/icons/sslWarning.png (icons/sslWarning.png)
* skin/classic/global/in-content/common.css (in-content/common.css)
* skin/classic/global/in-content/info-pages.css (in-content/info-pages.css)
skin/classic/global/tree/arrow-collapsed.svg (tree/arrow-collapsed.svg)
skin/classic/global/tree/arrow-collapsed-rtl.svg (tree/arrow-collapsed-rtl.svg)
skin/classic/global/tree/arrow-expanded.svg (tree/arrow-expanded.svg)
skin/classic/global/tree/columnpicker.gif (tree/columnpicker.gif)

View File

@ -2,15 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
%include shared.inc
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
tree {
margin: 0px 4px;
color: -moz-DialogText;
background-color: #FFFFFF;
-moz-appearance: listbox;
}
%include ../../shared/tree.inc.css
/* ::::: tree focusring ::::: */
@ -22,165 +14,10 @@ tree {
border: 1px solid -moz-mac-focusring;
}
/* ::::: tree rows ::::: */
treechildren::-moz-tree-row {
border-top: 1px solid transparent;
height: 18px;
background-color: -moz-field;
}
treechildren::-moz-tree-row(multicol, odd) {
background-color: -moz-oddtreerow;
}
treechildren::-moz-tree-row(selected) {
background-color: -moz-mac-secondaryhighlight;
}
treechildren::-moz-tree-row(selected, focus) {
background-color: Highlight;
color: HighlightText;
}
/* ::::: tree cells ::::: */
treechildren::-moz-tree-cell {
padding: 0px 2px 0px 2px;
}
treechildren::-moz-tree-cell-text {
color: inherit;
}
treechildren::-moz-tree-cell-text(selected) {
color: -moz-DialogText;
}
treechildren::-moz-tree-cell-text(selected, focus) {
color: HighlightText;
}
/* ::::: lines connecting cells ::::: */
treechildren::-moz-tree-line {
/* XXX there should be no border on Mac, but trees currently
paint the line black by default, so I'll just leave this
for now. */
visibility: hidden;
border: 1px dotted grey;
}
/* ::::: tree separator ::::: */
treechildren::-moz-tree-separator {
border-top: 1px dashed #C7C7C7;
margin: 0 2px;
}
/* ::::: drop feedback ::::: */
treechildren::-moz-tree-cell(primary, dropOn) {
background-color: #A1A1A1 !important;
color: #FFF !important;
background-image: none;
}
treechildren::-moz-tree-cell-text(primary, dropOn) {
color: #FFF !important;
}
treechildren::-moz-tree-drop-feedback {
background-color: #A1A1A1;
width: 50px;
height: 2px;
margin-inline-start: 5px;
}
/* ::::: tree columns ::::: */
treecol,
treecolpicker {
-moz-appearance: treeheadercell;
-moz-box-align: center;
-moz-box-pack: center;
color: -moz-DialogText;
padding: 0 4px;
}
.treecol-image {
padding: 0 1px;
}
.treecol-text {
margin: 0 !important;
}
treecol[hideheader="true"] {
-moz-appearance: none;
border: none;
padding: 0;
max-height: 0;
}
/* ::::: column drag and drop styles ::::: */
treecol[dragging="true"] {
color: GrayText;
}
treechildren::-moz-tree-column(insertbefore) {
border-inline-start: 1px solid ThreeDShadow;
}
treechildren::-moz-tree-column(insertafter) {
border-inline-end: 1px solid ThreeDShadow;
}
/* ::::: column picker ::::: */
.tree-columnpicker-icon {
list-style-image: url("chrome://global/skin/tree/columnpicker.gif");
}
/* ::::: twisty ::::: */
treechildren::-moz-tree-twisty {
-moz-appearance: treetwisty;
padding-inline-end: 2px;
}
treechildren::-moz-tree-twisty(open) {
-moz-appearance: treetwistyopen;
}
treechildren::-moz-tree-twisty(Name, separator) {
-moz-appearance: none;
}
treechildren::-moz-tree-indentation {
width: 16px;
}
/* ::::: editable tree ::::: */
.tree-input {
-moz-appearance: none;
border-width: 0;
box-shadow: var(--focus-ring-box-shadow);
margin: 0;
margin-inline-start: -2px;
padding: 2px 1px 1px;
}
treechildren::-moz-tree-cell(active, selected, focus, editing) {
background-color: transparent;
border: none;
}
treechildren::-moz-tree-cell-text(active, selected, editing) {
opacity: 0;
}

View File

@ -1,6 +0,0 @@
<!-- 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/. -->
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" fill="context-fill" fill-opacity="context-fill-opacity">
<polygon points="4,8.5 12,4 12,13" />
</svg>

Before

Width:  |  Height:  |  Size: 381 B

View File

@ -1,6 +0,0 @@
<!-- 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/. -->
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" fill="context-fill" fill-opacity="context-fill-opacity">
<polygon points="4,4 12,8.5 4,13" />
</svg>

Before

Width:  |  Height:  |  Size: 380 B

View File

@ -1,6 +0,0 @@
<!-- 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/. -->
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" fill="context-fill" fill-opacity="context-fill-opacity">
<polygon points="3,5 12,5 7.5,13" />
</svg>

Before

Width:  |  Height:  |  Size: 380 B

View File

@ -1,6 +1,6 @@
<!-- 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/. -->
<svg width="9" height="9" xmlns="http://www.w3.org/2000/svg" stroke="context-fill" stroke-width="1.6" fill="none">
<path d="m 6.5,0.5 -4,4 4,4"/>
</svg>
<svg width="8" height="8" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg" >
<path d="M1 4l4 4 1-1-3-3 3-3-1-1-4 4z" fill="context-fill"/>
</svg>

Before

Width:  |  Height:  |  Size: 367 B

After

Width:  |  Height:  |  Size: 363 B

View File

@ -1,6 +1,6 @@
<!-- 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/. -->
<svg width="9" height="9" xmlns="http://www.w3.org/2000/svg" stroke="context-fill" stroke-width="1.6" fill="none">
<path d="m 2.5,0.5 4,4 -4,4"/>
</svg>
<svg width="8" height="8" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg">
<path d="M7,4L3,8L2,7l3-3L2,1l1-1L7,4z" fill="context-fill"/>
</svg>

Before

Width:  |  Height:  |  Size: 367 B

After

Width:  |  Height:  |  Size: 362 B

View File

@ -1,6 +1,6 @@
<!-- 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/. -->
<svg width="9" height="9" xmlns="http://www.w3.org/2000/svg" stroke="context-fill" stroke-width="1.6" fill="none">
<path d="m 2.5,0.5 4,4 -4,4"/>
</svg>
<svg width="8" height="8" xmlns="http://www.w3.org/2000/svg">
<path d="M4 7L0 3l1-1 3 3 3-3 1 1-4 4z" fill="context-fill"/>
</svg>

Before

Width:  |  Height:  |  Size: 367 B

After

Width:  |  Height:  |  Size: 344 B

View File

@ -40,6 +40,9 @@ toolkit.jar:
skin/classic/global/icons/resizer.svg (../../shared/icons/resizer.svg)
skin/classic/global/icons/spinner-arrow-down.svg (../../shared/icons/spinner-arrow-down.svg)
skin/classic/global/icons/spinner-arrow-up.svg (../../shared/icons/spinner-arrow-up.svg)
skin/classic/global/icons/twisty-collapsed.svg (../../shared/icons/twisty-collapsed.svg)
skin/classic/global/icons/twisty-collapsed-rtl.svg (../../shared/icons/twisty-collapsed-rtl.svg)
skin/classic/global/icons/twisty-expanded.svg (../../shared/icons/twisty-expanded.svg)
skin/classic/global/icons/arrow-dropdown-12.svg (../../shared/icons/arrow-dropdown-12.svg)
skin/classic/global/icons/arrow-dropdown-16.svg (../../shared/icons/arrow-dropdown-16.svg)
skin/classic/global/icons/warning.svg (../../shared/icons/warning.svg)

View File

@ -0,0 +1,208 @@
/* 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/. */
/* ===== tree.css ===================================================
== Styles used by the XUL tree element.
======================================================================= */
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
/* ::::: tree ::::: */
tree {
margin: 0 4px;
background-color: -moz-Field;
color: -moz-FieldText;
-moz-appearance: listbox;
}
/* ::::: tree focusring ::::: */
.focusring > .tree-stack > .tree-rows > .tree-bodybox {
border: 1px solid transparent;
}
.focusring:focus > .tree-stack > .tree-rows > .tree-bodybox {
border: 1px solid #000000;
}
/* ::::: tree rows ::::: */
treechildren::-moz-tree-row {
border: 1px solid transparent;
min-height: 24px;
height: 1.3em;
}
treechildren::-moz-tree-row(multicol, odd) {
background-color: -moz-oddtreerow;
}
treechildren::-moz-tree-row(selected) {
background-color: -moz-cellhighlight;
}
treechildren::-moz-tree-row(selected, focus) {
background-color: Highlight;
}
/* ::::: tree cells ::::: */
treechildren::-moz-tree-cell {
padding: 0 2px;
}
treechildren::-moz-tree-cell-text {
color: inherit;
}
treechildren::-moz-tree-image(selected),
treechildren::-moz-tree-twisty(selected),
treechildren::-moz-tree-cell-text(selected) {
color: -moz-cellhighlighttext;
}
treechildren::-moz-tree-image(selected, focus),
treechildren::-moz-tree-twisty(selected, focus),
treechildren::-moz-tree-cell-text(selected, focus) {
color: HighlightText;
}
/* ::::: lines connecting cells ::::: */
treechildren::-moz-tree-line {
border: 1px dotted ThreeDShadow;
}
treechildren::-moz-tree-line(selected, focus) {
border: 1px dotted HighlightText;
}
/* ::::: tree separator ::::: */
treechildren::-moz-tree-separator {
border-top: 1px solid ThreeDShadow;
border-bottom: 1px solid ThreeDHighlight;
}
/* ::::: drop feedback ::::: */
treechildren::-moz-tree-cell-text(primary, dropOn) {
background-color: Highlight;
color: HighlightText;
}
treechildren::-moz-tree-drop-feedback {
background-color: Highlight;
width: 50px;
height: 2px;
margin-inline-start: 5px;
}
/* ::::: tree columns ::::: */
treecol,
treecolpicker {
-moz-appearance: treeheadercell;
-moz-box-align: center;
-moz-box-pack: center;
color: -moz-DialogText;
padding: 0 4px;
}
.treecol-image {
padding: 0 1px;
}
.treecol-text {
margin: 0 !important;
}
treecol[hideheader="true"] {
-moz-appearance: none;
}
/* ::::: column drag and drop styles ::::: */
treecol[dragging="true"] {
color: Graytext;
}
treechildren::-moz-tree-column(insertbefore) {
border-inline-start: 1px solid ThreeDShadow;
}
treechildren::-moz-tree-column(insertafter) {
border-inline-end: 1px solid ThreeDShadow;
}
/* ::::: column picker ::::: */
.tree-columnpicker-icon {
list-style-image: url("chrome://global/skin/tree/columnpicker.gif");
}
/* ::::: tree icons ::::: */
treechildren::-moz-tree-image {
-moz-context-properties: fill;
fill: currentColor;
}
/* ::::: twisty ::::: */
treechildren::-moz-tree-twisty {
padding-inline-end: 4px;
padding-inline-start: 4px;
padding-top: 1px;
width: 8px; /* The image's width is 8 pixels */
list-style-image: url("chrome://global/skin/icons/twisty-collapsed.svg");
-moz-context-properties: fill;
fill: currentColor;
}
treechildren:-moz-locale-dir(rtl)::-moz-tree-twisty(closed) {
list-style-image: url("chrome://global/skin/icons/twisty-collapsed-rtl.svg");
}
treechildren::-moz-tree-twisty(open) {
list-style-image: url("chrome://global/skin/icons/twisty-expanded.svg");
}
treechildren::-moz-tree-indentation {
width: 16px;
}
/* ::::: editable tree ::::: */
treechildren::-moz-tree-row(selected, editing) {
background-color: transparent;
border: none;
}
treechildren::-moz-tree-cell-text(selected, editing) {
color: inherit;
}
treechildren::-moz-tree-cell(active, selected, focus, editing) {
background-color: transparent;
border: none;
}
treechildren::-moz-tree-cell-text(active, selected, editing) {
opacity: 0;
}
.tree-input {
-moz-appearance: none;
border: 1px solid Highlight;
margin: 0;
margin-inline-start: -4px;
padding: 1px;
}

Some files were not shown because too many files have changed in this diff Show More