forked from mirrors/gecko-dev
Bug 970321 - Australis' UITour: make menu panel not break if tour tab is opened in new window, r=Unfocused, a=sylvestre
This commit is contained in:
parent
d36b49734f
commit
1293252519
6 changed files with 155 additions and 6 deletions
|
|
@ -2492,6 +2492,15 @@
|
|||
if (this.tabs.length == 1)
|
||||
return null;
|
||||
|
||||
let event = new CustomEvent("TabBecomingWindow", {
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
aTab.dispatchEvent(event);
|
||||
if (event.defaultPrevented) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var options = "chrome,dialog=no,all";
|
||||
for (var name in aOptions)
|
||||
options += "," + name + "=" + aOptions[name];
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ const PanelUI = {
|
|||
};
|
||||
},
|
||||
|
||||
_initialized: false,
|
||||
init: function() {
|
||||
for (let [k, v] of Iterator(this.kElements)) {
|
||||
// Need to do fresh let-bindings per iteration
|
||||
|
|
@ -46,6 +47,7 @@ const PanelUI = {
|
|||
|
||||
this.menuButton.addEventListener("mousedown", this);
|
||||
this.menuButton.addEventListener("keypress", this);
|
||||
this._initialized = true;
|
||||
},
|
||||
|
||||
_eventListenersAdded: false,
|
||||
|
|
@ -201,6 +203,18 @@ const PanelUI = {
|
|||
return this._readyPromise;
|
||||
}
|
||||
this._readyPromise = Task.spawn(function() {
|
||||
if (!this._initialized) {
|
||||
let delayedStartupDeferred = Promise.defer();
|
||||
let delayedStartupObserver = (aSubject, aTopic, aData) => {
|
||||
if (aSubject == window) {
|
||||
Services.obs.removeObserver(delayedStartupObserver, "browser-delayed-startup-finished");
|
||||
delayedStartupDeferred.resolve();
|
||||
}
|
||||
};
|
||||
Services.obs.addObserver(delayedStartupObserver, "browser-delayed-startup-finished", false);
|
||||
yield delayedStartupDeferred.promise;
|
||||
}
|
||||
|
||||
this.contents.setAttributeNS("http://www.w3.org/XML/1998/namespace", "lang",
|
||||
getLocale());
|
||||
if (!this._scrollWidth) {
|
||||
|
|
|
|||
|
|
@ -42,11 +42,17 @@ this.UITour = {
|
|||
seenPageIDs: new Set(),
|
||||
pageIDSourceTabs: new WeakMap(),
|
||||
pageIDSourceWindows: new WeakMap(),
|
||||
/* Map from browser windows to a set of tabs in which a tour is open */
|
||||
originTabs: new WeakMap(),
|
||||
/* Map from browser windows to a set of pinned tabs opened by (a) tour(s) */
|
||||
pinnedTabs: new WeakMap(),
|
||||
urlbarCapture: new WeakMap(),
|
||||
appMenuOpenForAnnotation: new Set(),
|
||||
|
||||
_detachingTab: false,
|
||||
_queuedEvents: [],
|
||||
_pendingDoc: null,
|
||||
|
||||
highlightEffects: ["random", "wobble", "zoom", "color"],
|
||||
targets: new Map([
|
||||
["accountStatus", {
|
||||
|
|
@ -138,7 +144,20 @@ this.UITour = {
|
|||
return false;
|
||||
|
||||
let window = this.getChromeWindow(contentDocument);
|
||||
// Do this before bailing if there's no tab, so later we can pick up the pieces:
|
||||
window.gBrowser.tabContainer.addEventListener("TabSelect", this);
|
||||
let tab = window.gBrowser._getTabForContentWindow(contentDocument.defaultView);
|
||||
if (!tab) {
|
||||
// This should only happen while detaching a tab:
|
||||
if (this._detachingTab) {
|
||||
this._queuedEvents.push(aEvent);
|
||||
this._pendingDoc = Cu.getWeakReference(contentDocument);
|
||||
return;
|
||||
}
|
||||
Cu.reportError("Discarding tabless UITour event (" + action + ") while not detaching a tab." +
|
||||
"This shouldn't happen!");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case "registerPageID": {
|
||||
|
|
@ -299,10 +318,10 @@ this.UITour = {
|
|||
|
||||
if (!this.originTabs.has(window))
|
||||
this.originTabs.set(window, new Set());
|
||||
this.originTabs.get(window).add(tab);
|
||||
|
||||
this.originTabs.get(window).add(tab);
|
||||
tab.addEventListener("TabClose", this);
|
||||
window.gBrowser.tabContainer.addEventListener("TabSelect", this);
|
||||
tab.addEventListener("TabBecomingWindow", this);
|
||||
window.addEventListener("SSWindowClosing", this);
|
||||
|
||||
return true;
|
||||
|
|
@ -316,6 +335,9 @@ this.UITour = {
|
|||
break;
|
||||
}
|
||||
|
||||
case "TabBecomingWindow":
|
||||
this._detachingTab = true;
|
||||
// Fall through
|
||||
case "TabClose": {
|
||||
let tab = aEvent.target;
|
||||
if (this.pageIDSourceTabs.has(tab)) {
|
||||
|
|
@ -346,13 +368,34 @@ this.UITour = {
|
|||
}
|
||||
|
||||
let window = aEvent.target.ownerDocument.defaultView;
|
||||
let selectedTab = window.gBrowser.selectedTab;
|
||||
let pinnedTab = this.pinnedTabs.get(window);
|
||||
if (pinnedTab && pinnedTab.tab == window.gBrowser.selectedTab)
|
||||
if (pinnedTab && pinnedTab.tab == selectedTab)
|
||||
break;
|
||||
let originTabs = this.originTabs.get(window);
|
||||
if (originTabs && originTabs.has(window.gBrowser.selectedTab))
|
||||
if (originTabs && originTabs.has(selectedTab))
|
||||
break;
|
||||
|
||||
let pendingDoc;
|
||||
if (this._detachingTab && this._pendingDoc && (pendingDoc = this._pendingDoc.get())) {
|
||||
if (selectedTab.linkedBrowser.contentDocument == pendingDoc) {
|
||||
if (!this.originTabs.get(window)) {
|
||||
this.originTabs.set(window, new Set());
|
||||
}
|
||||
this.originTabs.get(window).add(selectedTab);
|
||||
this.pendingDoc = null;
|
||||
this._detachingTab = false;
|
||||
while (this._queuedEvents.length) {
|
||||
try {
|
||||
this.onPageEvent(this._queuedEvents.shift());
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.teardownTour(window);
|
||||
break;
|
||||
}
|
||||
|
|
@ -413,8 +456,10 @@ this.UITour = {
|
|||
|
||||
let originTabs = this.originTabs.get(aWindow);
|
||||
if (originTabs) {
|
||||
for (let tab of originTabs)
|
||||
for (let tab of originTabs) {
|
||||
tab.removeEventListener("TabClose", this);
|
||||
tab.removeEventListener("TabBecomingWindow", this);
|
||||
}
|
||||
}
|
||||
this.originTabs.delete(aWindow);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ skip-if = os == "linux" # Intermittent failures, bug 951965
|
|||
[browser_UITour2.js]
|
||||
[browser_UITour3.js]
|
||||
[browser_UITour_panel_close_annotation.js]
|
||||
[browser_UITour_detach_tab.js]
|
||||
[browser_UITour_registerPageID.js]
|
||||
[browser_UITour_sync.js]
|
||||
[browser_taskbar_preview.js]
|
||||
|
|
|
|||
80
browser/modules/test/browser_UITour_detach_tab.js
Normal file
80
browser/modules/test/browser_UITour_detach_tab.js
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that annotations disappear when their target is hidden.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
let gTestTab;
|
||||
let gContentAPI;
|
||||
let gContentWindow;
|
||||
let gContentDoc;
|
||||
let highlight = document.getElementById("UITourHighlight");
|
||||
let tooltip = document.getElementById("UITourTooltip");
|
||||
|
||||
Components.utils.import("resource:///modules/UITour.jsm");
|
||||
|
||||
function test() {
|
||||
registerCleanupFunction(function() {
|
||||
gContentDoc = null;
|
||||
});
|
||||
UITourTest();
|
||||
}
|
||||
|
||||
let tests = [
|
||||
function test_move_tab_to_new_window(done) {
|
||||
let gOpenedWindow;
|
||||
let onVisibilityChange = (aEvent) => {
|
||||
if (!document.hidden && window != UITour.getChromeWindow(aEvent.target)) {
|
||||
gContentAPI.showHighlight("appMenu");
|
||||
}
|
||||
};
|
||||
let onDOMWindowDestroyed = (aWindow, aTopic, aData) => {
|
||||
if (gOpenedWindow && aWindow == gOpenedWindow) {
|
||||
Services.obs.removeObserver(onDOMWindowDestroyed, "dom-window-destroyed", false);
|
||||
done();
|
||||
}
|
||||
};
|
||||
let onBrowserDelayedStartup = (aWindow, aTopic, aData) => {
|
||||
gOpenedWindow = aWindow;
|
||||
Services.obs.removeObserver(onBrowserDelayedStartup, "browser-delayed-startup-finished");
|
||||
try {
|
||||
let newWindowHighlight = gOpenedWindow.document.getElementById("UITourHighlight");
|
||||
let selectedTab = aWindow.gBrowser.selectedTab;
|
||||
is(selectedTab.linkedBrowser && selectedTab.linkedBrowser.contentDocument, gContentDoc, "Document should be selected in new window");
|
||||
ok(UITour.originTabs && UITour.originTabs.has(aWindow), "Window should be known");
|
||||
ok(UITour.originTabs.get(aWindow).has(selectedTab), "Tab should be known");
|
||||
waitForElementToBeVisible(newWindowHighlight, function checkHighlightIsThere() {
|
||||
gContentAPI.showMenu("appMenu");
|
||||
isnot(aWindow.PanelUI.panel.state, "closed", "Panel should be open");
|
||||
ok(aWindow.PanelUI.contents.children.length > 0, "Panel contents should have children");
|
||||
gContentAPI.hideHighlight();
|
||||
gContentAPI.hideMenu("appMenu");
|
||||
gTestTab = null;
|
||||
aWindow.close();
|
||||
}, "Highlight should be shown in new window.");
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
ok(false, "An error occurred running UITour tab detach test.");
|
||||
} finally {
|
||||
gContentDoc.removeEventListener("visibilitychange", onVisibilityChange, false);
|
||||
Services.obs.addObserver(onDOMWindowDestroyed, "dom-window-destroyed", false);
|
||||
}
|
||||
};
|
||||
|
||||
Services.obs.addObserver(onBrowserDelayedStartup, "browser-delayed-startup-finished", false);
|
||||
// NB: we're using this rather than gContentWindow.document because the latter wouldn't
|
||||
// have an XRayWrapper, and we need to compare this to the doc we get using this method
|
||||
// later on...
|
||||
gContentDoc = gBrowser.selectedTab.linkedBrowser.contentDocument;
|
||||
gContentDoc.addEventListener("visibilitychange", onVisibilityChange, false);
|
||||
gContentAPI.showHighlight("appMenu");
|
||||
waitForElementToBeVisible(highlight, function checkForInitialHighlight() {
|
||||
gBrowser.replaceTabWithWindow(gBrowser.selectedTab);
|
||||
});
|
||||
|
||||
},
|
||||
];
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ function is_element_hidden(element, msg) {
|
|||
}
|
||||
|
||||
function loadUITourTestPage(callback, host = "https://example.com/") {
|
||||
if (gTestTab)
|
||||
if (gTestTab)
|
||||
gBrowser.removeTab(gTestTab);
|
||||
|
||||
let url = getRootDirectory(gTestPath) + "uitour.html";
|
||||
|
|
|
|||
Loading…
Reference in a new issue