summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-04 15:43:20 +0000
committerviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-04 15:43:20 +0000
commit6ce8ba65f2767fcabec600bf4c0022e0022c16cb (patch)
tree36921eb1bfb5f90dcb2b9c9d69d5a3064f6fb897
parent66edf481b897f0ebc5d0eb6751a02af6b60c30d6 (diff)
downloadchromium_src-6ce8ba65f2767fcabec600bf4c0022e0022c16cb.zip
chromium_src-6ce8ba65f2767fcabec600bf4c0022e0022c16cb.tar.gz
chromium_src-6ce8ba65f2767fcabec600bf4c0022e0022c16cb.tar.bz2
Mac: fix crashes related to detaching tabs.
There are actually two problems, with two fixes: - Remove TabStripController as observer when removing a tab. (Otherwise, there's a race condition which can result in a stale observation.) - Make sure the TabController (and its TabView) aren't deleted while handling a torn-off tab. BUG=31138 TEST=Attach/re-attach/move/close tabs under a variety of circumstances (see in particular the situation described in the bug). Do so till the cows come home. It should hopefully not crash. (Perhaps also check a debug build, and make sure no assertions fail.) Review URL: http://codereview.chromium.org/515066 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35455 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/cocoa/tab_strip_controller.mm10
-rw-r--r--chrome/browser/cocoa/tab_view.mm10
2 files changed, 16 insertions, 4 deletions
diff --git a/chrome/browser/cocoa/tab_strip_controller.mm b/chrome/browser/cocoa/tab_strip_controller.mm
index 31a38ef..b3a1e87 100644
--- a/chrome/browser/cocoa/tab_strip_controller.mm
+++ b/chrome/browser/cocoa/tab_strip_controller.mm
@@ -947,8 +947,8 @@ private:
}
}
-// Remove all knowledge about this tab and it's associated
-// controller and remove the view from the strip.
+// Remove all knowledge about this tab and its associated controller, and remove
+// the view from the strip.
- (void)removeTab:(TabController*)controller {
NSUInteger index = [tabArray_ indexOfObject:controller];
@@ -962,6 +962,12 @@ private:
NSView* tab = [controller view];
[tab removeFromSuperview];
+ // Remove ourself as an observer.
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:self
+ name:NSViewDidUpdateTrackingAreasNotification
+ object:tab];
+
// Clear the tab controller's target.
// TODO(viettrungluu): [crbug.com/23829] Find a better way to handle the tab
// controller's target.
diff --git a/chrome/browser/cocoa/tab_view.mm b/chrome/browser/cocoa/tab_view.mm
index 0ad8c8c..4267b15 100644
--- a/chrome/browser/cocoa/tab_view.mm
+++ b/chrome/browser/cocoa/tab_view.mm
@@ -264,6 +264,12 @@ const CGFloat kRapidCloseDist = 2.5;
dragOrigin_ = [NSEvent mouseLocation];
+ // If the tab gets torn off, the tab controller will be removed from the tab
+ // strip and then deallocated. This will also result in *us* being
+ // deallocated. Both these are bad, so we prevent this by retaining the
+ // controller.
+ scoped_nsobject<TabController> controller([controller_ retain]);
+
// Because we move views between windows, we need to handle the event loop
// ourselves. Ideally we should use the standard event loop.
while (1) {
@@ -286,12 +292,12 @@ const CGFloat kRapidCloseDist = 2.5;
// and the mouse hasn't moved too much, we close the tab.
if (closeButtonActive &&
(dx*dx + dy*dy) <= kRapidCloseDist*kRapidCloseDist &&
- [controller_ inRapidClosureMode]) {
+ [controller inRapidClosureMode]) {
NSPoint hitLocation =
[[self superview] convertPoint:[theEvent locationInWindow]
fromView:nil];
if ([self hitTest:hitLocation] == closeButton_) {
- [controller_ closeTab:self];
+ [controller closeTab:self];
break;
}
}