зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1591360 - Remove devtools/client/framework/sidebar.js. r=pbro.
It was only used by scratchpad which is removed
in Bug 1519103
.
Differential Revision: https://phabricator.services.mozilla.com/D50586
--HG--
extra : moz-landing-system : lando
This commit is contained in:
Родитель
d76b60f122
Коммит
e8a53e664a
|
@ -29,7 +29,6 @@ DevToolsModules(
|
||||||
'menu-item.js',
|
'menu-item.js',
|
||||||
'menu.js',
|
'menu.js',
|
||||||
'selection.js',
|
'selection.js',
|
||||||
'sidebar.js',
|
|
||||||
'source-map-url-service.js',
|
'source-map-url-service.js',
|
||||||
'store-provider.js',
|
'store-provider.js',
|
||||||
'store.js',
|
'store.js',
|
||||||
|
|
|
@ -1,635 +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/. */
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var Services = require("Services");
|
|
||||||
var EventEmitter = require("devtools/shared/event-emitter");
|
|
||||||
var Telemetry = require("devtools/client/shared/telemetry");
|
|
||||||
|
|
||||||
const { LocalizationHelper } = require("devtools/shared/l10n");
|
|
||||||
const L10N = new LocalizationHelper(
|
|
||||||
"devtools/client/locales/toolbox.properties"
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ToolSidebar provides methods to register tabs in the sidebar.
|
|
||||||
* It's assumed that the sidebar contains a xul:tabbox.
|
|
||||||
* Typically, you'll want the tabbox parameter to be a XUL tabbox like this:
|
|
||||||
*
|
|
||||||
* <tabbox id="inspector-sidebar" handleCtrlTab="false" class="devtools-sidebar-tabs">
|
|
||||||
* <tabs/>
|
|
||||||
* <tabpanels flex="1"/>
|
|
||||||
* </tabbox>
|
|
||||||
*
|
|
||||||
* The ToolSidebar API has a method to add new tabs, so the tabs and tabpanels
|
|
||||||
* nodes can be empty. But they can also already contain items before the
|
|
||||||
* ToolSidebar is created.
|
|
||||||
*
|
|
||||||
* Tabs added through the addTab method are only identified by an ID and a URL
|
|
||||||
* which is used as the href of an iframe node that is inserted in the newly
|
|
||||||
* created tabpanel.
|
|
||||||
* Tabs already present before the ToolSidebar is created may contain anything.
|
|
||||||
* However, these tabs must have ID attributes if it is required for the various
|
|
||||||
* methods that accept an ID as argument to work here.
|
|
||||||
*
|
|
||||||
* @param {Node} tabbox
|
|
||||||
* <tabbox> node;
|
|
||||||
* @param {ToolPanel} panel
|
|
||||||
* Related ToolPanel instance;
|
|
||||||
* @param {String} uid
|
|
||||||
* Unique ID
|
|
||||||
* @param {Object} options
|
|
||||||
* - hideTabstripe: Should the tabs be hidden. Defaults to false
|
|
||||||
* - showAllTabsMenu: Should a drop-down menu be displayed in case tabs
|
|
||||||
* become hidden. Defaults to false.
|
|
||||||
* - disableTelemetry: By default, switching tabs on and off in the sidebar
|
|
||||||
* will record tool usage in telemetry, pass this option to true to avoid it.
|
|
||||||
*
|
|
||||||
* Events raised:
|
|
||||||
* - new-tab-registered : After a tab has been added via addTab. The tab ID
|
|
||||||
* is passed with the event. This however, is raised before the tab iframe
|
|
||||||
* is fully loaded.
|
|
||||||
* - <tabid>-ready : After the tab iframe has been loaded
|
|
||||||
* - <tabid>-selected : After tab <tabid> was selected
|
|
||||||
* - select : Same as above, but for any tab, the ID is passed with the event
|
|
||||||
* - <tabid>-unselected : After tab <tabid> is unselected
|
|
||||||
*/
|
|
||||||
function ToolSidebar(tabbox, panel, uid, options = {}) {
|
|
||||||
EventEmitter.decorate(this);
|
|
||||||
|
|
||||||
this._tabbox = tabbox;
|
|
||||||
this._uid = uid;
|
|
||||||
this._panelDoc = this._tabbox.ownerDocument;
|
|
||||||
this._toolPanel = panel;
|
|
||||||
this._options = options;
|
|
||||||
|
|
||||||
this._onTabBoxOverflow = this._onTabBoxOverflow.bind(this);
|
|
||||||
this._onTabBoxUnderflow = this._onTabBoxUnderflow.bind(this);
|
|
||||||
|
|
||||||
const width = Services.prefs.getIntPref(
|
|
||||||
"devtools.toolsidebar-width." + this._uid,
|
|
||||||
undefined
|
|
||||||
);
|
|
||||||
if (width) {
|
|
||||||
this._width = width;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!options.disableTelemetry) {
|
|
||||||
this._telemetry = new Telemetry();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._tabbox.tabpanels.addEventListener("select", this, true);
|
|
||||||
|
|
||||||
this._tabs = new Map();
|
|
||||||
|
|
||||||
// Check for existing tabs in the DOM and add them.
|
|
||||||
this.addExistingTabs();
|
|
||||||
|
|
||||||
if (this._options.hideTabstripe) {
|
|
||||||
this._tabbox.setAttribute("hidetabs", "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._options.showAllTabsMenu) {
|
|
||||||
this.addAllTabsMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._toolPanel.emit("sidebar-created", this);
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.ToolSidebar = ToolSidebar;
|
|
||||||
|
|
||||||
ToolSidebar.prototype = {
|
|
||||||
TAB_ID_PREFIX: "sidebar-tab-",
|
|
||||||
|
|
||||||
TABPANEL_ID_PREFIX: "sidebar-panel-",
|
|
||||||
|
|
||||||
get toolboxSessionId() {
|
|
||||||
const frameElement = this._panelDoc.ownerGlobal.parent.frameElement;
|
|
||||||
|
|
||||||
if (frameElement) {
|
|
||||||
return frameElement.getAttribute("session_id");
|
|
||||||
}
|
|
||||||
|
|
||||||
// We are not running inside a toolbox... this is probably a scratchpad
|
|
||||||
// instance so return -1.
|
|
||||||
return -1;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a "…" button at the end of the tabstripe that toggles a dropdown menu
|
|
||||||
* containing the list of all tabs if any become hidden due to lack of room.
|
|
||||||
*
|
|
||||||
* If the ToolSidebar was created with the "showAllTabsMenu" option set to
|
|
||||||
* true, this is already done automatically. If not, you may call this
|
|
||||||
* function at any time to add the menu.
|
|
||||||
*/
|
|
||||||
addAllTabsMenu: function() {
|
|
||||||
if (this._allTabsBtn) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tabs = this._tabbox.tabs;
|
|
||||||
|
|
||||||
// Create a container and insert it first in the tabbox
|
|
||||||
const allTabsContainer = this._panelDoc.createXULElement("stack");
|
|
||||||
this._tabbox.insertBefore(allTabsContainer, tabs);
|
|
||||||
|
|
||||||
// Move the tabs inside and make them flex
|
|
||||||
allTabsContainer.appendChild(tabs);
|
|
||||||
tabs.setAttribute("flex", "1");
|
|
||||||
|
|
||||||
// Create the dropdown menu next to the tabs
|
|
||||||
this._allTabsBtn = this._panelDoc.createXULElement("toolbarbutton");
|
|
||||||
this._allTabsBtn.setAttribute("class", "devtools-sidebar-alltabs");
|
|
||||||
this._allTabsBtn.setAttribute("end", "0");
|
|
||||||
this._allTabsBtn.setAttribute("top", "0");
|
|
||||||
this._allTabsBtn.setAttribute("width", "15");
|
|
||||||
this._allTabsBtn.setAttribute("type", "menu");
|
|
||||||
this._allTabsBtn.setAttribute(
|
|
||||||
"tooltiptext",
|
|
||||||
L10N.getStr("sidebar.showAllTabs.tooltip")
|
|
||||||
);
|
|
||||||
this._allTabsBtn.setAttribute("hidden", "true");
|
|
||||||
allTabsContainer.appendChild(this._allTabsBtn);
|
|
||||||
|
|
||||||
const menuPopup = this._panelDoc.createXULElement("menupopup");
|
|
||||||
this._allTabsBtn.appendChild(menuPopup);
|
|
||||||
|
|
||||||
// Listening to tabs overflow event to toggle the alltabs button
|
|
||||||
tabs.addEventListener("overflow", this._onTabBoxOverflow);
|
|
||||||
tabs.addEventListener("underflow", this._onTabBoxUnderflow);
|
|
||||||
|
|
||||||
// Add menuitems to the alltabs menu if there are already tabs in the
|
|
||||||
// sidebar
|
|
||||||
for (const [id, tab] of this._tabs) {
|
|
||||||
const item = this._addItemToAllTabsMenu(id, tab, {
|
|
||||||
selected: tab.hasAttribute("selected"),
|
|
||||||
});
|
|
||||||
if (tab.hidden) {
|
|
||||||
item.hidden = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
removeAllTabsMenu: function() {
|
|
||||||
if (!this._allTabsBtn) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tabs = this._tabbox.tabs;
|
|
||||||
|
|
||||||
tabs.removeEventListener("overflow", this._onTabBoxOverflow);
|
|
||||||
tabs.removeEventListener("underflow", this._onTabBoxUnderflow);
|
|
||||||
|
|
||||||
// Moving back the tabs as a first child of the tabbox
|
|
||||||
this._tabbox.insertBefore(tabs, this._tabbox.tabpanels);
|
|
||||||
this._tabbox.querySelector("stack").remove();
|
|
||||||
|
|
||||||
this._allTabsBtn = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onTabBoxOverflow: function() {
|
|
||||||
this._allTabsBtn.removeAttribute("hidden");
|
|
||||||
},
|
|
||||||
|
|
||||||
_onTabBoxUnderflow: function() {
|
|
||||||
this._allTabsBtn.setAttribute("hidden", "true");
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an item in the allTabs menu for a given tab.
|
|
||||||
*/
|
|
||||||
_addItemToAllTabsMenu: function(id, tab, options) {
|
|
||||||
if (!this._allTabsBtn) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const item = this._panelDoc.createXULElement("menuitem");
|
|
||||||
const idPrefix = "sidebar-alltabs-item-";
|
|
||||||
item.setAttribute("id", idPrefix + id);
|
|
||||||
item.setAttribute("label", tab.getAttribute("label"));
|
|
||||||
item.setAttribute("type", "checkbox");
|
|
||||||
if (options.selected) {
|
|
||||||
item.setAttribute("checked", true);
|
|
||||||
}
|
|
||||||
// The auto-checking of menuitems in this menu doesn't work, so let's do
|
|
||||||
// it manually
|
|
||||||
item.setAttribute("autocheck", false);
|
|
||||||
|
|
||||||
const menu = this._allTabsBtn.querySelector("menupopup");
|
|
||||||
if (options.insertBefore) {
|
|
||||||
const referenceItem = menu.querySelector(
|
|
||||||
`#${idPrefix}${options.insertBefore}`
|
|
||||||
);
|
|
||||||
menu.insertBefore(item, referenceItem);
|
|
||||||
} else {
|
|
||||||
menu.appendChild(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
item.addEventListener("click", () => {
|
|
||||||
this._tabbox.selectedTab = tab;
|
|
||||||
});
|
|
||||||
|
|
||||||
tab.allTabsMenuItem = item;
|
|
||||||
|
|
||||||
return item;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a tab. A tab is a document.
|
|
||||||
* The document must have a title, which will be used as the name of the tab.
|
|
||||||
*
|
|
||||||
* @param {string} id The unique id for this tab.
|
|
||||||
* @param {string} url The URL of the document to load in this new tab.
|
|
||||||
* @param {Object} options A set of options for this new tab:
|
|
||||||
* - {Boolean} selected Set to true to make this new tab selected by default.
|
|
||||||
* - {String} insertBefore By default, the new tab is appended at the end of the
|
|
||||||
* tabbox, pass the ID of an existing tab to insert it before that tab instead.
|
|
||||||
*/
|
|
||||||
addTab: function(id, url, options = {}) {
|
|
||||||
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.createXULElement("tab");
|
|
||||||
|
|
||||||
tab.setAttribute("id", this.TAB_ID_PREFIX + id);
|
|
||||||
tab.setAttribute("crop", "end");
|
|
||||||
// Avoid showing "undefined" while the tab is loading
|
|
||||||
tab.setAttribute("label", "");
|
|
||||||
|
|
||||||
if (options.insertBefore) {
|
|
||||||
const referenceTab = this.getTab(options.insertBefore);
|
|
||||||
this._tabbox.tabs.insertBefore(tab, referenceTab);
|
|
||||||
} else {
|
|
||||||
this._tabbox.tabs.appendChild(tab);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the tab to the allTabs menu if exists
|
|
||||||
const allTabsItem = this._addItemToAllTabsMenu(id, tab, options);
|
|
||||||
|
|
||||||
const onIFrameLoaded = event => {
|
|
||||||
const win = iframe.contentWindow;
|
|
||||||
const doc = win.document;
|
|
||||||
tab.setAttribute("label", doc.title);
|
|
||||||
|
|
||||||
if (allTabsItem) {
|
|
||||||
allTabsItem.setAttribute("label", doc.title);
|
|
||||||
}
|
|
||||||
|
|
||||||
iframe.removeEventListener("load", onIFrameLoaded, true);
|
|
||||||
if ("setPanel" in win) {
|
|
||||||
win.setPanel(this._toolPanel, iframe);
|
|
||||||
}
|
|
||||||
this.emit(id + "-ready");
|
|
||||||
};
|
|
||||||
|
|
||||||
iframe.addEventListener("load", onIFrameLoaded, true);
|
|
||||||
|
|
||||||
const tabpanel = this._panelDoc.createXULElement("tabpanel");
|
|
||||||
tabpanel.setAttribute("id", this.TABPANEL_ID_PREFIX + id);
|
|
||||||
tabpanel.appendChild(iframe);
|
|
||||||
|
|
||||||
if (options.insertBefore) {
|
|
||||||
const referenceTabpanel = this.getTabPanel(options.insertBefore);
|
|
||||||
this._tabbox.tabpanels.insertBefore(tabpanel, referenceTabpanel);
|
|
||||||
} else {
|
|
||||||
this._tabbox.tabpanels.appendChild(tabpanel);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._tooltip = this._panelDoc.createXULElement("tooltip");
|
|
||||||
this._tooltip.id = "aHTMLTooltip";
|
|
||||||
tabpanel.appendChild(this._tooltip);
|
|
||||||
this._tooltip.page = true;
|
|
||||||
|
|
||||||
tab.linkedPanel = this.TABPANEL_ID_PREFIX + id;
|
|
||||||
|
|
||||||
// We store the index of this tab.
|
|
||||||
this._tabs.set(id, tab);
|
|
||||||
|
|
||||||
if (options.selected) {
|
|
||||||
this._selectTabSoon(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.emit("new-tab-registered", id);
|
|
||||||
},
|
|
||||||
|
|
||||||
untitledTabsIndex: 0,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search for existing tabs in the markup that aren't know yet and add them.
|
|
||||||
*/
|
|
||||||
addExistingTabs: function() {
|
|
||||||
const knownTabs = [...this._tabs.values()];
|
|
||||||
|
|
||||||
for (const tab of this._tabbox.tabs.querySelectorAll("tab")) {
|
|
||||||
if (knownTabs.includes(tab)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find an ID for this unknown tab
|
|
||||||
let id =
|
|
||||||
tab.getAttribute("id") || "untitled-tab-" + this.untitledTabsIndex++;
|
|
||||||
|
|
||||||
// If the existing tab contains the tab ID prefix, extract the ID of the
|
|
||||||
// tab
|
|
||||||
if (id.startsWith(this.TAB_ID_PREFIX)) {
|
|
||||||
id = id.split(this.TAB_ID_PREFIX).pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register the tab
|
|
||||||
this._tabs.set(id, tab);
|
|
||||||
this.emit("new-tab-registered", id);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an existing tab.
|
|
||||||
* @param {String} tabId The ID of the tab that was used to register it, or
|
|
||||||
* the tab id attribute value if the tab existed before the sidebar got created.
|
|
||||||
* @param {String} tabPanelId Optional. If provided, this ID will be used
|
|
||||||
* instead of the tabId to retrieve and remove the corresponding <tabpanel>
|
|
||||||
*/
|
|
||||||
async removeTab(tabId, tabPanelId) {
|
|
||||||
// Remove the tab if it can be found
|
|
||||||
const tab = this.getTab(tabId);
|
|
||||||
if (!tab) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const win = this.getWindowForTab(tabId);
|
|
||||||
if (win && "destroy" in win) {
|
|
||||||
await win.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
tab.remove();
|
|
||||||
|
|
||||||
// Also remove the tabpanel
|
|
||||||
const panel = this.getTabPanel(tabPanelId || tabId);
|
|
||||||
if (panel) {
|
|
||||||
panel.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._tabs.delete(tabId);
|
|
||||||
this.emit("tab-unregistered", tabId);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show or hide a specific tab.
|
|
||||||
* @param {Boolean} isVisible True to show the tab/tabpanel, False to hide it.
|
|
||||||
* @param {String} id The ID of the tab to be hidden.
|
|
||||||
*/
|
|
||||||
toggleTab: function(isVisible, id) {
|
|
||||||
// Toggle the tab.
|
|
||||||
const tab = this.getTab(id);
|
|
||||||
if (!tab) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tab.hidden = !isVisible;
|
|
||||||
|
|
||||||
// Toggle the item in the allTabs menu.
|
|
||||||
if (this._allTabsBtn) {
|
|
||||||
this._allTabsBtn.querySelector(
|
|
||||||
"#sidebar-alltabs-item-" + id
|
|
||||||
).hidden = !isVisible;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Select a specific tab.
|
|
||||||
*/
|
|
||||||
select: function(id) {
|
|
||||||
const tab = this.getTab(id);
|
|
||||||
if (tab) {
|
|
||||||
this._tabbox.selectedTab = tab;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hack required to select a tab right after it was created.
|
|
||||||
*
|
|
||||||
* @param {String} id
|
|
||||||
* The sidebar tab id to select.
|
|
||||||
*/
|
|
||||||
_selectTabSoon: function(id) {
|
|
||||||
this._panelDoc.defaultView.setTimeout(() => {
|
|
||||||
this.select(id);
|
|
||||||
}, 0);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the id of the selected tab.
|
|
||||||
*/
|
|
||||||
getCurrentTabID: function() {
|
|
||||||
let currentID = null;
|
|
||||||
for (const [id, tab] of this._tabs) {
|
|
||||||
if (this._tabbox.tabs.selectedItem == tab) {
|
|
||||||
currentID = id;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return currentID;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the requested tab panel based on the id.
|
|
||||||
* @param {String} id
|
|
||||||
* @return {DOMNode}
|
|
||||||
*/
|
|
||||||
getTabPanel: function(id) {
|
|
||||||
// Search with and without the ID prefix as there might have been existing
|
|
||||||
// tabpanels by the time the sidebar got created
|
|
||||||
return this._tabbox.tabpanels.querySelector(
|
|
||||||
"#" + this.TABPANEL_ID_PREFIX + id + ", #" + id
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the tab based on the provided id, if one was registered with this id.
|
|
||||||
* @param {String} id
|
|
||||||
* @return {DOMNode}
|
|
||||||
*/
|
|
||||||
getTab: function(id) {
|
|
||||||
// FIXME: A workaround for broken browser_net_raw_headers.js failure only in non-e10s mode
|
|
||||||
return this._tabs && this._tabs.get(id);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event handler.
|
|
||||||
*/
|
|
||||||
handleEvent: function(event) {
|
|
||||||
if (event.type !== "select" || this._destroyed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._currentTool == this.getCurrentTabID()) {
|
|
||||||
// Tool hasn't changed.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const previousTool = this._currentTool;
|
|
||||||
this._currentTool = this.getCurrentTabID();
|
|
||||||
if (previousTool) {
|
|
||||||
if (this._telemetry) {
|
|
||||||
this._telemetry.toolClosed(previousTool, this.toolboxSessionId, this);
|
|
||||||
}
|
|
||||||
this.emit(previousTool + "-unselected");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._telemetry) {
|
|
||||||
this._telemetry.toolOpened(
|
|
||||||
this._currentTool,
|
|
||||||
this.toolboxSessionId,
|
|
||||||
this
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.emit(this._currentTool + "-selected");
|
|
||||||
this.emit("select", this._currentTool);
|
|
||||||
|
|
||||||
// Handlers for "select"/"...-selected"/"...-unselected" events might have
|
|
||||||
// destroyed the sidebar in the meantime.
|
|
||||||
if (this._destroyed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle menuitem selection if the allTabsMenu is there by unchecking all
|
|
||||||
// items except the selected one.
|
|
||||||
const tab = this._tabbox.selectedTab;
|
|
||||||
if (tab.allTabsMenuItem) {
|
|
||||||
for (const otherItem of this._allTabsBtn.querySelectorAll("menuitem")) {
|
|
||||||
otherItem.removeAttribute("checked");
|
|
||||||
}
|
|
||||||
tab.allTabsMenuItem.setAttribute("checked", true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggle sidebar's visibility state.
|
|
||||||
*/
|
|
||||||
toggle: function() {
|
|
||||||
if (this._tabbox.hasAttribute("hidden")) {
|
|
||||||
this.show();
|
|
||||||
} else {
|
|
||||||
this.hide();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the sidebar.
|
|
||||||
*
|
|
||||||
* @param {String} id
|
|
||||||
* The sidebar tab id to select.
|
|
||||||
*/
|
|
||||||
show: function(id) {
|
|
||||||
if (this._width) {
|
|
||||||
this._tabbox.width = this._width;
|
|
||||||
}
|
|
||||||
this._tabbox.removeAttribute("hidden");
|
|
||||||
|
|
||||||
// If an id is given, select the corresponding sidebar tab and record the
|
|
||||||
// tool opened.
|
|
||||||
if (id) {
|
|
||||||
this._currentTool = id;
|
|
||||||
|
|
||||||
if (this._telemetry) {
|
|
||||||
this._telemetry.toolOpened(
|
|
||||||
this._currentTool,
|
|
||||||
this.toolboxSessionId,
|
|
||||||
this
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._selectTabSoon(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.emit("show");
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the sidebar.
|
|
||||||
*/
|
|
||||||
hide: function() {
|
|
||||||
Services.prefs.setIntPref(
|
|
||||||
"devtools.toolsidebar-width." + this._uid,
|
|
||||||
this._tabbox.width
|
|
||||||
);
|
|
||||||
this._tabbox.setAttribute("hidden", "true");
|
|
||||||
this._panelDoc.activeElement.blur();
|
|
||||||
|
|
||||||
this.emit("hide");
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the window containing the tab content.
|
|
||||||
*/
|
|
||||||
getWindowForTab: function(id) {
|
|
||||||
if (!this._tabs.has(id)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the tabpanel and make sure it contains an iframe
|
|
||||||
const panel = this.getTabPanel(id);
|
|
||||||
if (!panel || !panel.firstChild || !panel.firstChild.contentWindow) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return panel.firstChild.contentWindow;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clean-up.
|
|
||||||
*/
|
|
||||||
async destroy() {
|
|
||||||
if (this._destroyed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._destroyed = true;
|
|
||||||
|
|
||||||
Services.prefs.setIntPref(
|
|
||||||
"devtools.toolsidebar-width." + this._uid,
|
|
||||||
this._tabbox.width
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this._allTabsBtn) {
|
|
||||||
this.removeAllTabsMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._tabbox.tabpanels.removeEventListener("select", this, true);
|
|
||||||
|
|
||||||
// Note that we check for the existence of this._tabbox.tabpanels at each
|
|
||||||
// step as the container window may have been closed by the time one of the
|
|
||||||
// panel's destroy promise resolves.
|
|
||||||
while (this._tabbox.tabpanels && this._tabbox.tabpanels.hasChildNodes()) {
|
|
||||||
const panel = this._tabbox.tabpanels.firstChild;
|
|
||||||
const win = panel.firstChild.contentWindow;
|
|
||||||
if (win && "destroy" in win) {
|
|
||||||
await win.destroy();
|
|
||||||
}
|
|
||||||
panel.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
while (this._tabbox.tabs && this._tabbox.tabs.hasChildNodes()) {
|
|
||||||
this._tabbox.tabs.firstChild.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._currentTool && this._telemetry) {
|
|
||||||
this._telemetry.toolClosed(
|
|
||||||
this._currentTool,
|
|
||||||
this.toolboxSessionId,
|
|
||||||
this
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._toolPanel.emit("sidebar-destroyed", this);
|
|
||||||
|
|
||||||
this._tabs = null;
|
|
||||||
this._tabbox = null;
|
|
||||||
this._panelDoc = null;
|
|
||||||
this._toolPanel = null;
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -6,10 +6,6 @@ support-files =
|
||||||
browser_toolbox_options_disable_js_iframe.html
|
browser_toolbox_options_disable_js_iframe.html
|
||||||
browser_toolbox_options_disable_cache.sjs
|
browser_toolbox_options_disable_cache.sjs
|
||||||
browser_toolbox_options_disable_cache.css.sjs
|
browser_toolbox_options_disable_cache.css.sjs
|
||||||
browser_toolbox_sidebar_existing_tabs.xul
|
|
||||||
browser_toolbox_sidebar_events.xul
|
|
||||||
browser_toolbox_sidebar_tool.xul
|
|
||||||
browser_toolbox_sidebar_toolURL.xul
|
|
||||||
browser_toolbox_window_title_changes_page.html
|
browser_toolbox_window_title_changes_page.html
|
||||||
browser_toolbox_window_title_frame_select_page.html
|
browser_toolbox_window_title_frame_select_page.html
|
||||||
code_bundle_late_script.js
|
code_bundle_late_script.js
|
||||||
|
@ -126,10 +122,6 @@ run-if = e10s
|
||||||
[browser_toolbox_selected_tool_unavailable.js]
|
[browser_toolbox_selected_tool_unavailable.js]
|
||||||
[browser_toolbox_selectionchanged_event.js]
|
[browser_toolbox_selectionchanged_event.js]
|
||||||
[browser_toolbox_show_toolbox_tool_ready.js]
|
[browser_toolbox_show_toolbox_tool_ready.js]
|
||||||
[browser_toolbox_sidebar.js]
|
|
||||||
[browser_toolbox_sidebar_events.js]
|
|
||||||
[browser_toolbox_sidebar_existing_tabs.js]
|
|
||||||
[browser_toolbox_sidebar_overflow_menu.js]
|
|
||||||
[browser_toolbox_split_console.js]
|
[browser_toolbox_split_console.js]
|
||||||
[browser_toolbox_target.js]
|
[browser_toolbox_target.js]
|
||||||
[browser_toolbox_tabsswitch_shortcuts.js]
|
[browser_toolbox_tabsswitch_shortcuts.js]
|
||||||
|
|
|
@ -1,192 +0,0 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
function test() {
|
|
||||||
const { ToolSidebar } = require("devtools/client/framework/sidebar");
|
|
||||||
|
|
||||||
const tab1URL = "data:text/html;charset=utf8,<title>1</title><p>1</p>";
|
|
||||||
const tab2URL = "data:text/html;charset=utf8,<title>2</title><p>2</p>";
|
|
||||||
const tab3URL = "data:text/html;charset=utf8,<title>3</title><p>3</p>";
|
|
||||||
|
|
||||||
let tab1Selected = false;
|
|
||||||
const registeredTabs = {};
|
|
||||||
const readyTabs = {};
|
|
||||||
|
|
||||||
const toolDefinition = {
|
|
||||||
id: "fakeTool4242",
|
|
||||||
visibilityswitch: "devtools.fakeTool4242.enabled",
|
|
||||||
url: CHROME_URL_ROOT + "browser_toolbox_sidebar_toolURL.xul",
|
|
||||||
label: "FAKE TOOL!!!",
|
|
||||||
isTargetSupported: () => true,
|
|
||||||
build: function(iframeWindow, toolbox) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
executeSoon(() => {
|
|
||||||
resolve({
|
|
||||||
target: toolbox.target,
|
|
||||||
toolbox: toolbox,
|
|
||||||
isReady: true,
|
|
||||||
destroy: function() {},
|
|
||||||
panelDoc: iframeWindow.document,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
gDevTools.registerTool(toolDefinition);
|
|
||||||
|
|
||||||
addTab("about:blank").then(async function(aTab) {
|
|
||||||
const target = await TargetFactory.forTab(aTab);
|
|
||||||
gDevTools
|
|
||||||
.showToolbox(target, toolDefinition.id)
|
|
||||||
.then(function(toolbox) {
|
|
||||||
const panel = toolbox.getPanel(toolDefinition.id);
|
|
||||||
panel.toolbox = toolbox;
|
|
||||||
ok(true, "Tool open");
|
|
||||||
|
|
||||||
const tabbox = panel.panelDoc.getElementById("sidebar");
|
|
||||||
panel.sidebar = new ToolSidebar(tabbox, panel, "testbug865688", true);
|
|
||||||
|
|
||||||
panel.sidebar.on("new-tab-registered", function(id) {
|
|
||||||
registeredTabs[id] = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
panel.sidebar.once("tab1-ready", function() {
|
|
||||||
info("tab1-ready");
|
|
||||||
readyTabs.tab1 = true;
|
|
||||||
allTabsReady(panel);
|
|
||||||
});
|
|
||||||
|
|
||||||
panel.sidebar.once("tab2-ready", function() {
|
|
||||||
info("tab2-ready");
|
|
||||||
readyTabs.tab2 = true;
|
|
||||||
allTabsReady(panel);
|
|
||||||
});
|
|
||||||
|
|
||||||
panel.sidebar.once("tab3-ready", function() {
|
|
||||||
info("tab3-ready");
|
|
||||||
readyTabs.tab3 = true;
|
|
||||||
allTabsReady(panel);
|
|
||||||
});
|
|
||||||
|
|
||||||
panel.sidebar.once("tab1-selected", function() {
|
|
||||||
info("tab1-selected");
|
|
||||||
tab1Selected = true;
|
|
||||||
allTabsReady(panel);
|
|
||||||
});
|
|
||||||
|
|
||||||
panel.sidebar.addTab("tab1", tab1URL, { selected: true });
|
|
||||||
panel.sidebar.addTab("tab2", tab2URL);
|
|
||||||
panel.sidebar.addTab("tab3", tab3URL);
|
|
||||||
|
|
||||||
panel.sidebar.show();
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
});
|
|
||||||
|
|
||||||
function allTabsReady(panel) {
|
|
||||||
if (
|
|
||||||
!tab1Selected ||
|
|
||||||
!readyTabs.tab1 ||
|
|
||||||
!readyTabs.tab2 ||
|
|
||||||
!readyTabs.tab3
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok(registeredTabs.tab1, "tab1 registered");
|
|
||||||
ok(registeredTabs.tab2, "tab2 registered");
|
|
||||||
ok(registeredTabs.tab3, "tab3 registered");
|
|
||||||
ok(readyTabs.tab1, "tab1 ready");
|
|
||||||
ok(readyTabs.tab2, "tab2 ready");
|
|
||||||
ok(readyTabs.tab3, "tab3 ready");
|
|
||||||
|
|
||||||
const tabs = panel.sidebar._tabbox.querySelectorAll("tab");
|
|
||||||
const panels = panel.sidebar._tabbox.querySelectorAll("tabpanel");
|
|
||||||
let label = 1;
|
|
||||||
for (const tab of tabs) {
|
|
||||||
is(tab.getAttribute("label"), label++, "Tab has the right title");
|
|
||||||
}
|
|
||||||
|
|
||||||
is(label, 4, "Found the right amount of tabs.");
|
|
||||||
is(panel.sidebar._tabbox.selectedPanel, panels[0], "First tab is selected");
|
|
||||||
is(panel.sidebar.getCurrentTabID(), "tab1", "getCurrentTabID() is correct");
|
|
||||||
|
|
||||||
panel.sidebar.once("tab1-unselected", function() {
|
|
||||||
ok(true, "received 'unselected' event");
|
|
||||||
panel.sidebar.once("tab2-selected", function() {
|
|
||||||
ok(true, "received 'selected' event");
|
|
||||||
tabs[1].focus();
|
|
||||||
is(
|
|
||||||
panel.sidebar._panelDoc.activeElement,
|
|
||||||
tabs[1],
|
|
||||||
"Focus is set to second tab"
|
|
||||||
);
|
|
||||||
panel.sidebar.hide();
|
|
||||||
isnot(
|
|
||||||
panel.sidebar._panelDoc.activeElement,
|
|
||||||
tabs[1],
|
|
||||||
"Focus is reset for sidebar"
|
|
||||||
);
|
|
||||||
is(
|
|
||||||
panel.sidebar._tabbox.getAttribute("hidden"),
|
|
||||||
"true",
|
|
||||||
"Sidebar hidden"
|
|
||||||
);
|
|
||||||
is(
|
|
||||||
panel.sidebar.getWindowForTab("tab1").location.href,
|
|
||||||
tab1URL,
|
|
||||||
"Window is accessible"
|
|
||||||
);
|
|
||||||
testRemoval(panel);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
panel.sidebar.select("tab2");
|
|
||||||
}
|
|
||||||
|
|
||||||
function testRemoval(panel) {
|
|
||||||
panel.sidebar.once("tab-unregistered", function(id) {
|
|
||||||
info("tab-unregistered");
|
|
||||||
registeredTabs[id] = false;
|
|
||||||
|
|
||||||
is(id, "tab3", "The right tab must be removed");
|
|
||||||
|
|
||||||
const tabs = panel.sidebar._tabbox.querySelectorAll("tab");
|
|
||||||
const panels = panel.sidebar._tabbox.querySelectorAll("tabpanel");
|
|
||||||
|
|
||||||
is(tabs.length, 2, "There is the right number of tabs");
|
|
||||||
is(panels.length, 2, "There is the right number of panels");
|
|
||||||
|
|
||||||
testWidth(panel);
|
|
||||||
});
|
|
||||||
|
|
||||||
panel.sidebar.removeTab("tab3");
|
|
||||||
}
|
|
||||||
|
|
||||||
function testWidth(panel) {
|
|
||||||
const tabbox = panel.panelDoc.getElementById("sidebar");
|
|
||||||
tabbox.width = 420;
|
|
||||||
panel.sidebar.destroy().then(function() {
|
|
||||||
tabbox.width = 0;
|
|
||||||
panel.sidebar = new ToolSidebar(tabbox, panel, "testbug865688", true);
|
|
||||||
panel.sidebar.show();
|
|
||||||
is(panel.panelDoc.getElementById("sidebar").width, 420, "Width restored");
|
|
||||||
|
|
||||||
finishUp(panel);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function finishUp(panel) {
|
|
||||||
panel.sidebar.destroy();
|
|
||||||
panel.toolbox.destroy().then(function() {
|
|
||||||
gDevTools.unregisterTool(toolDefinition.id);
|
|
||||||
|
|
||||||
gBrowser.removeCurrentTab();
|
|
||||||
|
|
||||||
executeSoon(function() {
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,88 +0,0 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
function test() {
|
|
||||||
const { ToolSidebar } = require("devtools/client/framework/sidebar");
|
|
||||||
|
|
||||||
const tab1URL = "data:text/html;charset=utf8,<title>1</title><p>1</p>";
|
|
||||||
|
|
||||||
const collectedEvents = [];
|
|
||||||
|
|
||||||
const toolDefinition = {
|
|
||||||
id: "testTool1072208",
|
|
||||||
visibilityswitch: "devtools.testTool1072208.enabled",
|
|
||||||
url: CHROME_URL_ROOT + "browser_toolbox_sidebar_events.xul",
|
|
||||||
label: "Test tool",
|
|
||||||
isTargetSupported: () => true,
|
|
||||||
build: function(iframeWindow, toolbox) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
executeSoon(() => {
|
|
||||||
resolve({
|
|
||||||
target: toolbox.target,
|
|
||||||
toolbox: toolbox,
|
|
||||||
isReady: true,
|
|
||||||
destroy: function() {},
|
|
||||||
panelDoc: iframeWindow.document,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
gDevTools.registerTool(toolDefinition);
|
|
||||||
|
|
||||||
addTab("about:blank").then(async function(aTab) {
|
|
||||||
const target = await TargetFactory.forTab(aTab);
|
|
||||||
gDevTools
|
|
||||||
.showToolbox(target, toolDefinition.id)
|
|
||||||
.then(function(toolbox) {
|
|
||||||
const panel = toolbox.getPanel(toolDefinition.id);
|
|
||||||
ok(true, "Tool open");
|
|
||||||
|
|
||||||
panel.once("sidebar-created", function() {
|
|
||||||
collectedEvents.push("sidebar-created");
|
|
||||||
});
|
|
||||||
|
|
||||||
panel.once("sidebar-destroyed", function() {
|
|
||||||
collectedEvents.push("sidebar-destroyed");
|
|
||||||
});
|
|
||||||
|
|
||||||
const tabbox = panel.panelDoc.getElementById("sidebar");
|
|
||||||
panel.sidebar = new ToolSidebar(tabbox, panel, "testbug1072208", true);
|
|
||||||
|
|
||||||
panel.sidebar.once("show", function() {
|
|
||||||
collectedEvents.push("show");
|
|
||||||
});
|
|
||||||
|
|
||||||
panel.sidebar.once("hide", function() {
|
|
||||||
collectedEvents.push("hide");
|
|
||||||
});
|
|
||||||
|
|
||||||
panel.sidebar.once("tab1-selected", () => finishUp(panel));
|
|
||||||
panel.sidebar.addTab("tab1", tab1URL, { selected: true });
|
|
||||||
panel.sidebar.show();
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
});
|
|
||||||
|
|
||||||
function finishUp(panel) {
|
|
||||||
panel.sidebar.hide();
|
|
||||||
panel.sidebar.destroy();
|
|
||||||
|
|
||||||
const events = collectedEvents.join(":");
|
|
||||||
is(
|
|
||||||
events,
|
|
||||||
"sidebar-created:show:hide:sidebar-destroyed",
|
|
||||||
"Found the right amount of collected events."
|
|
||||||
);
|
|
||||||
|
|
||||||
panel.toolbox.destroy().then(function() {
|
|
||||||
gDevTools.unregisterTool(toolDefinition.id);
|
|
||||||
gBrowser.removeCurrentTab();
|
|
||||||
|
|
||||||
executeSoon(function() {
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
<?xml version='1.0'?>
|
|
||||||
<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'>
|
|
||||||
<hbox flex='1'><description flex='1'>foo</description><splitter class='devtools-side-splitter'/>
|
|
||||||
<tabbox flex='1' id='sidebar' class='devtools-sidebar-tabs'><tabs/><tabpanels flex='1'/></tabbox>
|
|
||||||
</hbox>
|
|
||||||
</window>
|
|
|
@ -1,77 +0,0 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Test that the sidebar widget auto-registers existing tabs.
|
|
||||||
|
|
||||||
const { ToolSidebar } = require("devtools/client/framework/sidebar");
|
|
||||||
|
|
||||||
const testToolDefinition = {
|
|
||||||
id: "testTool",
|
|
||||||
url: CHROME_URL_ROOT + "browser_toolbox_sidebar_existing_tabs.xul",
|
|
||||||
label: "Test Tool",
|
|
||||||
isTargetSupported: () => true,
|
|
||||||
build: (iframeWindow, toolbox) => {
|
|
||||||
return promise.resolve({
|
|
||||||
target: toolbox.target,
|
|
||||||
toolbox: toolbox,
|
|
||||||
isReady: true,
|
|
||||||
destroy: () => {},
|
|
||||||
panelDoc: iframeWindow.document,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
add_task(async function() {
|
|
||||||
const tab = await addTab("about:blank");
|
|
||||||
|
|
||||||
const target = await TargetFactory.forTab(tab);
|
|
||||||
|
|
||||||
gDevTools.registerTool(testToolDefinition);
|
|
||||||
const toolbox = await gDevTools.showToolbox(target, testToolDefinition.id);
|
|
||||||
|
|
||||||
const toolPanel = toolbox.getPanel(testToolDefinition.id);
|
|
||||||
const tabbox = toolPanel.panelDoc.getElementById("sidebar");
|
|
||||||
|
|
||||||
info("Creating the sidebar widget");
|
|
||||||
const sidebar = new ToolSidebar(tabbox, toolPanel, "bug1101569");
|
|
||||||
|
|
||||||
info("Checking that existing tabs have been registered");
|
|
||||||
ok(sidebar.getTab("tab1"), "Existing tab 1 was found");
|
|
||||||
ok(sidebar.getTab("tab2"), "Existing tab 2 was found");
|
|
||||||
ok(sidebar.getTabPanel("tabpanel1"), "Existing tabpanel 1 was found");
|
|
||||||
ok(sidebar.getTabPanel("tabpanel2"), "Existing tabpanel 2 was found");
|
|
||||||
|
|
||||||
info("Checking that the sidebar API works with existing tabs");
|
|
||||||
|
|
||||||
sidebar.select("tab2");
|
|
||||||
is(
|
|
||||||
tabbox.selectedTab,
|
|
||||||
tabbox.querySelector("#tab2"),
|
|
||||||
"Existing tabs can be selected"
|
|
||||||
);
|
|
||||||
|
|
||||||
sidebar.select("tab1");
|
|
||||||
is(
|
|
||||||
tabbox.selectedTab,
|
|
||||||
tabbox.querySelector("#tab1"),
|
|
||||||
"Existing tabs can be selected"
|
|
||||||
);
|
|
||||||
|
|
||||||
is(
|
|
||||||
sidebar.getCurrentTabID(),
|
|
||||||
"tab1",
|
|
||||||
"getCurrentTabID returns the expected id"
|
|
||||||
);
|
|
||||||
|
|
||||||
info("Removing a tab");
|
|
||||||
sidebar.removeTab("tab2", "tabpanel2");
|
|
||||||
ok(!sidebar.getTab("tab2"), "Tab 2 was removed correctly");
|
|
||||||
ok(!sidebar.getTabPanel("tabpanel2"), "Tabpanel 2 was removed correctly");
|
|
||||||
|
|
||||||
sidebar.destroy();
|
|
||||||
await toolbox.destroy();
|
|
||||||
gDevTools.unregisterTool(testToolDefinition.id);
|
|
||||||
gBrowser.removeCurrentTab();
|
|
||||||
});
|
|
|
@ -1,8 +0,0 @@
|
||||||
<?xml version='1.0'?>
|
|
||||||
<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'>
|
|
||||||
<hbox flex='1'><description flex='1'>test tool</description>
|
|
||||||
<splitter class='devtools-side-splitter'/>
|
|
||||||
<tabbox flex='1' id='sidebar' class='devtools-sidebar-tabs'>
|
|
||||||
<tabs><tab id='tab1' label='tab 1'></tab><tab id='tab2' label='tab 2'></tab></tabs>
|
|
||||||
<tabpanels flex='1'><tabpanel id='tabpanel1'>tab 1</tabpanel><tabpanel id='tabpanel2'>tab 2</tabpanel></tabpanels>
|
|
||||||
</tabbox></hbox></window>
|
|
|
@ -1,87 +0,0 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Test that the sidebar widget correctly displays the "all tabs..." button
|
|
||||||
// when the tabs overflow.
|
|
||||||
|
|
||||||
const { ToolSidebar } = require("devtools/client/framework/sidebar");
|
|
||||||
|
|
||||||
const testToolDefinition = {
|
|
||||||
id: "testTool",
|
|
||||||
url: CHROME_URL_ROOT + "browser_toolbox_sidebar_tool.xul",
|
|
||||||
label: "Test Tool",
|
|
||||||
isTargetSupported: () => true,
|
|
||||||
build: (iframeWindow, toolbox) => {
|
|
||||||
return {
|
|
||||||
target: toolbox.target,
|
|
||||||
toolbox: toolbox,
|
|
||||||
isReady: true,
|
|
||||||
destroy: () => {},
|
|
||||||
panelDoc: iframeWindow.document,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
add_task(async function() {
|
|
||||||
const tab = await addTab("about:blank");
|
|
||||||
const target = await TargetFactory.forTab(tab);
|
|
||||||
|
|
||||||
gDevTools.registerTool(testToolDefinition);
|
|
||||||
const toolbox = await gDevTools.showToolbox(target, testToolDefinition.id);
|
|
||||||
|
|
||||||
const toolPanel = toolbox.getPanel(testToolDefinition.id);
|
|
||||||
const tabbox = toolPanel.panelDoc.getElementById("sidebar");
|
|
||||||
|
|
||||||
info("Creating the sidebar widget");
|
|
||||||
const sidebar = new ToolSidebar(tabbox, toolPanel, "bug1101569", {
|
|
||||||
showAllTabsMenu: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const allTabsMenu = toolPanel.panelDoc.querySelector(
|
|
||||||
".devtools-sidebar-alltabs"
|
|
||||||
);
|
|
||||||
ok(allTabsMenu, "The all-tabs menu is available");
|
|
||||||
is(allTabsMenu.getAttribute("hidden"), "true", "The menu is hidden for now");
|
|
||||||
|
|
||||||
info("Adding 10 tabs to the sidebar widget");
|
|
||||||
for (let nb = 0; nb < 10; nb++) {
|
|
||||||
const url = `data:text/html;charset=utf8,<title>tab ${nb}</title><p>Test tab ${nb}</p>`;
|
|
||||||
sidebar.addTab("tab" + nb, url, { selected: nb === 0 });
|
|
||||||
}
|
|
||||||
|
|
||||||
info("Fake an overflow event so that the all-tabs menu is visible");
|
|
||||||
sidebar._onTabBoxOverflow();
|
|
||||||
ok(!allTabsMenu.hasAttribute("hidden"), "The all-tabs menu is now shown");
|
|
||||||
|
|
||||||
info("Select each tab, one by one");
|
|
||||||
for (let nb = 0; nb < 10; nb++) {
|
|
||||||
const id = "tab" + nb;
|
|
||||||
|
|
||||||
info("Found tab item nb " + nb);
|
|
||||||
const item = allTabsMenu.querySelector("#sidebar-alltabs-item-" + id);
|
|
||||||
|
|
||||||
info("Click on the tab");
|
|
||||||
EventUtils.sendMouseEvent(
|
|
||||||
{ type: "click" },
|
|
||||||
item,
|
|
||||||
toolPanel.panelDoc.defaultView
|
|
||||||
);
|
|
||||||
|
|
||||||
is(
|
|
||||||
tabbox.selectedTab.id,
|
|
||||||
"sidebar-tab-" + id,
|
|
||||||
"The selected tab is now nb " + nb
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
info("Fake an underflow event so that the all-tabs menu gets hidden");
|
|
||||||
sidebar._onTabBoxUnderflow();
|
|
||||||
is(allTabsMenu.getAttribute("hidden"), "true", "The all-tabs menu is hidden");
|
|
||||||
|
|
||||||
await sidebar.destroy();
|
|
||||||
await toolbox.destroy();
|
|
||||||
gDevTools.unregisterTool(testToolDefinition.id);
|
|
||||||
gBrowser.removeCurrentTab();
|
|
||||||
});
|
|
|
@ -1,18 +0,0 @@
|
||||||
<?xml version="1.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/. -->
|
|
||||||
<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
|
|
||||||
<?xml-stylesheet href="chrome://devtools/content/shared/widgets/widgets.css" type="text/css"?>
|
|
||||||
<?xml-stylesheet href="chrome://devtools/skin/widgets.css" type="text/css"?>
|
|
||||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
|
||||||
<script type="application/javascript" src="chrome://devtools/content/shared/theme-switching.js"/>
|
|
||||||
<box flex="1" class="devtools-responsive-container theme-body">
|
|
||||||
<vbox flex="1" class="devtools-main-content" id="content">test</vbox>
|
|
||||||
<splitter class="devtools-side-splitter"/>
|
|
||||||
<tabbox flex="1" id="sidebar" class="devtools-sidebar-tabs">
|
|
||||||
<tabs/>
|
|
||||||
<tabpanels flex="1"/>
|
|
||||||
</tabbox>
|
|
||||||
</box>
|
|
||||||
</window>
|
|
|
@ -1,7 +0,0 @@
|
||||||
<?xml version='1.0'?>
|
|
||||||
<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'>
|
|
||||||
<hbox flex='1'><description flex='1'>foo</description><splitter class='devtools-side-splitter'/>
|
|
||||||
<tabbox flex='1' id='sidebar' class='devtools-sidebar-tabs'><tabs/><tabpanels flex='1'/></tabbox>
|
|
||||||
</hbox>
|
|
||||||
</window>
|
|
||||||
|
|
|
@ -6,18 +6,6 @@
|
||||||
|
|
||||||
const EventEmitter = require("devtools/shared/event-emitter");
|
const EventEmitter = require("devtools/shared/event-emitter");
|
||||||
|
|
||||||
/**
|
|
||||||
* This object represents replacement for ToolSidebar
|
|
||||||
* implemented in devtools/client/framework/sidebar.js module
|
|
||||||
*
|
|
||||||
* This new component is part of devtools.html aimed at
|
|
||||||
* removing XUL and use HTML for entire DevTools UI.
|
|
||||||
* There are currently two implementation of the side bar since
|
|
||||||
* the `sidebar.js` module (mentioned above) is still used by
|
|
||||||
* other panels.
|
|
||||||
* As soon as all panels are using this HTML based
|
|
||||||
* implementation it can be removed.
|
|
||||||
*/
|
|
||||||
function ToolSidebar(tabbox, panel, uid, options = {}) {
|
function ToolSidebar(tabbox, panel, uid, options = {}) {
|
||||||
EventEmitter.decorate(this);
|
EventEmitter.decorate(this);
|
||||||
|
|
||||||
|
|
|
@ -45,11 +45,6 @@ toolbox.elementPicker.key=CmdOrCtrl+Shift+C
|
||||||
# Key shortcut used to toggle the element picker for macOS.
|
# Key shortcut used to toggle the element picker for macOS.
|
||||||
toolbox.elementPicker.mac.key=Cmd+Opt+C
|
toolbox.elementPicker.mac.key=Cmd+Opt+C
|
||||||
|
|
||||||
# LOCALIZATION NOTE (sidebar.showAllTabs.tooltip)
|
|
||||||
# This is the tooltip shown when hover over the '…' button in the tabbed side
|
|
||||||
# bar, when there's no enough space to show all tabs at once
|
|
||||||
sidebar.showAllTabs.tooltip=All tabs
|
|
||||||
|
|
||||||
# LOCALIZATION NOTE (toolbox.noContentProcessForTab.message)
|
# LOCALIZATION NOTE (toolbox.noContentProcessForTab.message)
|
||||||
# Used as a message in the alert displayed when trying to open a browser
|
# Used as a message in the alert displayed when trying to open a browser
|
||||||
# content toolbox and there is no content process running for the current tab
|
# content toolbox and there is no content process running for the current tab
|
||||||
|
|
Загрузка…
Ссылка в новой задаче