Bug 977043 - Add toolbox-level frame selection to change the currently targeted document. r=bgrins,past

This commit is contained in:
Alexandre Poirot 2014-08-27 12:19:30 +02:00
Родитель 8530aab086
Коммит 86679e0faf
13 изменённых файлов: 173 добавлений и 19 удалений

Просмотреть файл

@ -1302,6 +1302,7 @@ pref("devtools.toolbox.splitconsoleHeight", 100);
// Toolbox Button preferences
pref("devtools.command-button-pick.enabled", true);
pref("devtools.command-button-frames.enabled", false);
pref("devtools.command-button-splitconsole.enabled", true);
pref("devtools.command-button-paintflashing.enabled", false);
pref("devtools.command-button-tilt.enabled", false);

Просмотреть файл

@ -37,7 +37,9 @@ function test() {
// Check no toolbox buttons are shown
let buttons = addonDebugger.frame.contentDocument.getElementById("toolbox-buttons").children;
is(buttons.length, 0, "no toolbox buttons for the addon debugger");
Array.forEach(buttons, (btn, i) => {
is(btn.hidden, true, "no toolbox buttons for the addon debugger -- " + btn.className);
});
yield addonDebugger.destroy();
yield removeAddon(addon);

Просмотреть файл

@ -374,6 +374,7 @@ TabTarget.prototype = {
event.url = aPacket.url;
event.title = aPacket.title;
event.nativeConsoleAPI = aPacket.nativeConsoleAPI;
event.isFrameSwitching = aPacket.isFrameSwitching;
// Send any stored event payload (DOMWindow or nsIRequest) for backwards
// compatibility with non-remotable tools.
if (aPacket.state == "start") {
@ -387,6 +388,11 @@ TabTarget.prototype = {
}
};
this.client.addListener("tabNavigated", this._onTabNavigated);
this._onFrameUpdate = (aType, aPacket) => {
this.emit("frame-update", aPacket);
};
this.client.addListener("frameUpdate", this._onFrameUpdate);
},
/**
@ -396,6 +402,7 @@ TabTarget.prototype = {
this.client.removeListener("closed", this.destroy);
this.client.removeListener("tabNavigated", this._onTabNavigated);
this.client.removeListener("tabDetached", this._onTabDetached);
this.client.removeListener("frameUpdate", this._onFrameUpdate);
},
/**

Просмотреть файл

@ -57,12 +57,13 @@ function testSelectTool(aToolbox) {
function testPreferenceAndUIStateIsConsistent() {
let checkNodes = [...panelWin.document.querySelectorAll("#enabled-toolbox-buttons-box > checkbox")];
let toolboxButtonNodes = [...doc.querySelectorAll(".command-button")];
toolboxButtonNodes.push(doc.getElementById("command-button-frames"));
let toggleableTools = toolbox.toolboxButtons;
for (let tool of toggleableTools) {
let isVisible = getBoolPref(tool.visibilityswitch);
let button = toolboxButtonNodes.filter(button=>button.id === tool.id)[0];
let button = toolboxButtonNodes.filter(button => button.id === tool.id)[0];
is (!button.hasAttribute("hidden"), isVisible, "Button visibility matches pref for " + tool.id);
let check = checkNodes.filter(node=>node.id === tool.id)[0];

Просмотреть файл

@ -47,6 +47,26 @@ loader.lazyGetter(this, "toolboxStrings", () => {
loader.lazyGetter(this, "Selection", () => require("devtools/framework/selection").Selection);
loader.lazyGetter(this, "InspectorFront", () => require("devtools/server/actors/inspector").InspectorFront);
// White-list buttons that can be toggled to prevent adding prefs for
// addons that have manually inserted toolbarbuttons into DOM.
// (By default, supported target is only local tab)
const ToolboxButtons = [
{ id: "command-button-pick",
isTargetSupported: target => !target.isAddon },
{ id: "command-button-frames",
isTargetSupported: target => (
!target.isAddon && target.activeTab && target.activeTab.traits.frames
)
},
{ id: "command-button-splitconsole" },
{ id: "command-button-responsive" },
{ id: "command-button-paintflashing" },
{ id: "command-button-tilt" },
{ id: "command-button-scratchpad" },
{ id: "command-button-eyedropper" },
{ id: "command-button-screenshot" }
];
/**
* A "Toolbox" is the component that holds all the tools for one specific
* target. Visually, it's a document that includes the tools tabs and all
@ -69,6 +89,8 @@ function Toolbox(target, selectedTool, hostType, hostOptions) {
this._toolRegistered = this._toolRegistered.bind(this);
this._toolUnregistered = this._toolUnregistered.bind(this);
this._refreshHostTitle = this._refreshHostTitle.bind(this);
this.selectFrame = this.selectFrame.bind(this);
this._updateFrames = this._updateFrames.bind(this);
this._splitConsoleOnKeypress = this._splitConsoleOnKeypress.bind(this);
this.destroy = this.destroy.bind(this);
this.highlighterUtils = getHighlighterUtils(this);
@ -96,6 +118,8 @@ function Toolbox(target, selectedTool, hostType, hostOptions) {
EventEmitter.decorate(this);
this._target.on("navigate", this._refreshHostTitle);
this._target.on("frame-update", this._updateFrames);
this.on("host-changed", this._refreshHostTitle);
this.on("select", this._refreshHostTitle);
@ -243,11 +267,16 @@ Toolbox.prototype = {
let domReady = () => {
this.isReady = true;
this._listFrames();
this.closeButton = this.doc.getElementById("toolbox-close");
this.closeButton.addEventListener("command", this.destroy, true);
gDevTools.on("pref-changed", this._prefChanged);
let framesMenu = this.doc.getElementById("command-button-frames");
framesMenu.addEventListener("command", this.selectFrame, true);
this._buildDockButtons();
this._buildOptions();
this._buildTabs();
@ -591,6 +620,7 @@ Toolbox.prototype = {
}
if (!this.target.isLocalTab) {
this.setToolboxButtonsVisibility();
return Promise.resolve();
}
@ -616,6 +646,7 @@ Toolbox.prototype = {
this._pickerButton.id = "command-button-pick";
this._pickerButton.className = "command-button command-button-invertable";
this._pickerButton.setAttribute("tooltiptext", toolboxStrings("pickButton.tooltip"));
this._pickerButton.setAttribute("hidden", "true");
let container = this.doc.querySelector("#toolbox-picker-container");
container.appendChild(this._pickerButton);
@ -654,28 +685,19 @@ Toolbox.prototype = {
* added manually).
*/
get toolboxButtons() {
// White-list buttons that can be toggled to prevent adding prefs for
// addons that have manually inserted toolbarbuttons into DOM.
return [
"command-button-pick",
"command-button-splitconsole",
"command-button-responsive",
"command-button-paintflashing",
"command-button-tilt",
"command-button-scratchpad",
"command-button-eyedropper",
"command-button-screenshot"
].map(id => {
let button = this.doc.getElementById(id);
return ToolboxButtons.map(options => {
let button = this.doc.getElementById(options.id);
// Some buttons may not exist inside of Browser Toolbox
if (!button) {
return false;
}
return {
id: id,
id: options.id,
button: button,
label: button.getAttribute("tooltiptext"),
visibilityswitch: "devtools." + id + ".enabled"
visibilityswitch: "devtools." + options.id + ".enabled",
isTargetSupported: options.isTargetSupported ? options.isTargetSupported
: target => target.isLocalTab
}
}).filter(button=>button);
},
@ -686,12 +708,14 @@ Toolbox.prototype = {
*/
setToolboxButtonsVisibility: function() {
this.toolboxButtons.forEach(buttonSpec => {
let {visibilityswitch, id, button}=buttonSpec;
let { visibilityswitch, id, button, isTargetSupported } = buttonSpec;
let on = true;
try {
on = Services.prefs.getBoolPref(visibilityswitch);
} catch (ex) { }
on = on && isTargetSupported(this.target);
if (button) {
if (on) {
button.removeAttribute("hidden");
@ -1134,6 +1158,96 @@ Toolbox.prototype = {
this._host.setTitle(title);
},
_listFrames: function (event) {
if (!this._target.form || !this._target.form.actor) {
// We are not targetting a regular TabActor
// it can be either an addon or browser toolbox actor
return;
}
let packet = {
to: this._target.form.actor,
type: "listFrames"
};
this._target.client.request(packet, resp => {
this._updateFrames(null, { frames: resp.frames });
});
},
selectFrame: function (event) {
let windowId = event.target.getAttribute("data-window-id");
let packet = {
to: this._target.form.actor,
type: "switchToFrame",
windowId: windowId
};
this._target.client.request(packet);
// Wait for frameUpdate event to update the UI
},
_updateFrames: function (event, data) {
if (!Services.prefs.getBoolPref("devtools.command-button-frames.enabled")) {
return;
}
// We may receive this event before the toolbox is ready.
if (!this.isReady) {
return;
}
let menu = this.doc.getElementById("command-button-frames");
if (data.destroyAll) {
let menupopup = menu.firstChild;
while (menupopup.firstChild) {
menupopup.firstChild.remove();
}
return;
} else if (data.selected) {
let item = menu.querySelector("menuitem[data-window-id=\"" + data.selected + "\"]");
if (!item) {
return;
}
// Toggle the toolbarbutton if we selected a non top-level frame
if (item.hasAttribute("data-parent-id")) {
menu.setAttribute("checked", "true");
} else {
menu.removeAttribute("checked");
}
// Uncheck the previously selected frame
let selected = menu.querySelector("menuitem[checked=true]")
if (selected) {
selected.removeAttribute("checked");
}
// Check the new one
item.setAttribute("checked", "true");
} else if (data.frames) {
data.frames.forEach(win => {
let item = menu.querySelector("menuitem[data-window-id=\"" + win.id + "\"]");
if (win.destroy) {
if (item) {
item.remove();
}
return;
}
if (!item) {
item = this.doc.createElement("menuitem");
item.setAttribute("data-window-id", win.id);
if (win.parentID) {
item.setAttribute("data-parent-id", win.parentID);
}
// If we register a root docshell and we don't have any selected,
// consider it as the currently targeted one.
if (!win.parentID && !menu.querySelector("menuitem[checked=true]")) {
item.setAttribute("checked", "true");
menu.removeAttribute("checked");
}
menu.firstChild.appendChild(item);
}
item.setAttribute("label", win.url);
});
}
},
/**
* Create a host object based on the given host type.
*
@ -1355,6 +1469,7 @@ Toolbox.prototype = {
}
this._target.off("navigate", this._refreshHostTitle);
this._target.off("frame-update", this._updateFrames);
this.off("select", this._refreshHostTitle);
this.off("host-changed", this._refreshHostTitle);

Просмотреть файл

@ -69,7 +69,15 @@
<toolbar class="devtools-tabbar">
<hbox id="toolbox-picker-container" />
<hbox id="toolbox-tabs" flex="1" role="tablist" />
<hbox id="toolbox-buttons" pack="end"/>
<hbox id="toolbox-buttons" pack="end">
<toolbarbutton id="command-button-frames"
class="command-button command-button-invertable devtools-toolbarbutton"
tooltiptext="&toolboxFramesTooltip;"
type="menu"
hidden="true">
<menupopup position="bottomright topright"></menupopup>
</toolbarbutton>
</hbox>
<vbox id="toolbox-controls-separator" class="devtools-separator"/>
<hbox id="toolbox-option-container"/>
<hbox id="toolbox-controls">

Просмотреть файл

@ -18,6 +18,10 @@
<!ENTITY toolboxZoomReset.key "0">
<!ENTITY toolboxReload.key "r">
<!-- LOCALIZATION NOTE (toolboxFramesButton): This is the label for
- the iframes menu list that appears only when the document has some.
- It allows you to switch the context of the whole toolbox. -->
<!ENTITY toolboxFramesTooltip "Select an iframe as the currently targeted document">
<!-- LOCALIZATION NOTE (options.context.advancedSettings): This is the label for
- the heading of the advanced settings group in the options panel. -->

Просмотреть файл

@ -217,6 +217,8 @@ browser.jar:
skin/classic/browser/devtools/command-tilt@2x.png (../shared/devtools/images/command-tilt@2x.png)
skin/classic/browser/devtools/command-pick.png (../shared/devtools/images/command-pick.png)
skin/classic/browser/devtools/command-pick@2x.png (../shared/devtools/images/command-pick@2x.png)
skin/classic/browser/devtools/command-frames.png (../shared/devtools/images/command-frames.png)
skin/classic/browser/devtools/command-frames@2x.png (../shared/devtools/images/command-frames@2x.png)
skin/classic/browser/devtools/command-console.png (../shared/devtools/images/command-console.png)
skin/classic/browser/devtools/command-console@2x.png (../shared/devtools/images/command-console@2x.png)
skin/classic/browser/devtools/command-eyedropper.png (../shared/devtools/images/command-eyedropper.png)

Просмотреть файл

@ -340,6 +340,8 @@ browser.jar:
skin/classic/browser/devtools/command-tilt@2x.png (../shared/devtools/images/command-tilt@2x.png)
skin/classic/browser/devtools/command-pick.png (../shared/devtools/images/command-pick.png)
skin/classic/browser/devtools/command-pick@2x.png (../shared/devtools/images/command-pick@2x.png)
skin/classic/browser/devtools/command-frames.png (../shared/devtools/images/command-frames.png)
skin/classic/browser/devtools/command-frames@2x.png (../shared/devtools/images/command-frames@2x.png)
skin/classic/browser/devtools/command-console.png (../shared/devtools/images/command-console.png)
skin/classic/browser/devtools/command-console@2x.png (../shared/devtools/images/command-console@2x.png)
skin/classic/browser/devtools/command-eyedropper.png (../shared/devtools/images/command-eyedropper.png)

Двоичные данные
browser/themes/shared/devtools/images/command-frames.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 522 B

Двоичные данные
browser/themes/shared/devtools/images/command-frames@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 836 B

Просмотреть файл

@ -596,6 +596,10 @@
background-image: url("chrome://browser/skin/devtools/command-pick.png");
}
#command-button-frames > image {
background-image: url("chrome://browser/skin/devtools/command-frames.png");
}
#command-button-splitconsole > image {
background-image: url("chrome://browser/skin/devtools/command-console.png");
}
@ -629,6 +633,10 @@
background-image: url("chrome://browser/skin/devtools/command-pick@2x.png");
}
#command-button-frames > image {
background-image: url("chrome://browser/skin/devtools/command-frames@2x.png");
}
#command-button-splitconsole > image {
background-image: url("chrome://browser/skin/devtools/command-console@2x.png");
}

Просмотреть файл

@ -257,6 +257,8 @@ browser.jar:
skin/classic/browser/devtools/command-tilt@2x.png (../shared/devtools/images/command-tilt@2x.png)
skin/classic/browser/devtools/command-pick.png (../shared/devtools/images/command-pick.png)
skin/classic/browser/devtools/command-pick@2x.png (../shared/devtools/images/command-pick@2x.png)
skin/classic/browser/devtools/command-frames.png (../shared/devtools/images/command-frames.png)
skin/classic/browser/devtools/command-frames@2x.png (../shared/devtools/images/command-frames@2x.png)
skin/classic/browser/devtools/command-console.png (../shared/devtools/images/command-console.png)
skin/classic/browser/devtools/command-console@2x.png (../shared/devtools/images/command-console@2x.png)
skin/classic/browser/devtools/command-eyedropper.png (../shared/devtools/images/command-eyedropper.png)
@ -666,6 +668,8 @@ browser.jar:
skin/classic/aero/browser/devtools/command-tilt@2x.png (../shared/devtools/images/command-tilt@2x.png)
skin/classic/aero/browser/devtools/command-pick.png (../shared/devtools/images/command-pick.png)
skin/classic/aero/browser/devtools/command-pick@2x.png (../shared/devtools/images/command-pick@2x.png)
skin/classic/aero/browser/devtools/command-frames.png (../shared/devtools/images/command-frames.png)
skin/classic/aero/browser/devtools/command-frames@2x.png (../shared/devtools/images/command-frames@2x.png)
skin/classic/aero/browser/devtools/command-console.png (../shared/devtools/images/command-console.png)
skin/classic/aero/browser/devtools/command-console@2x.png (../shared/devtools/images/command-console@2x.png)
skin/classic/aero/browser/devtools/command-eyedropper.png (../shared/devtools/images/command-eyedropper.png)