mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 20:35:50 +00:00
Bug 626455 - modal dialog in onbeforeunload: browser freeze after removing last tab group in panorama; r=dietrich
This commit is contained in:
parent
f40258527f
commit
60949f9a7a
46
browser/base/content/tabview/content.js
Normal file
46
browser/base/content/tabview/content.js
Normal file
@ -0,0 +1,46 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is content.js.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Tim Taubert <ttaubert@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
addEventListener("DOMWillOpenModalDialog", function (event) {
|
||||
// (event.isTrusted == true) when the event is generated by a user action
|
||||
// and does not originate from a script.
|
||||
if (event.isTrusted) {
|
||||
// we're intentionally sending a synchronous message to handle this event
|
||||
// as quick as possible, switch the selected tab and hide the tabview
|
||||
// before the modal dialog is shown
|
||||
sendSyncMessage("Panorama:DOMWillOpenModalDialog");
|
||||
}
|
||||
}, true);
|
@ -738,9 +738,13 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// ----------
|
||||
// Function: _unhide
|
||||
// Shows the hidden group.
|
||||
_unhide: function GroupItem__unhide() {
|
||||
let self = this;
|
||||
|
||||
//
|
||||
// Parameters:
|
||||
// options - various options (see below)
|
||||
//
|
||||
// Possible options:
|
||||
// immediately - true when no animations should be used
|
||||
_unhide: function GroupItem__unhide(options) {
|
||||
this._cancelFadeAwayUndoButtonTimer();
|
||||
this.hidden = false;
|
||||
this.$undoContainer.remove();
|
||||
@ -748,20 +752,31 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
this.droppable(true);
|
||||
this.setTrenches(this.bounds);
|
||||
|
||||
iQ(this.container).show().animate({
|
||||
"-moz-transform": "scale(1)",
|
||||
"opacity": 1
|
||||
}, {
|
||||
duration: 170,
|
||||
complete: function() {
|
||||
self._children.forEach(function(child) {
|
||||
iQ(child.container).show();
|
||||
});
|
||||
let self = this;
|
||||
|
||||
UI.setActive(self);
|
||||
self._sendToSubscribers("groupShown", { groupItemId: self.id });
|
||||
}
|
||||
});
|
||||
let finalize = function () {
|
||||
self._children.forEach(function(child) {
|
||||
iQ(child.container).show();
|
||||
});
|
||||
|
||||
UI.setActive(self);
|
||||
self._sendToSubscribers("groupShown", { groupItemId: self.id });
|
||||
};
|
||||
|
||||
let $container = iQ(this.container).show();
|
||||
|
||||
if (!options || !options.immediately) {
|
||||
$container.animate({
|
||||
"-moz-transform": "scale(1)",
|
||||
"opacity": 1
|
||||
}, {
|
||||
duration: 170,
|
||||
complete: finalize
|
||||
});
|
||||
} else {
|
||||
$container.css({"-moz-transform": "none", opacity: 1});
|
||||
finalize();
|
||||
}
|
||||
|
||||
GroupItems.updateGroupCloseButtons();
|
||||
},
|
||||
@ -779,15 +794,29 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
let remainingGroups = GroupItems.groupItems.filter(function (groupItem) {
|
||||
return (groupItem != self && groupItem.getChildren().length);
|
||||
});
|
||||
|
||||
let tab = null;
|
||||
|
||||
if (!gBrowser._numPinnedTabs && !remainingGroups.length) {
|
||||
let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
|
||||
return (groupItem != self && !groupItem.getChildren().length);
|
||||
});
|
||||
let group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
|
||||
group.newTab(null, { closedLastTab: true });
|
||||
tab = group.newTab(null, {dontZoomIn: true});
|
||||
}
|
||||
|
||||
this.destroy();
|
||||
let closed = this.destroy();
|
||||
|
||||
if (!tab)
|
||||
return;
|
||||
|
||||
if (closed) {
|
||||
// Let's make the new tab the selected tab.
|
||||
UI.goToTab(tab);
|
||||
} else {
|
||||
// Remove the new tab and group, if this group is no longer closed.
|
||||
tab._tabViewTabItem.parent.destroy({immediately: true});
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -800,6 +829,10 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
//
|
||||
// Options:
|
||||
// immediately - (bool) if true, no animation will be used
|
||||
//
|
||||
// Returns true if the groupItem has been closed, or false otherwise. A group
|
||||
// could not have been closed due to a tab with an onUnload handler (that
|
||||
// waits for user interaction).
|
||||
destroy: function GroupItem_destroy(options) {
|
||||
let self = this;
|
||||
|
||||
@ -808,14 +841,11 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// In other words, the group "close" event is fired before all browser
|
||||
// tabs in the group are closed. The below code would fire the group "close"
|
||||
// event only after all browser tabs in that group are closed.
|
||||
let shouldRemoveTabItems = [];
|
||||
let toClose = this._children.concat();
|
||||
toClose.forEach(function(child) {
|
||||
this._children.concat().forEach(function(child) {
|
||||
child.removeSubscriber("close", self._onChildClose);
|
||||
|
||||
let removed = child.close(true);
|
||||
if (removed) {
|
||||
shouldRemoveTabItems.push(child);
|
||||
if (child.close(true)) {
|
||||
self.remove(child, { dontArrange: true });
|
||||
} else {
|
||||
// child.removeSubscriber() must be called before child.close(),
|
||||
// therefore we call child.addSubscriber() if the tab is not removed.
|
||||
@ -823,15 +853,14 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
}
|
||||
});
|
||||
|
||||
if (shouldRemoveTabItems.length != toClose.length) {
|
||||
// remove children without the assiciated tab and show the group item
|
||||
shouldRemoveTabItems.forEach(function(child) {
|
||||
self.remove(child, { dontArrange: true });
|
||||
});
|
||||
if (this._children.length) {
|
||||
if (this.hidden)
|
||||
this.$undoContainer.fadeOut(function() { self._unhide() });
|
||||
|
||||
this.$undoContainer.fadeOut(function() { self._unhide() });
|
||||
return false;
|
||||
} else {
|
||||
this.close(options);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
@ -1809,13 +1838,16 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// Parameters:
|
||||
// url - the new tab should open this url as well
|
||||
// options - the options object
|
||||
// dontZoomIn - set to true to not zoom into the newly created tab
|
||||
// closedLastTab - boolean indicates the last tab has just been closed
|
||||
newTab: function GroupItem_newTab(url, options) {
|
||||
if (options && options.closedLastTab)
|
||||
UI.closedLastTabInTabView = true;
|
||||
|
||||
UI.setActive(this, { dontSetActiveTabInGroup: true });
|
||||
gBrowser.loadOneTab(url || "about:blank", { inBackground: false });
|
||||
|
||||
let dontZoomIn = !!(options && options.dontZoomIn);
|
||||
return gBrowser.loadOneTab(url || "about:blank", { inBackground: dontZoomIn });
|
||||
},
|
||||
|
||||
// ----------
|
||||
|
@ -482,29 +482,22 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// closing tab doesn't belong to a group and no empty group, create a new
|
||||
// one for the new tab.
|
||||
if (!groupClose && gBrowser.tabs.length == 1) {
|
||||
let group;
|
||||
if (this.tab._tabViewTabItem.parent) {
|
||||
group = this.tab._tabViewTabItem.parent;
|
||||
} else {
|
||||
let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
|
||||
return (!groupItem.getChildren().length);
|
||||
});
|
||||
group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
|
||||
}
|
||||
let group = this.tab._tabViewTabItem.parent;
|
||||
group.newTab(null, { closedLastTab: true });
|
||||
}
|
||||
|
||||
// when "TabClose" event is fired, the browser tab is about to close and our
|
||||
// item "close" is fired before the browser tab actually get closed.
|
||||
// Therefore, we need "tabRemoved" event below.
|
||||
gBrowser.removeTab(this.tab);
|
||||
let tabNotClosed =
|
||||
Array.some(gBrowser.tabs, function(tab) { return tab == this.tab; }, this);
|
||||
if (!tabNotClosed)
|
||||
let tabClosed = !this.tab;
|
||||
|
||||
if (tabClosed)
|
||||
this._sendToSubscribers("tabRemoved");
|
||||
|
||||
// No need to explicitly delete the tab data, becasue sessionstore data
|
||||
// associated with the tab will automatically go away
|
||||
return !tabNotClosed;
|
||||
return tabClosed;
|
||||
},
|
||||
|
||||
// ----------
|
||||
|
@ -26,6 +26,7 @@
|
||||
* Raymond Lee <raymond@appcoast.com>
|
||||
* Sean Dunn <seanedunn@yahoo.com>
|
||||
* Tim Taubert <tim.taubert@gmx.de>
|
||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -80,6 +81,10 @@ let UI = {
|
||||
// If true, a closed tab has just been restored.
|
||||
restoredClosedTab: false,
|
||||
|
||||
// Variable: _isChangingVisibility
|
||||
// Tracks whether we're currently in the process of showing/hiding the tabview.
|
||||
_isChangingVisibility: false,
|
||||
|
||||
// Variable: _reorderTabItemsOnShow
|
||||
// Keeps track of the <GroupItem>s which their tab items' tabs have been moved
|
||||
// and re-orders the tab items when switching to TabView.
|
||||
@ -230,6 +235,15 @@ let UI = {
|
||||
self.uninit();
|
||||
});
|
||||
|
||||
// ___ setup DOMWillOpenModalDialog message handler
|
||||
let mm = gWindow.messageManager;
|
||||
let callback = this._onDOMWillOpenModalDialog.bind(this);
|
||||
mm.addMessageListener("Panorama:DOMWillOpenModalDialog", callback);
|
||||
|
||||
this._cleanupFunctions.push(function () {
|
||||
mm.removeMessageListener("Panorama:DOMWillOpenModalDialog", callback);
|
||||
});
|
||||
|
||||
// ___ setup key handlers
|
||||
this._setTabViewFrameKeyHandlers();
|
||||
|
||||
@ -272,6 +286,10 @@ let UI = {
|
||||
self._save();
|
||||
}, false);
|
||||
|
||||
// ___ load frame script
|
||||
let frameScript = "chrome://browser/content/tabview-content.js";
|
||||
gWindow.messageManager.loadFrameScript(frameScript, true);
|
||||
|
||||
// ___ Done
|
||||
this._frameInitialized = true;
|
||||
this._save();
|
||||
@ -476,9 +494,11 @@ let UI = {
|
||||
// Parameters:
|
||||
// zoomOut - true for zoom out animation, false for nothing.
|
||||
showTabView: function UI_showTabView(zoomOut) {
|
||||
if (this.isTabViewVisible())
|
||||
if (this.isTabViewVisible() || this._isChangingVisibility)
|
||||
return;
|
||||
|
||||
this._isChangingVisibility = true;
|
||||
|
||||
// initialize the direction of the page
|
||||
this._initPageDirection();
|
||||
|
||||
@ -521,6 +541,7 @@ let UI = {
|
||||
self.setActive(item);
|
||||
|
||||
self._resize(true);
|
||||
self._isChangingVisibility = false;
|
||||
dispatchEvent(event);
|
||||
|
||||
// Flush pending updates
|
||||
@ -530,6 +551,7 @@ let UI = {
|
||||
});
|
||||
} else {
|
||||
self.clearActiveTab();
|
||||
self._isChangingVisibility = false;
|
||||
dispatchEvent(event);
|
||||
|
||||
// Flush pending updates
|
||||
@ -546,9 +568,11 @@ let UI = {
|
||||
// Function: hideTabView
|
||||
// Hides TabView and shows the main browser UI.
|
||||
hideTabView: function UI_hideTabView() {
|
||||
if (!this.isTabViewVisible())
|
||||
if (!this.isTabViewVisible() || this._isChangingVisibility)
|
||||
return;
|
||||
|
||||
this._isChangingVisibility = true;
|
||||
|
||||
// another tab might be select if user decides to stay on a page when
|
||||
// a onclose confirmation prompts.
|
||||
GroupItems.removeHiddenGroups();
|
||||
@ -575,6 +599,8 @@ let UI = {
|
||||
#endif
|
||||
Storage.saveVisibilityData(gWindow, "false");
|
||||
|
||||
this._isChangingVisibility = false;
|
||||
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("tabviewhidden", true, false);
|
||||
dispatchEvent(event);
|
||||
@ -748,21 +774,14 @@ let UI = {
|
||||
groupItem._children.length == 1 &&
|
||||
groupItem._children[0].tab == tab);
|
||||
|
||||
// 2) Take care of the case where you've closed the last tab in
|
||||
// an un-named groupItem, which means that the groupItem is gone (null) and
|
||||
// there are no visible tabs.
|
||||
let closingUnnamedGroup = (groupItem == null &&
|
||||
gBrowser.visibleTabs.length <= 1);
|
||||
|
||||
// 3) When a blank tab is active while restoring a closed tab the
|
||||
// 2) When a blank tab is active while restoring a closed tab the
|
||||
// blank tab gets removed. The active group is not closed as this is
|
||||
// where the restored tab goes. So do not show the TabView.
|
||||
let tabItem = tab && tab._tabViewTabItem;
|
||||
let closingBlankTabAfterRestore =
|
||||
(tabItem && tabItem.isRemovedAfterRestore);
|
||||
|
||||
if ((closingLastOfGroup || closingUnnamedGroup) &&
|
||||
!closingBlankTabAfterRestore) {
|
||||
if (closingLastOfGroup && !closingBlankTabAfterRestore) {
|
||||
// for the tab focus event to pick up.
|
||||
self._closedLastVisibleTab = true;
|
||||
self.showTabView();
|
||||
@ -882,8 +901,14 @@ let UI = {
|
||||
|
||||
// if TabView is visible but we didn't just close the last tab or
|
||||
// selected tab, show chrome.
|
||||
if (this.isTabViewVisible())
|
||||
if (this.isTabViewVisible()) {
|
||||
// Unhide the group of the tab the user is activating.
|
||||
if (tab && tab._tabViewTabItem && tab._tabViewTabItem.parent &&
|
||||
tab._tabViewTabItem.parent.hidden)
|
||||
tab._tabViewTabItem.parent._unhide({immediately: true});
|
||||
|
||||
this.hideTabView();
|
||||
}
|
||||
|
||||
// another tab might be selected when hideTabView() is invoked so a
|
||||
// validation is needed.
|
||||
@ -917,6 +942,27 @@ let UI = {
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: _onDOMWillOpenModalDialog
|
||||
// Called when a web page is about to show a modal dialog.
|
||||
_onDOMWillOpenModalDialog: function UI__onDOMWillOpenModalDialog(cx) {
|
||||
if (!this.isTabViewVisible())
|
||||
return;
|
||||
|
||||
let index = gBrowser.browsers.indexOf(cx.target);
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
let tab = gBrowser.tabs[index];
|
||||
|
||||
// When TabView is visible, we need to call onTabSelect to make sure that
|
||||
// TabView is hidden and that the correct group is activated. When a modal
|
||||
// dialog is shown for currently selected tab the onTabSelect event handler
|
||||
// is not called, so we need to do it.
|
||||
if (gBrowser.selectedTab == tab && this._currentTab == tab)
|
||||
this.onTabSelect(tab);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: setReorderTabsOnHide
|
||||
// Sets the groupItem which the tab items' tabs should be re-ordered when
|
||||
|
@ -111,6 +111,7 @@ _BROWSER_FILES = \
|
||||
browser_tabview_bug625269.js \
|
||||
browser_tabview_bug625424.js \
|
||||
browser_tabview_bug626368.js \
|
||||
browser_tabview_bug626455.js \
|
||||
browser_tabview_bug626525.js \
|
||||
browser_tabview_bug626791.js \
|
||||
browser_tabview_bug627239.js \
|
||||
|
@ -10,7 +10,7 @@ function test() {
|
||||
function part1(win) {
|
||||
registerCleanupFunction(function() win.close());
|
||||
|
||||
let contentWindow = win.document.getElementById("tab-view").contentWindow;
|
||||
let contentWindow = win.TabView.getContentWindow();
|
||||
is(contentWindow.GroupItems.groupItems.length, 1, "Has only one group");
|
||||
|
||||
let originalTab = win.gBrowser.selectedTab;
|
||||
@ -71,15 +71,12 @@ function part2(win) {
|
||||
// switch the selected tab to new tab
|
||||
win.gBrowser.selectedTab = newTab;
|
||||
|
||||
whenTabViewIsHidden(function () {
|
||||
is(win.gBrowser.selectedTab, newTab, "The seleted tab should be the same as before (new tab)");
|
||||
win.close();
|
||||
finish();
|
||||
});
|
||||
|
||||
// show tabview
|
||||
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, win);
|
||||
// hide tabview
|
||||
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, win);
|
||||
})
|
||||
showTabView(function () {
|
||||
hideTabView(function () {
|
||||
is(win.gBrowser.selectedTab, newTab,
|
||||
"The selected tab should be the same as before (new tab)");
|
||||
waitForFocus(finish);
|
||||
}, win);
|
||||
}, win);
|
||||
}, win);
|
||||
}
|
||||
|
@ -21,9 +21,7 @@ function onTabViewShown() {
|
||||
|
||||
function testStayOnPage(contentWindow, groupItemOne, groupItemTwo) {
|
||||
whenDialogOpened(function (dialog) {
|
||||
groupItemTwo.addSubscriber("groupShown", function onShown() {
|
||||
groupItemTwo.removeSubscriber("groupShown", onShown);
|
||||
|
||||
executeSoon(function () {
|
||||
is(gBrowser.tabs.length, 2,
|
||||
"The total number of tab is 2 when staying on the page");
|
||||
is(contentWindow.TabItems.getItems().length, 2,
|
||||
|
@ -25,6 +25,7 @@ function test1() {
|
||||
is(groupItems.length, 1, "there is one groupItem");
|
||||
|
||||
whenTabViewIsHidden(function() {
|
||||
gBrowser.selectedTab = gBrowser.tabs[0];
|
||||
is(groupItems.length, 2, "there are two groupItems");
|
||||
closeGroupItem(groupItems[1], finish);
|
||||
});
|
||||
|
@ -18,6 +18,6 @@ function test() {
|
||||
cw.GroupItems.resumeArrange();
|
||||
ok(groupItem.isStacked(), 'groupItem is now stacked');
|
||||
|
||||
closeGroupItem(groupItem, finish);
|
||||
closeGroupItem(groupItem, function () hideTabView(finish));
|
||||
});
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ function test() {
|
||||
ok(!document.getElementById("context_openTabInWindow").disabled, "The 'Move to New Window' menu item is enabled");
|
||||
|
||||
let newTabTwo = gBrowser.selectedTab;
|
||||
gBrowser.selected = originalTab;
|
||||
gBrowser.selectedTab = originalTab;
|
||||
|
||||
gBrowser.removeTab(newTabOne);
|
||||
gBrowser.removeTab(newTabTwo);
|
||||
|
127
browser/base/content/test/tabview/browser_tabview_bug626455.js
Normal file
127
browser/base/content/test/tabview/browser_tabview_bug626455.js
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||
* Raymond Lee <raymond@appcoast.com>
|
||||
*/
|
||||
|
||||
const TEST_URL = 'data:text/html,<script>window.onbeforeunload=' +
|
||||
'function(e){e.returnValue="?"}</script><body ' +
|
||||
'onunload="alert(\'onunload\')" onpagehide="' +
|
||||
'alert(\'onpagehide\')"></body>';
|
||||
|
||||
let contentWindow;
|
||||
let activeGroup;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
showTabView(function () {
|
||||
contentWindow = TabView.getContentWindow();
|
||||
activeGroup = contentWindow.GroupItems.getActiveGroupItem();
|
||||
|
||||
gBrowser.browsers[0].contentWindow.location =
|
||||
"data:text/html,<p>test for bug 626455, tab1";
|
||||
gBrowser.addTab(TEST_URL);
|
||||
|
||||
afterAllTabsLoaded(testStayOnPage);
|
||||
});
|
||||
}
|
||||
|
||||
function testStayOnPage() {
|
||||
whenDialogOpened(function (dialog) {
|
||||
// stay on page
|
||||
dialog.cancelDialog();
|
||||
|
||||
executeSoon(function () {
|
||||
showTabView(function () {
|
||||
is(gBrowser.tabs.length, 1,
|
||||
"The total number of tab is 1 when staying on the page");
|
||||
|
||||
let location = gBrowser.browsers[0].contentWindow.location.toString();
|
||||
isnot(location.indexOf("onbeforeunload"), -1,
|
||||
"The open tab is the expected one");
|
||||
|
||||
is(contentWindow.GroupItems.getActiveGroupItem(), activeGroup,
|
||||
"Active group is still the same");
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"Only one group is open");
|
||||
|
||||
// start the next test
|
||||
testLeavePage();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
closeGroupItem(activeGroup);
|
||||
}
|
||||
|
||||
function testLeavePage() {
|
||||
let dialogsAccepted = 0;
|
||||
|
||||
whenDialogOpened(function onDialogOpened(dialog) {
|
||||
if (++dialogsAccepted < 3)
|
||||
whenDialogOpened(onDialogOpened);
|
||||
|
||||
// Leave page
|
||||
dialog.acceptDialog();
|
||||
});
|
||||
|
||||
whenGroupClosed(activeGroup, finishTest);
|
||||
closeGroupItem(activeGroup);
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
is(gBrowser.tabs.length, 1,
|
||||
"The total number of tab is 1 after leaving the page");
|
||||
is(contentWindow.TabItems.getItems().length, 1,
|
||||
"The total number of tab items is 1 after leaving the page");
|
||||
|
||||
let location = gBrowser.browsers[0].contentWindow.location.toString();
|
||||
is(location, "about:blank", "The open tab is the expected one");
|
||||
|
||||
isnot(contentWindow.GroupItems.getActiveGroupItem(), activeGroup,
|
||||
"Active group is no longer the same");
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"Only one group is open");
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
// ----------
|
||||
function whenGroupClosed(group, callback) {
|
||||
group.addSubscriber("close", function onClose() {
|
||||
group.removeSubscriber("close", onClose);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
// ----------
|
||||
function whenDialogOpened(callback) {
|
||||
let wm = Cc["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Ci.nsIWindowMediator);
|
||||
|
||||
let listener = {
|
||||
onCloseWindow: function () {},
|
||||
onWindowTitleChange: function () {},
|
||||
|
||||
onOpenWindow: function (xulWin) {
|
||||
let domWin = xulWin.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow);
|
||||
|
||||
whenWindowLoaded(domWin, function () {
|
||||
let dialog = domWin.document.querySelector("dialog");
|
||||
if (dialog) {
|
||||
wm.removeListener(listener);
|
||||
callback(dialog);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
wm.addListener(listener);
|
||||
}
|
@ -67,7 +67,7 @@ function test() {
|
||||
EventUtils.synthesizeMouse(target, 600, 5, {type: "mouseup"}, cw);
|
||||
|
||||
checkNumberOfGroupItems(2);
|
||||
next();
|
||||
closeGroupItem(cw.GroupItems.groupItems[1], next);
|
||||
}, win);
|
||||
}
|
||||
|
||||
|
@ -3,49 +3,32 @@
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
TabView.toggle();
|
||||
showTabView(onTabViewShown);
|
||||
}
|
||||
|
||||
function onTabViewWindowLoaded() {
|
||||
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
|
||||
function onTabViewShown() {
|
||||
ok(TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
||||
let contentWindow = TabView.getContentWindow();
|
||||
let [originalTab] = gBrowser.visibleTabs;
|
||||
|
||||
let createGroupItem = function (left, top, width, height) {
|
||||
let box = new contentWindow.Rect(left, top, width, height);
|
||||
let groupItem = new contentWindow.GroupItem([], {bounds: box, immediately: true});
|
||||
|
||||
contentWindow.UI.setActive(groupItem);
|
||||
gBrowser.loadOneTab("about:blank", {inBackground: true});
|
||||
|
||||
return groupItem;
|
||||
};
|
||||
|
||||
// create group one and two
|
||||
let boxOne = new contentWindow.Rect(20, 20, 300, 300);
|
||||
let groupOne = new contentWindow.GroupItem([], { bounds: boxOne });
|
||||
ok(groupOne.isEmpty(), "This group is empty");
|
||||
let groupOne = createGroupItem(20, 20, 300, 300);
|
||||
let groupTwo = createGroupItem(20, 400, 300, 300);
|
||||
|
||||
let boxTwo = new contentWindow.Rect(20, 400, 300, 300);
|
||||
let groupTwo = new contentWindow.GroupItem([], { bounds: boxTwo });
|
||||
|
||||
groupOne.addSubscriber("childAdded", function onChildAdded() {
|
||||
groupOne.removeSubscriber("childAdded", onChildAdded);
|
||||
groupTwo.newTab();
|
||||
waitForFocus(function () {
|
||||
addTest(contentWindow, groupOne.id, groupTwo.id, originalTab);
|
||||
});
|
||||
|
||||
let count = 0;
|
||||
let onTabViewShown = function() {
|
||||
if (count == 2) {
|
||||
window.removeEventListener("tabviewshown", onTabViewShown, false);
|
||||
addTest(contentWindow, groupOne.id, groupTwo.id, originalTab);
|
||||
}
|
||||
};
|
||||
let onTabViewHidden = function() {
|
||||
TabView.toggle();
|
||||
if (++count == 2)
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
};
|
||||
window.addEventListener("tabviewshown", onTabViewShown, false);
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
||||
// open tab in group
|
||||
groupOne.newTab();
|
||||
}
|
||||
|
||||
function addTest(contentWindow, groupOneId, groupTwoId, originalTab) {
|
||||
@ -74,24 +57,13 @@ function addTest(contentWindow, groupOneId, groupTwoId, originalTab) {
|
||||
"The number of children in group one is decreased by 1");
|
||||
is(groupTwo.getChildren().length, ++groupTwoTabItemCount,
|
||||
"The number of children in group two is increased by 1");
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
groupTwo.closeAll();
|
||||
// close undo group
|
||||
let closeButton = groupTwo.$undoContainer.find(".close");
|
||||
EventUtils.sendMouseEvent(
|
||||
{ type: "click" }, closeButton[0], contentWindow);
|
||||
};
|
||||
groupTwo.addSubscriber("close", function onClose() {
|
||||
groupTwo.removeSubscriber("close", onClose);
|
||||
finish();
|
||||
|
||||
closeGroupItem(groupOne, function () {
|
||||
closeGroupItem(groupTwo, function () hideTabView(finish));
|
||||
});
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
gBrowser.selectedTab = originalTab;
|
||||
}
|
||||
|
||||
groupTwo.addSubscriber("childAdded", endGame);
|
||||
|
||||
simulateDragDrop(tabItem.container, offsetX, offsetY, contentWindow);
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,18 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let timerId;
|
||||
let newWin;
|
||||
|
||||
// ----------
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// launch tab view for the first time
|
||||
newWindowWithTabView(function() {}, function(win) {
|
||||
let panelSelected = false;
|
||||
registerCleanupFunction(function () ok(panelSelected, "panel is selected"));
|
||||
|
||||
let onLoad = function (win) {
|
||||
registerCleanupFunction(function () win.close());
|
||||
|
||||
newWin = win;
|
||||
|
||||
let onSelect = function(event) {
|
||||
@ -21,27 +24,26 @@ function test() {
|
||||
return;
|
||||
|
||||
deck.removeEventListener("select", onSelect, true);
|
||||
|
||||
whenTabViewIsShown(function() {
|
||||
executeSoon(function() {
|
||||
testMethodToHideAndShowTabView(function() {
|
||||
newWin.document.getElementById("menu_tabview").doCommand();
|
||||
}, function() {
|
||||
testMethodToHideAndShowTabView(function() {
|
||||
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, newWin);
|
||||
}, finish);
|
||||
});
|
||||
});
|
||||
}, win);
|
||||
panelSelected = true;
|
||||
};
|
||||
|
||||
let deck = win.document.getElementById("tab-view-deck");
|
||||
deck.addEventListener("select", onSelect, true);
|
||||
});
|
||||
};
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
newWin.close();
|
||||
});
|
||||
let onShow = function (win) {
|
||||
executeSoon(function() {
|
||||
testMethodToHideAndShowTabView(function() {
|
||||
newWin.document.getElementById("menu_tabview").doCommand();
|
||||
}, function() {
|
||||
testMethodToHideAndShowTabView(function() {
|
||||
EventUtils.synthesizeKey("E", { accelKey: true, shiftKey: true }, newWin);
|
||||
}, finish);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
newWindowWithTabView(onShow, onLoad);
|
||||
}
|
||||
|
||||
function testMethodToHideAndShowTabView(executeFunc, callback) {
|
||||
|
@ -55,6 +55,7 @@ browser.jar:
|
||||
content/browser/tabview.css (content/tabview/tabview.css)
|
||||
* content/browser/tabview.js (content/tabview/tabview.js)
|
||||
content/browser/tabview.html (content/tabview/tabview.html)
|
||||
content/browser/tabview-content.js (content/tabview/content.js)
|
||||
* content/browser/urlbarBindings.xml (content/urlbarBindings.xml)
|
||||
* content/browser/utilityOverlay.js (content/utilityOverlay.js)
|
||||
* content/browser/web-panels.js (content/web-panels.js)
|
||||
|
Loading…
Reference in New Issue
Block a user