Closed
Bug 599626
Opened 14 years ago
Closed 14 years ago
After perform close group in Panorama, the browser becomes unresponsive
Categories
(Firefox Graveyard :: Panorama, defect, P1)
Firefox Graveyard
Panorama
Tracking
(blocking2.0 betaN+)
RESOLVED
FIXED
Firefox 4.0
Tracking | Status | |
---|---|---|
blocking2.0 | --- | betaN+ |
People
(Reporter: alice0775, Assigned: raymondlee)
References
Details
(Keywords: dataloss, hang)
Attachments
(2 files, 7 obsolete files)
160 bytes,
text/html
|
Details | |
26.49 KB,
patch
|
Details | Diff | Splinter Review |
Build Identifier: http://hg.mozilla.org/mozilla-central/rev/71e8b5aee972
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b7pre) Gecko/20100925
Firefox/4.0b7pre ID:20100925041313
If there are tab which is include onbeforeunload(such as Google Document),
After perform close group in Panorama,
The browser does not response.
Reproducible: Always
Steps to Reproduce:
1. Start Minefield with new profile
2. Open Testcase
3. Open adequate number of web pages in new tabs.
4. Go Panorama
5. Divide tabs into two groups
6. Close a group which include the testcase
7. Choose a remaining group
8. When popup confirmation prompts, you chose "Stay on Page"
9. Close tab and you chose "Leave on Page"
Actual Results:
Browser hangs.
And the chosen group will be lost.
Expected Results:
Browser should not hang.
the chosen group should be there.
Reporter | ||
Comment 1•14 years ago
|
||
Reporter | ||
Comment 2•14 years ago
|
||
Error console at Step 9:
Error: browser.webProgress is undefined
Source file: chrome://browser/content/tabbrowser.xml
Line: 1465
// Remove the tab's filter and progress listener.
const filter = this.mTabFilters[aTab._tPos];
>> browser.webProgress.removeProgressListener(filter);
filter.removeProgressListener(this.mTabListeners[aTab._tPos]);
this.mTabListeners[aTab._tPos].destroy();
A script on this page may be busy, or it may have stopped responding. You can stop the script now, or you can continue to see if the script will complete.
Script: chrome://browser/content/tabbrowser.xml:1495
<method name="_endRemoveTab">
<parameter name="aTab"/>
<body>
<![CDATA[
if (!aTab || !aTab._endRemoveArgs)
>> return;
var [aCloseWindow, aNewTab] = aTab._endRemoveArgs;
Updated•14 years ago
|
Assignee | ||
Updated•14 years ago
|
Status: NEW → ASSIGNED
Assignee | ||
Updated•14 years ago
|
OS: Windows 7 → All
Hardware: x86 → All
Assignee | ||
Comment 3•14 years ago
|
||
This patch breaks some tests and is missing a test as well
Assignee | ||
Updated•14 years ago
|
Summary: After perform close group in Panorama,The browser does not response, → After perform close group in Panorama, the browser becomes unresponsive
Assignee | ||
Comment 4•14 years ago
|
||
Attachment #480946 -
Attachment is obsolete: true
Attachment #481297 -
Flags: feedback?(ian)
Assignee | ||
Updated•14 years ago
|
Assignee | ||
Comment 5•14 years ago
|
||
(In reply to comment #4)
> Created attachment 481297 [details] [diff] [review]
> v1
Passed Try
Comment 6•14 years ago
|
||
Comment on attachment 481297 [details] [diff] [review]
v1
+ // Function: _showHiddenGroup
+ // Shows the hidden group.
I find this name a little confusing, like this group has a hidden group, rather than that this group is hidden. Maybe a better name would be just _unhide()?
+ // Function: removeHiddenGroup
This name is similarly confusing. How about closeHidden()?
I think this routine is more complicated than it needs to be. Rather than doing the removeSubscriber/shouldRemoveTabItems thing, just close all the tabs and then check to see if the group has automatically closed itself. If it hasn't, check to see if it still has tabs in it. If it does, unhide it, otherwise close it.
You may need to modify GroupItem.close so it does the right thing in the hidden state, but that's better than having what's essentially a copy of it in this routine.
+ GroupItems.removeHiddenGroups();
Why did you move this out of hideTabView? Seemed like a better spot for it.
removeHiddenGroups: function GroupItems_removeHiddenGroups() {
- iQ(".undo").remove();
-
// ToDo: encapsulate this in the group item. bug 594863
Looks like you've done that ToDo; remove the comment and make a note in the bug to resolve it once this lands.
close: function TabItem_close() {
gBrowser.removeTab(this.tab);
- this._sendToSubscribers("tabRemoved");
+ let tabNotClosed =
+ Array.some(gBrowser.tabs, function(tab) { return tab == this.tab; }, this);
+ if (!tabNotClosed)
+ this._sendToSubscribers("tabRemoved");
// No need to explicitly delete the tab data, becasue sessionstore data
// associated with the tab will automatically go away
+ return !tabNotClosed;
},
If you take my suggestion above on removeHiddenGroup, you don't need this modification, though it does improve the quality of the "tabRemoved" message. On the other hand, why do we have "tabRemoved" when we already have "close"? Seems like that should get sorted out.
Attachment #481297 -
Flags: feedback?(ian) → feedback-
Assignee | ||
Comment 7•14 years ago
|
||
(In reply to comment #6)
> Comment on attachment 481297 [details] [diff] [review]
> v1
>
> + // Function: _showHiddenGroup
> + // Shows the hidden group.
>
> I find this name a little confusing, like this group has a hidden group, rather
> than that this group is hidden. Maybe a better name would be just _unhide()?
>
> + // Function: removeHiddenGroup
>
> This name is similarly confusing. How about closeHidden()?
>
Fixed
> I think this routine is more complicated than it needs to be. Rather than
> doing the removeSubscriber/shouldRemoveTabItems thing, just close all the tabs
> and then check to see if the group has automatically closed itself. If it
> hasn't, check to see if it still has tabs in it. If it does, unhide it,
> otherwise close it.
>
> You may need to modify GroupItem.close so it does the right thing in the hidden
> state, but that's better than having what's essentially a copy of it in this
> routine.
>
I've tried your suggestion however, it took me a while to figure the following flow.
When gBrowser.removeTab() is called, the "TabClose" event is fired. "TabClose" only means that the browser tab is about to close, not already closed. It would trigger the item "close" event is fired and then the browser tab would get closed. In other words, the group "close" event is fired before all browser tabs in the group are closed. if I If I change the code based on your suggestion , several tests would be broken because those tests assume that all browser tabs in that group are closed before the group "close" event is fired.
Therefore, I keep the code and just simplified it a bit to use GroupItem.close();.
> + GroupItems.removeHiddenGroups();
>
> Why did you move this out of hideTabView? Seemed like a better spot for it.
>
That's what I thought as well, however, putting GroupItems.removeHiddenGroups() would cause some undesired effects like the "Stay on page/ Leave page" dialog would appear twice. Therefore, I keep it in the zoomIn method.
> removeHiddenGroups: function GroupItems_removeHiddenGroups() {
> - iQ(".undo").remove();
> -
> // ToDo: encapsulate this in the group item. bug 594863
>
> Looks like you've done that ToDo; remove the comment and make a note in the bug
> to resolve it once this lands.
>
Sure
> close: function TabItem_close() {
> gBrowser.removeTab(this.tab);
> - this._sendToSubscribers("tabRemoved");
> + let tabNotClosed =
> + Array.some(gBrowser.tabs, function(tab) { return tab == this.tab; },
> this);
> + if (!tabNotClosed)
> + this._sendToSubscribers("tabRemoved");
>
> // No need to explicitly delete the tab data, becasue sessionstore data
> // associated with the tab will automatically go away
> + return !tabNotClosed;
> },
>
> If you take my suggestion above on removeHiddenGroup, you don't need this
> modification, though it does improve the quality of the "tabRemoved" message.
> On the other hand, why do we have "tabRemoved" when we already have "close"?
> Seems like that should get sorted out.
When "TabClose" event is fired, the browser tab is about to close and our item "close" is fired. Then, the browser tab get closed. Therefore, the "close" event doesn't mean the tab is already removed.
Attachment #481297 -
Attachment is obsolete: true
Attachment #481783 -
Flags: feedback?(ian)
Comment 8•14 years ago
|
||
Comment on attachment 481783 [details] [diff] [review]
v1
(In reply to comment #7)
> > + GroupItems.removeHiddenGroups();
> >
> > Why did you move this out of hideTabView? Seemed like a better spot for it.
> >
>
> That's what I thought as well, however, putting GroupItems.removeHiddenGroups()
> would cause some undesired effects like the "Stay on page/ Leave page" dialog
> would appear twice. Therefore, I keep it in the zoomIn method.
This worries me, as it means it'll have to be in two places (at the moment, maybe more in the future). Can you please look into why you're getting those undesired effects? I would think even if the routine got called twice, the first one would clean everything out (either closing or unhiding every group). Unless an exception is being thrown?
Attachment #481783 -
Flags: feedback?(ian) → feedback-
Assignee | ||
Comment 9•14 years ago
|
||
* Require patch from Bug 595521
(In reply to comment #8)
> Comment on attachment 481783 [details] [diff] [review]
> v1
>
> (In reply to comment #7)
> > > + GroupItems.removeHiddenGroups();
> > >
> > > Why did you move this out of hideTabView? Seemed like a better spot for it.
> > >
> >
> > That's what I thought as well, however, putting GroupItems.removeHiddenGroups()
> > would cause some undesired effects like the "Stay on page/ Leave page" dialog
> > would appear twice. Therefore, I keep it in the zoomIn method.
>
> This worries me, as it means it'll have to be in two places (at the moment,
> maybe more in the future). Can you please look into why you're getting those
> undesired effects? I would think even if the routine got called twice, the
> first one would clean everything out (either closing or unhiding every group).
> Unless an exception is being thrown?
If the GroupItems.removeHiddenGroups() is placed inside the hideTabView(), the routine would be:
* zoomIn() => the target tab is selected > onTabSelect() > hideTabView() => tab with confirmation prompt is selected > onTabSelect() > hideTabView() => prompt is displayed > user selects "Stay on page" or "Leave page".
The hideTabView()and GroupItems.removeHiddenGroups() (inside the hideTabView()) are called twice in the above routine. That's why the prompt is displayed twice as well as we try to close the same tab twice.
Another problem is that the target tab wouldn't be selected if user selects "Stay on page" in the above routine. The tab with prompt would remain selected.
Attachment #481783 -
Attachment is obsolete: true
Attachment #483404 -
Flags: feedback?(ian)
Comment 10•14 years ago
|
||
Comment on attachment 483404 [details] [diff] [review]
v1
(In reply to comment #9)
> If the GroupItems.removeHiddenGroups() is placed inside the hideTabView(), the
> routine would be:
> * zoomIn() => the target tab is selected > onTabSelect() > hideTabView() => tab
> with confirmation prompt is selected > onTabSelect() > hideTabView() => prompt
> is displayed > user selects "Stay on page" or "Leave page".
>
> The hideTabView()and GroupItems.removeHiddenGroups() (inside the hideTabView())
> are called twice in the above routine. That's why the prompt is displayed
> twice as well as we try to close the same tab twice.
Thank you for explaining this.
The thing is, we're not in control of all of the times we get TabSelect events (for instance when pages open due to external links), so we really can't cover all cases unless we put it inside onTabSelect or hideTabView, but then you get the nesting you describe. I think the best approach is for GroupItems to set a "_removingHiddenGroups" flag on itself and guard against re-entry that way.
> Another problem is that the target tab wouldn't be selected if user selects
> "Stay on page" in the above routine. The tab with prompt would remain selected.
I think this would actually be the correct behavior; if you chose to "stay on page", you probably have some unfinished business there.
Attachment #483404 -
Flags: feedback?(ian) → feedback-
Assignee | ||
Comment 11•14 years ago
|
||
* This patch requires patch for bug 595521
(In reply to comment #10)>
> The thing is, we're not in control of all of the times we get TabSelect events
> (for instance when pages open due to external links), so we really can't cover
> all cases unless we put it inside onTabSelect or hideTabView, but then you get
> the nesting you describe. I think the best approach is for GroupItems to set a
> "_removingHiddenGroups" flag on itself and guard against re-entry that way.
>
Done
> > Another problem is that the target tab wouldn't be selected if user selects
> > "Stay on page" in the above routine. The tab with prompt would remain selected.
>
> I think this would actually be the correct behavior; if you chose to "stay on
> page", you probably have some unfinished business there.
Done
Attachment #483404 -
Attachment is obsolete: true
Attachment #483913 -
Flags: feedback?(ian)
Comment 12•14 years ago
|
||
Comment on attachment 483913 [details] [diff] [review]
v1
Thanks, looking good. One thing:
>@@ -978,16 +1012,17 @@ GroupItem.prototype = Utils.extend(new I
> .addClass("appTabIcon")
> .attr("src", icon)
> .data("xulTab", xulTab)
> .appendTo(this.$appTabTray)
> .click(function(event) {
> if (Utils.isRightClick(event))
> return;
>
>+ GroupItems.removeHiddenGroups();
> GroupItems.setActiveGroupItem(self);
> UI.goToTab(iQ(this).data("xulTab"));
> });
You can remove this .removeHiddenGroups call (now that you're not removing it from hideTabView).
Attachment #483913 -
Flags: feedback?(ian) → feedback+
Assignee | ||
Comment 13•14 years ago
|
||
Removed the unnecessary .removeHiddenGroups call
f+=Ian
Attachment #483913 -
Attachment is obsolete: true
Attachment #484016 -
Flags: review?(dolske)
Attachment #484016 -
Flags: feedback?(ian)
Assignee | ||
Updated•14 years ago
|
Attachment #484016 -
Flags: feedback?(ian)
Assignee | ||
Comment 14•14 years ago
|
||
The last patch couldn't be applied cleanly. Here is a new one.
Attachment #484016 -
Attachment is obsolete: true
Attachment #484243 -
Flags: review?(dolske)
Attachment #484016 -
Flags: review?(dolske)
Comment 15•14 years ago
|
||
So, I'm missing something there. Comment 0 describes a problem caused by an onbeforeunload handler, which is commonly used to either (1) warn the user they're closing a page that has unsaved data or (2) annoy the user into staying on the site.
If you try and close a window with such a tab in it, we cancel the close, focus the tab with the problem, and show a prompt.
What should Panorama be doing if you close such a group? Nothing? Exiting Panorama to show the tab+prompt? Something else?
Assignee | ||
Comment 16•14 years ago
|
||
(In reply to comment #15)
> So, I'm missing something there. Comment 0 describes a problem caused by an
> onbeforeunload handler, which is commonly used to either (1) warn the user
> they're closing a page that has unsaved data or (2) annoy the user into staying
> on the site.
>
> If you try and close a window with such a tab in it, we cancel the close, focus
> the tab with the problem, and show a prompt.
>
> What should Panorama be doing if you close such a group? Nothing? Exiting
> Panorama to show the tab+prompt? Something else?
In Panorama view, if user closes the group and then close the "Undo Close group", the group would disappear in the UI and the prompt would display and ask whether you want to stay on the page or leave the page. If user stays on the page, the group would re-appear again. If user leaves the page, the group wouldn't appear.
In comment 0, step 7 - Choose a remaining group which means user picks a tab and exit the Panorama view. When exiting Panorama, all the hidden groups would be removed. Since a group contains a page with onbeforeunload handler, that tab+prompt would be shown. If user stays on the page, the tab would remain selected. If user decides to leave the page, the tab would be closed and the tabs in the original selected appropriate group would be displayed.
Assignee | ||
Updated•14 years ago
|
Attachment #484243 -
Attachment description: v1 → v1 (require patch in bug 595521)
Comment 17•14 years ago
|
||
Requesting blocking as this now blocks a blocker (bug 599623).
blocking2.0: --- → ?
Updated•14 years ago
|
blocking2.0: ? → betaN+
Updated•14 years ago
|
Attachment #484243 -
Flags: review?(dolske) → review+
Assignee | ||
Comment 18•14 years ago
|
||
r=dolske, a=blocking2.0
Attachment #484243 -
Attachment is obsolete: true
Assignee | ||
Updated•14 years ago
|
Keywords: checkin-needed
Comment 19•14 years ago
|
||
Looks like it's been a while since this patch has had a try run (comment 5), and it's hard for me to tell how much has changed. Does it need another?
Assignee | ||
Comment 20•14 years ago
|
||
(In reply to comment #19)
> Looks like it's been a while since this patch has had a try run (comment 5),
> and it's hard for me to tell how much has changed. Does it need another?
Sent it to try 52985d23f93e and waiting for the result
Assignee | ||
Comment 21•14 years ago
|
||
(In reply to comment #20)
> Sent it to try 52985d23f93e and waiting for the result
Passed try
Comment 22•14 years ago
|
||
Updated•9 years ago
|
Product: Firefox → Firefox Graveyard
You need to log in
before you can comment on or make changes to this bug.
Description
•