Commit 2391c42b authored by shess@chromium.org's avatar shess@chromium.org

[Mac] Tear down extension-installed bubble before main window closes.

The main window closed before the bubble, so when the bubble tried to
remove itself as a child window, it called a stale reference.

Additionally, revise a couple uses of this pattern to be more robust
by asking the window being closed to remove itself from its current
parent window (which would be nil in this case).

BUG=94172
TEST=see bug, monitor crash server.


Review URL: http://codereview.chromium.org/7740060

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@99784 0039d316-1c4b-4281-b951-d872f2087c98
parent 062968e1
......@@ -157,7 +157,7 @@ class Bridge : public NotificationObserver {
}
- (void)close {
[parentWindow_ removeChildWindow:[self window]];
[[[self window] parentWindow] removeChildWindow:[self window]];
[super close];
}
......
......@@ -107,6 +107,13 @@ class ExtensionLoadedNotificationObserver : public NotificationObserver {
// Start showing window only after extension has fully loaded.
extensionObserver_.reset(new ExtensionLoadedNotificationObserver(
self, browser->profile()));
// Watch to see if the parent window closes, and if so, close this one.
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center addObserver:self
selector:@selector(parentWindowWillClose:)
name:NSWindowWillCloseNotification
object:parentWindow_];
}
return self;
}
......@@ -117,10 +124,14 @@ class ExtensionLoadedNotificationObserver : public NotificationObserver {
}
- (void)close {
[parentWindow_ removeChildWindow:[self window]];
[[[self window] parentWindow] removeChildWindow:[self window]];
[super close];
}
- (void)parentWindowWillClose:(NSNotification*)notification {
[self close];
}
- (void)windowWillClose:(NSNotification*)notification {
// Turn off page action icon preview when the window closes, unless we
// already removed it when the window resigned key status.
......
......@@ -14,9 +14,12 @@
#import "chrome/browser/ui/cocoa/browser_test_helper.h"
#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
#import "chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h"
#import "chrome/browser/ui/cocoa/info_bubble_window.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
#include "third_party/ocmock/gtest_support.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#include "webkit/glue/image_decoder.h"
// ExtensionInstalledBubbleController with removePageActionPreview overridden
......@@ -200,3 +203,37 @@ TEST_F(ExtensionInstalledBubbleControllerTest, BrowserActionTest) {
[controller close];
}
TEST_F(ExtensionInstalledBubbleControllerTest, ParentClose) {
extension_ = CreateExtension(extension_installed_bubble::kBrowserAction);
ExtensionInstalledBubbleControllerForTest* controller =
[[ExtensionInstalledBubbleControllerForTest alloc]
initWithParentWindow:window_
extension:extension_.get()
browser:browser_
icon:icon_];
EXPECT_TRUE(controller);
// Bring up the window and disable close animation.
[controller showWindow:nil];
NSWindow* bubbleWindow = [controller window];
ASSERT_TRUE([bubbleWindow isKindOfClass:[InfoBubbleWindow class]]);
[static_cast<InfoBubbleWindow*>(bubbleWindow) setDelayOnClose:NO];
// Observe whether the bubble window closes.
NSString* notification = NSWindowWillCloseNotification;
id observer = [OCMockObject observerMock];
[[observer expect] notificationWithName:notification object:bubbleWindow];
[[NSNotificationCenter defaultCenter]
addMockObserver:observer name:notification object:bubbleWindow];
// The bubble window goes from visible to not-visible.
EXPECT_TRUE([bubbleWindow isVisible]);
[window_ close];
EXPECT_FALSE([bubbleWindow isVisible]);
[[NSNotificationCenter defaultCenter] removeObserver:observer];
// Check that the appropriate notification was received.
EXPECT_OCMOCK_VERIFY(observer);
}
......@@ -171,15 +171,7 @@ class DevtoolsNotificationBridge : public NotificationObserver {
}
- (void)close {
[parentWindow_ removeChildWindow:[self window]];
// No longer have a parent window, so nil out the pointer and deregister for
// notifications.
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center removeObserver:self
name:NSWindowWillCloseNotification
object:parentWindow_];
parentWindow_ = nil;
[[[self window] parentWindow] removeChildWindow:[self window]];
[super close];
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment