Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(262)

Side by Side Diff: chrome/browser/ui/cocoa/base_bubble_controller_unittest.mm

Issue 576643002: Mac: Ignore sheets when deciding whether to dismiss a browser action popup. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: -dot notation.. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/ui/cocoa/base_bubble_controller.mm ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/browser/ui/cocoa/base_bubble_controller.h" 5 #import "chrome/browser/ui/cocoa/base_bubble_controller.h"
6 6
7 #include "base/mac/mac_util.h" 7 #include "base/mac/mac_util.h"
8 #import "base/mac/scoped_nsobject.h" 8 #import "base/mac/scoped_nsobject.h"
9 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h" 9 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
10 #import "chrome/browser/ui/cocoa/info_bubble_view.h" 10 #import "chrome/browser/ui/cocoa/info_bubble_view.h"
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 79
80 - (void)menuDidClose:(NSMenu*)menu { 80 - (void)menuDidClose:(NSMenu*)menu {
81 isMenuOpen_ = NO; 81 isMenuOpen_ = NO;
82 didOpen_ = YES; 82 didOpen_ = YES;
83 } 83 }
84 84
85 @end 85 @end
86 86
87 class BaseBubbleControllerTest : public CocoaTest { 87 class BaseBubbleControllerTest : public CocoaTest {
88 public: 88 public:
89 BaseBubbleControllerTest() : controller_(nil) {}
90
89 virtual void SetUp() OVERRIDE { 91 virtual void SetUp() OVERRIDE {
90 bubbleWindow_.reset([[InfoBubbleWindow alloc] 92 bubble_window_.reset([[InfoBubbleWindow alloc]
91 initWithContentRect:NSMakeRect(0, 0, kBubbleWindowWidth, 93 initWithContentRect:NSMakeRect(0, 0, kBubbleWindowWidth,
92 kBubbleWindowHeight) 94 kBubbleWindowHeight)
93 styleMask:NSBorderlessWindowMask 95 styleMask:NSBorderlessWindowMask
94 backing:NSBackingStoreBuffered 96 backing:NSBackingStoreBuffered
95 defer:YES]); 97 defer:YES]);
96 [bubbleWindow_ setAllowedAnimations:0]; 98 [bubble_window_ setAllowedAnimations:0];
97 99
98 // The bubble controller will release itself when the window closes. 100 // The bubble controller will release itself when the window closes.
99 controller_ = [[BaseBubbleController alloc] 101 controller_ = [[BaseBubbleController alloc]
100 initWithWindow:bubbleWindow_.get() 102 initWithWindow:bubble_window_
101 parentWindow:test_window() 103 parentWindow:test_window()
102 anchoredAt:NSMakePoint(kAnchorPointX, kAnchorPointY)]; 104 anchoredAt:NSMakePoint(kAnchorPointX, kAnchorPointY)];
103 EXPECT_TRUE([controller_ bubble]); 105 EXPECT_TRUE([controller_ bubble]);
106 EXPECT_EQ(bubble_window_.get(), [controller_ window]);
104 } 107 }
105 108
106 virtual void TearDown() OVERRIDE { 109 virtual void TearDown() OVERRIDE {
107 // Close our windows. 110 // Close our windows.
108 [controller_ close]; 111 [controller_ close];
109 bubbleWindow_.reset(NULL); 112 bubble_window_.reset();
110 CocoaTest::TearDown(); 113 CocoaTest::TearDown();
111 } 114 }
112 115
113 public: 116 // Closing the bubble will autorelease the controller. Give callers a keep-
114 base::scoped_nsobject<InfoBubbleWindow> bubbleWindow_; 117 // alive to run checks after closing.
118 base::scoped_nsobject<BaseBubbleController> ShowBubble() WARN_UNUSED_RESULT {
119 base::scoped_nsobject<BaseBubbleController> keep_alive(
120 [controller_ retain]);
121 EXPECT_FALSE([bubble_window_ isVisible]);
122 [controller_ showWindow:nil];
123 EXPECT_TRUE([bubble_window_ isVisible]);
124 return keep_alive;
125 }
126
127 // Fake the key state notification. Because unit_tests is a "daemon" process
128 // type, its windows can never become key (nor can the app become active).
129 // Instead of the hacks below, one could make a browser_test or transform the
130 // process type, but this seems easiest and is best suited to a unit test.
131 //
132 // On Lion and above, which have the event taps, simply post a notification
133 // that will cause the controller to call |-windowDidResignKey:|. Earlier
134 // OSes can call through directly.
135 void SimulateKeyStatusChange() {
136 NSNotification* notif =
137 [NSNotification notificationWithName:NSWindowDidResignKeyNotification
138 object:[controller_ window]];
139 if (base::mac::IsOSLionOrLater())
140 [[NSNotificationCenter defaultCenter] postNotification:notif];
141 else
142 [controller_ windowDidResignKey:notif];
143 }
144
145 protected:
146 base::scoped_nsobject<InfoBubbleWindow> bubble_window_;
115 BaseBubbleController* controller_; 147 BaseBubbleController* controller_;
148
149 private:
150 DISALLOW_COPY_AND_ASSIGN(BaseBubbleControllerTest);
116 }; 151 };
117 152
118 // Test that kAlignEdgeToAnchorEdge and a left bubble arrow correctly aligns the 153 // Test that kAlignEdgeToAnchorEdge and a left bubble arrow correctly aligns the
119 // left edge of the buble to the anchor point. 154 // left edge of the buble to the anchor point.
120 TEST_F(BaseBubbleControllerTest, LeftAlign) { 155 TEST_F(BaseBubbleControllerTest, LeftAlign) {
121 [[controller_ bubble] setArrowLocation:info_bubble::kTopLeft]; 156 [[controller_ bubble] setArrowLocation:info_bubble::kTopLeft];
122 [[controller_ bubble] setAlignment:info_bubble::kAlignEdgeToAnchorEdge]; 157 [[controller_ bubble] setAlignment:info_bubble::kAlignEdgeToAnchorEdge];
123 [controller_ showWindow:nil]; 158 [controller_ showWindow:nil];
124 159
125 NSRect frame = [[controller_ window] frame]; 160 NSRect frame = [[controller_ window] frame];
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 EXPECT_EQ(frame.size.width, kBubbleWindowWidth); 228 EXPECT_EQ(frame.size.width, kBubbleWindowWidth);
194 EXPECT_EQ(frame.size.height, kBubbleWindowHeight); 229 EXPECT_EQ(frame.size.height, kBubbleWindowHeight);
195 // Make sure the bubble arrow points to the anchor. 230 // Make sure the bubble arrow points to the anchor.
196 EXPECT_EQ(NSMidX(frame), kAnchorPointX); 231 EXPECT_EQ(NSMidX(frame), kAnchorPointX);
197 EXPECT_GE(NSMaxY(frame), kAnchorPointY); 232 EXPECT_GE(NSMaxY(frame), kAnchorPointY);
198 } 233 }
199 234
200 // Tests that when a new window gets key state (and the bubble resigns) that 235 // Tests that when a new window gets key state (and the bubble resigns) that
201 // the key window changes. 236 // the key window changes.
202 TEST_F(BaseBubbleControllerTest, ResignKeyCloses) { 237 TEST_F(BaseBubbleControllerTest, ResignKeyCloses) {
203 // Closing the bubble will autorelease the controller.
204 base::scoped_nsobject<BaseBubbleController> keep_alive([controller_ retain]);
205
206 NSWindow* bubble_window = [controller_ window];
207 EXPECT_FALSE([bubble_window isVisible]);
208
209 base::scoped_nsobject<NSWindow> other_window( 238 base::scoped_nsobject<NSWindow> other_window(
210 [[NSWindow alloc] initWithContentRect:NSMakeRect(500, 500, 500, 500) 239 [[NSWindow alloc] initWithContentRect:NSMakeRect(500, 500, 500, 500)
211 styleMask:NSTitledWindowMask 240 styleMask:NSTitledWindowMask
212 backing:NSBackingStoreBuffered 241 backing:NSBackingStoreBuffered
213 defer:YES]); 242 defer:YES]);
214 EXPECT_FALSE([other_window isVisible]);
215 243
216 [controller_ showWindow:nil]; 244 base::scoped_nsobject<BaseBubbleController> keep_alive = ShowBubble();
217 EXPECT_TRUE([bubble_window isVisible]);
218 EXPECT_FALSE([other_window isVisible]); 245 EXPECT_FALSE([other_window isVisible]);
219 246
220 [other_window makeKeyAndOrderFront:nil]; 247 [other_window makeKeyAndOrderFront:nil];
221 // Fake the key state notification. Because unit_tests is a "daemon" process 248 SimulateKeyStatusChange();
222 // type, its windows can never become key (nor can the app become active).
223 // Instead of the hacks below, one could make a browser_test or transform the
224 // process type, but this seems easiest and is best suited to a unit test.
225 //
226 // On Lion and above, which have the event taps, simply post a notification
227 // that will cause the controller to call |-windowDidResignKey:|. Earlier
228 // OSes can call through directly.
229 NSNotification* notif =
230 [NSNotification notificationWithName:NSWindowDidResignKeyNotification
231 object:bubble_window];
232 if (base::mac::IsOSLionOrLater())
233 [[NSNotificationCenter defaultCenter] postNotification:notif];
234 else
235 [controller_ windowDidResignKey:notif];
236 249
237 250 EXPECT_FALSE([bubble_window_ isVisible]);
238 EXPECT_FALSE([bubble_window isVisible]);
239 EXPECT_TRUE([other_window isVisible]); 251 EXPECT_TRUE([other_window isVisible]);
240 } 252 }
241 253
242 // Test that clicking outside the window causes the bubble to close if 254 // Test that clicking outside the window causes the bubble to close if
243 // shouldCloseOnResignKey is YES. 255 // shouldCloseOnResignKey is YES.
244 TEST_F(BaseBubbleControllerTest, LionClickOutsideClosesWithoutContextMenu) { 256 TEST_F(BaseBubbleControllerTest, LionClickOutsideClosesWithoutContextMenu) {
245 // The event tap is only installed on 10.7+. 257 // The event tap is only installed on 10.7+.
246 if (!base::mac::IsOSLionOrLater()) 258 if (!base::mac::IsOSLionOrLater())
247 return; 259 return;
248 260
249 // Closing the bubble will autorelease the controller. 261 base::scoped_nsobject<BaseBubbleController> keep_alive = ShowBubble();
250 base::scoped_nsobject<BaseBubbleController> keep_alive([controller_ retain]);
251 NSWindow* window = [controller_ window]; 262 NSWindow* window = [controller_ window];
252 263
253 EXPECT_TRUE([controller_ shouldCloseOnResignKey]); // Verify default value. 264 EXPECT_TRUE([controller_ shouldCloseOnResignKey]); // Verify default value.
254 EXPECT_FALSE([window isVisible]);
255
256 [controller_ showWindow:nil];
257
258 EXPECT_TRUE([window isVisible]);
259
260 [controller_ setShouldCloseOnResignKey:NO]; 265 [controller_ setShouldCloseOnResignKey:NO];
261 NSEvent* event = cocoa_test_event_utils::LeftMouseDownAtPointInWindow( 266 NSEvent* event = cocoa_test_event_utils::LeftMouseDownAtPointInWindow(
262 NSMakePoint(10, 10), test_window()); 267 NSMakePoint(10, 10), test_window());
263 [NSApp sendEvent:event]; 268 [NSApp sendEvent:event];
264 269
265 EXPECT_TRUE([window isVisible]); 270 EXPECT_TRUE([window isVisible]);
266 271
267 event = cocoa_test_event_utils::RightMouseDownAtPointInWindow( 272 event = cocoa_test_event_utils::RightMouseDownAtPointInWindow(
268 NSMakePoint(10, 10), test_window()); 273 NSMakePoint(10, 10), test_window());
269 [NSApp sendEvent:event]; 274 [NSApp sendEvent:event];
(...skipping 18 matching lines...) Expand all
288 EXPECT_FALSE([window isVisible]); 293 EXPECT_FALSE([window isVisible]);
289 } 294 }
290 295
291 // Test that right-clicking the window with displaying a context menu causes 296 // Test that right-clicking the window with displaying a context menu causes
292 // the bubble to close. 297 // the bubble to close.
293 TEST_F(BaseBubbleControllerTest, LionRightClickOutsideClosesWithContextMenu) { 298 TEST_F(BaseBubbleControllerTest, LionRightClickOutsideClosesWithContextMenu) {
294 // The event tap is only installed on 10.7+. 299 // The event tap is only installed on 10.7+.
295 if (!base::mac::IsOSLionOrLater()) 300 if (!base::mac::IsOSLionOrLater())
296 return; 301 return;
297 302
298 // Closing the bubble will autorelease the controller. 303 base::scoped_nsobject<BaseBubbleController> keep_alive = ShowBubble();
299 base::scoped_nsobject<BaseBubbleController> keep_alive([controller_ retain]);
300 NSWindow* window = [controller_ window]; 304 NSWindow* window = [controller_ window];
301 305
302 EXPECT_TRUE([controller_ shouldCloseOnResignKey]); // Verify default value.
303 EXPECT_FALSE([window isVisible]);
304
305 [controller_ showWindow:nil];
306
307 EXPECT_TRUE([window isVisible]);
308
309 base::scoped_nsobject<NSMenu> context_menu( 306 base::scoped_nsobject<NSMenu> context_menu(
310 [[NSMenu alloc] initWithTitle:@""]); 307 [[NSMenu alloc] initWithTitle:@""]);
311 [context_menu addItemWithTitle:@"ContextMenuTest" 308 [context_menu addItemWithTitle:@"ContextMenuTest"
312 action:nil 309 action:nil
313 keyEquivalent:@""]; 310 keyEquivalent:@""];
314 base::scoped_nsobject<ContextMenuController> menu_controller( 311 base::scoped_nsobject<ContextMenuController> menu_controller(
315 [[ContextMenuController alloc] initWithMenu:context_menu 312 [[ContextMenuController alloc] initWithMenu:context_menu
316 andWindow:window]); 313 andWindow:window]);
317 314
318 // Set the menu as the contextual menu of contentView of test_window(). 315 // Set the menu as the contextual menu of contentView of test_window().
(...skipping 15 matching lines...) Expand all
334 [NSApp sendEvent:event]; 331 [NSApp sendEvent:event];
335 332
336 // When we got here, menu has already run its RunLoop. 333 // When we got here, menu has already run its RunLoop.
337 // See -[ContextualMenuController menuWillOpen:]. 334 // See -[ContextualMenuController menuWillOpen:].
338 EXPECT_FALSE([window isVisible]); 335 EXPECT_FALSE([window isVisible]);
339 336
340 EXPECT_FALSE([menu_controller isMenuOpen]); 337 EXPECT_FALSE([menu_controller isMenuOpen]);
341 EXPECT_TRUE([menu_controller didOpen]); 338 EXPECT_TRUE([menu_controller didOpen]);
342 } 339 }
343 340
341 // Test that the bubble is not dismissed when it has an attached sheet, or when
342 // a sheet loses key status (since the sheet is not attached when that happens).
343 TEST_F(BaseBubbleControllerTest, BubbleStaysOpenWithSheet) {
344 base::scoped_nsobject<BaseBubbleController> keep_alive = ShowBubble();
345
346 // Make a dummy NSPanel for the sheet. Don't use [NSOpenPanel openPanel],
347 // otherwise a stray FI_TFloatingInputWindow is created which the unit test
348 // harness doesn't like.
349 base::scoped_nsobject<NSPanel> panel(
350 [[NSPanel alloc] initWithContentRect:NSMakeRect(0, 0, 100, 50)
351 styleMask:NSTitledWindowMask
352 backing:NSBackingStoreBuffered
353 defer:YES]);
354 EXPECT_FALSE([panel isReleasedWhenClosed]); // scoped_nsobject releases it.
355
356 // With a NSOpenPanel, we would call -[NSSavePanel beginSheetModalForWindow]
357 // here. In 10.9, we would call [NSWindow beginSheet:]. For 10.6, this:
358 [[NSApplication sharedApplication] beginSheet:panel
359 modalForWindow:bubble_window_
360 modalDelegate:nil
361 didEndSelector:NULL
362 contextInfo:NULL];
363
364 EXPECT_TRUE([bubble_window_ isVisible]);
365 EXPECT_TRUE([panel isVisible]);
366 // Losing key status while there is an attached window should not close the
367 // bubble.
368 SimulateKeyStatusChange();
369 EXPECT_TRUE([bubble_window_ isVisible]);
370 EXPECT_TRUE([panel isVisible]);
371
372 // Closing the attached sheet should not close the bubble.
373 [[NSApplication sharedApplication] endSheet:panel];
374 [panel close];
375
376 EXPECT_FALSE([bubble_window_ attachedSheet]);
377 EXPECT_TRUE([bubble_window_ isVisible]);
378 EXPECT_FALSE([panel isVisible]);
379
380 // Now that the sheet is gone, a key status change should close the bubble.
381 SimulateKeyStatusChange();
382 EXPECT_FALSE([bubble_window_ isVisible]);
383 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/base_bubble_controller.mm ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698