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

Side by Side Diff: chrome/browser/ui/panels/panel_browser_window_cocoa_unittest.mm

Issue 10908153: [Panel refactor] Deprecate old panels. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix linux_chromeos test failure Created 8 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 | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #import "chrome/browser/ui/panels/panel_browser_window_cocoa.h"
6
7 #include <Carbon/Carbon.h>
8 #import <Cocoa/Cocoa.h>
9
10 #include "base/command_line.h"
11 #include "base/debug/debugger.h"
12 #include "base/mac/scoped_nsautorelease_pool.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/sys_string_conversions.h"
15 #include "chrome/app/chrome_command_ids.h" // IDC_*
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/browser_list.h"
18 #import "chrome/browser/ui/cocoa/browser_window_utils.h"
19 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
20 #import "chrome/browser/ui/cocoa/run_loop_testing.h"
21 #include "chrome/browser/ui/panels/panel.h"
22 #include "chrome/browser/ui/panels/panel_browser_window.h"
23 #include "chrome/browser/ui/panels/panel_manager.h"
24 #import "chrome/browser/ui/panels/panel_titlebar_view_cocoa.h"
25 #import "chrome/browser/ui/panels/panel_window_controller_cocoa.h"
26 #include "chrome/common/chrome_notification_types.h"
27 #include "chrome/common/chrome_switches.h"
28 #include "content/public/test/test_utils.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "testing/gtest_mac.h"
31
32 class PanelAnimatedBoundsObserver :
33 public content::WindowedNotificationObserver {
34 public:
35 PanelAnimatedBoundsObserver(Panel* panel)
36 : content::WindowedNotificationObserver(
37 chrome::NOTIFICATION_PANEL_BOUNDS_ANIMATIONS_FINISHED,
38 content::Source<Panel>(panel)) { }
39 virtual ~PanelAnimatedBoundsObserver() { }
40 };
41
42 // Main test class.
43 class PanelBrowserWindowCocoaTest : public CocoaProfileTest {
44 public:
45 virtual void SetUp() {
46 CocoaProfileTest::SetUp();
47 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnablePanels);
48 }
49
50 Panel* CreateTestPanel(const std::string& panel_name) {
51 // Opening panels on a Mac causes NSWindowController of the Panel window
52 // to be autoreleased. We need a pool drained after it's done so the test
53 // can close correctly.
54 base::mac::ScopedNSAutoreleasePool autorelease_pool;
55
56 PanelManager* manager = PanelManager::GetInstance();
57 int panels_count = manager->num_panels();
58
59 Browser* panel_browser = new Browser(Browser::CreateParams::CreateForApp(
60 Browser::TYPE_PANEL, panel_name, gfx::Rect(), profile()));
61 EXPECT_EQ(panels_count + 1, manager->num_panels());
62
63 PanelBrowserWindow* panel_browser_window =
64 static_cast<PanelBrowserWindow*>(panel_browser->window());
65 Panel* panel = panel_browser_window->panel();
66 EXPECT_TRUE(panel);
67 EXPECT_TRUE(panel->native_panel()); // Native panel is created right away.
68 PanelBrowserWindowCocoa* native_window =
69 static_cast<PanelBrowserWindowCocoa*>(panel->native_panel());
70 EXPECT_EQ(panel, native_window->panel_); // Back pointer initialized.
71
72 PanelAnimatedBoundsObserver bounds_observer(panel);
73
74 // Window should not load before Show().
75 // Note: Loading the wnidow causes Cocoa to autorelease a few objects.
76 // This is the reason we do this within the scope of the
77 // ScopedNSAutoreleasePool.
78 EXPECT_FALSE([native_window->controller_ isWindowLoaded]);
79 panel->Show();
80 EXPECT_TRUE([native_window->controller_ isWindowLoaded]);
81 EXPECT_TRUE([native_window->controller_ window]);
82
83 // Wait until bounds animate to their specified values.
84 bounds_observer.Wait();
85
86 return panel;
87 }
88
89 void VerifyTitlebarLocation(NSView* contentView, NSView* titlebar) {
90 NSRect content_frame = [contentView frame];
91 NSRect titlebar_frame = [titlebar frame];
92 // Since contentView and titlebar are both children of window's root view,
93 // we can compare their frames since they are in the same coordinate system.
94 EXPECT_EQ(NSMinX(content_frame), NSMinX(titlebar_frame));
95 EXPECT_EQ(NSWidth(content_frame), NSWidth(titlebar_frame));
96 EXPECT_EQ(NSHeight([[titlebar superview] bounds]), NSMaxY(titlebar_frame));
97 }
98
99 void ClosePanelAndWait(Panel* panel) {
100 EXPECT_TRUE(panel);
101 // Closing a panel may involve several async tasks. Need to use
102 // message pump and wait for the notification.
103 PanelManager* manager = PanelManager::GetInstance();
104 int panel_count = manager->num_panels();
105 content::WindowedNotificationObserver signal(
106 chrome::NOTIFICATION_PANEL_CLOSED,
107 content::Source<Panel>(panel));
108 panel->Close();
109 signal.Wait();
110 // Now we have one less panel.
111 EXPECT_EQ(panel_count - 1, manager->num_panels());
112 }
113
114 NSMenuItem* CreateMenuItem(NSMenu* menu, int command_id) {
115 NSMenuItem* item =
116 [menu addItemWithTitle:@""
117 action:@selector(commandDispatch:)
118 keyEquivalent:@""];
119 [item setTag:command_id];
120 return item;
121 }
122 };
123
124 TEST_F(PanelBrowserWindowCocoaTest, CreateClose) {
125 PanelManager* manager = PanelManager::GetInstance();
126 EXPECT_EQ(0, manager->num_panels()); // No panels initially.
127
128 Panel* panel = CreateTestPanel("Test Panel");
129 ASSERT_TRUE(panel);
130
131 gfx::Rect bounds = panel->GetBounds();
132 EXPECT_TRUE(bounds.width() > 0);
133 EXPECT_TRUE(bounds.height() > 0);
134
135 PanelBrowserWindowCocoa* native_window =
136 static_cast<PanelBrowserWindowCocoa*>(panel->native_panel());
137 ASSERT_TRUE(native_window);
138 // NSWindows created by NSWindowControllers don't have this bit even if
139 // their NIB has it. The controller's lifetime is the window's lifetime.
140 EXPECT_EQ(NO, [[native_window->controller_ window] isReleasedWhenClosed]);
141
142 ClosePanelAndWait(panel);
143 EXPECT_EQ(0, manager->num_panels());
144 }
145
146 TEST_F(PanelBrowserWindowCocoaTest, AssignedBounds) {
147 Panel* panel1 = CreateTestPanel("Test Panel 1");
148 Panel* panel2 = CreateTestPanel("Test Panel 2");
149 Panel* panel3 = CreateTestPanel("Test Panel 3");
150
151 gfx::Rect bounds1 = panel1->GetBounds();
152 gfx::Rect bounds2 = panel2->GetBounds();
153 gfx::Rect bounds3 = panel3->GetBounds();
154
155 // This checks panelManager calculating and assigning bounds right.
156 // Panels should stack on the bottom right to left.
157 EXPECT_LT(bounds3.x() + bounds3.width(), bounds2.x());
158 EXPECT_LT(bounds2.x() + bounds2.width(), bounds1.x());
159 EXPECT_EQ(bounds1.y(), bounds2.y());
160 EXPECT_EQ(bounds2.y(), bounds3.y());
161
162 // After panel2 is closed, panel3 should take its place.
163 ClosePanelAndWait(panel2);
164 bounds3 = panel3->GetBounds();
165 EXPECT_EQ(bounds2, bounds3);
166
167 // After panel1 is closed, panel3 should take its place.
168 ClosePanelAndWait(panel1);
169 EXPECT_EQ(bounds1, panel3->GetBounds());
170
171 ClosePanelAndWait(panel3);
172 }
173
174 // Same test as AssignedBounds, but checks actual bounds on native OS windows.
175 TEST_F(PanelBrowserWindowCocoaTest, NativeBounds) {
176 Panel* panel1 = CreateTestPanel("Test Panel 1");
177 Panel* panel2 = CreateTestPanel("Test Panel 2");
178 Panel* panel3 = CreateTestPanel("Test Panel 3");
179
180 PanelBrowserWindowCocoa* native_window1 =
181 static_cast<PanelBrowserWindowCocoa*>(panel1->native_panel());
182 PanelBrowserWindowCocoa* native_window2 =
183 static_cast<PanelBrowserWindowCocoa*>(panel2->native_panel());
184 PanelBrowserWindowCocoa* native_window3 =
185 static_cast<PanelBrowserWindowCocoa*>(panel3->native_panel());
186
187 NSRect bounds1 = [[native_window1->controller_ window] frame];
188 NSRect bounds2 = [[native_window2->controller_ window] frame];
189 NSRect bounds3 = [[native_window3->controller_ window] frame];
190
191 EXPECT_LT(bounds3.origin.x + bounds3.size.width, bounds2.origin.x);
192 EXPECT_LT(bounds2.origin.x + bounds2.size.width, bounds1.origin.x);
193 EXPECT_EQ(bounds1.origin.y, bounds2.origin.y);
194 EXPECT_EQ(bounds2.origin.y, bounds3.origin.y);
195
196 {
197 // After panel2 is closed, panel3 should take its place.
198 PanelAnimatedBoundsObserver bounds_observer(panel3);
199 ClosePanelAndWait(panel2);
200 bounds_observer.Wait();
201 bounds3 = [[native_window3->controller_ window] frame];
202 EXPECT_EQ(bounds2.origin.x, bounds3.origin.x);
203 EXPECT_EQ(bounds2.origin.y, bounds3.origin.y);
204 EXPECT_EQ(bounds2.size.width, bounds3.size.width);
205 EXPECT_EQ(bounds2.size.height, bounds3.size.height);
206 }
207
208 {
209 // After panel1 is closed, panel3 should take its place.
210 PanelAnimatedBoundsObserver bounds_observer(panel3);
211 ClosePanelAndWait(panel1);
212 bounds_observer.Wait();
213 bounds3 = [[native_window3->controller_ window] frame];
214 EXPECT_EQ(bounds1.origin.x, bounds3.origin.x);
215 EXPECT_EQ(bounds1.origin.y, bounds3.origin.y);
216 EXPECT_EQ(bounds1.size.width, bounds3.size.width);
217 EXPECT_EQ(bounds1.size.height, bounds3.size.height);
218 }
219
220 ClosePanelAndWait(panel3);
221 }
222
223 // Verify the titlebar is being created.
224 TEST_F(PanelBrowserWindowCocoaTest, TitlebarViewCreate) {
225 Panel* panel = CreateTestPanel("Test Panel");
226
227 PanelBrowserWindowCocoa* native_window =
228 static_cast<PanelBrowserWindowCocoa*>(panel->native_panel());
229
230 PanelTitlebarViewCocoa* titlebar = [native_window->controller_ titlebarView];
231 EXPECT_TRUE(titlebar);
232 EXPECT_EQ(native_window->controller_, [titlebar controller]);
233
234 ClosePanelAndWait(panel);
235 }
236
237 // Verify the sizing of titlebar - should be affixed on top of regular titlebar.
238 TEST_F(PanelBrowserWindowCocoaTest, TitlebarViewSizing) {
239 Panel* panel = CreateTestPanel("Test Panel");
240
241 PanelBrowserWindowCocoa* native_window =
242 static_cast<PanelBrowserWindowCocoa*>(panel->native_panel());
243 PanelTitlebarViewCocoa* titlebar = [native_window->controller_ titlebarView];
244
245 NSView* contentView = [[native_window->controller_ window] contentView];
246 VerifyTitlebarLocation(contentView, titlebar);
247
248 // In local coordinate system, width of titlebar should match width of
249 // content view of the window. They both use the same scale factor.
250 EXPECT_EQ(NSWidth([contentView bounds]), NSWidth([titlebar bounds]));
251
252 NSRect oldTitleFrame = [[titlebar title] frame];
253 NSRect oldIconFrame = [[titlebar icon] frame];
254
255 // Now resize the Panel, see that titlebar follows.
256 const int kDelta = 153; // random number
257 gfx::Rect bounds = panel->GetBounds();
258 // Grow panel in a way so that its titlebar moves and grows.
259 bounds.set_x(bounds.x() - kDelta);
260 bounds.set_y(bounds.y() - kDelta);
261 bounds.set_width(bounds.width() + kDelta);
262 bounds.set_height(bounds.height() + kDelta);
263
264 PanelAnimatedBoundsObserver bounds_observer(panel);
265 native_window->SetPanelBounds(bounds);
266 bounds_observer.Wait();
267
268 // Verify the panel resized.
269 NSRect window_frame = [[native_window->controller_ window] frame];
270 EXPECT_EQ(NSWidth(window_frame), bounds.width());
271 EXPECT_EQ(NSHeight(window_frame), bounds.height());
272
273 // Verify the titlebar is still on top of regular titlebar.
274 VerifyTitlebarLocation(contentView, titlebar);
275
276 // Verify that the title/icon frames were updated.
277 NSRect newTitleFrame = [[titlebar title] frame];
278 NSRect newIconFrame = [[titlebar icon] frame];
279
280 EXPECT_EQ(newTitleFrame.origin.x - newIconFrame.origin.x,
281 oldTitleFrame.origin.x - oldIconFrame.origin.x);
282 // Icon and Text should remain at the same left-aligned position.
283 EXPECT_EQ(newTitleFrame.origin.x, oldTitleFrame.origin.x);
284 EXPECT_EQ(newIconFrame.origin.x, oldIconFrame.origin.x);
285
286 ClosePanelAndWait(panel);
287 }
288
289 // Verify closing behavior of titlebar close button.
290 TEST_F(PanelBrowserWindowCocoaTest, TitlebarViewClose) {
291 Panel* panel = CreateTestPanel("Test Panel");
292
293 PanelBrowserWindowCocoa* native_window =
294 static_cast<PanelBrowserWindowCocoa*>(panel->native_panel());
295
296 PanelTitlebarViewCocoa* titlebar = [native_window->controller_ titlebarView];
297 EXPECT_TRUE(titlebar);
298
299 PanelManager* manager = PanelManager::GetInstance();
300 EXPECT_EQ(1, manager->num_panels());
301 // Simulate clicking Close Button and wait until the Panel closes.
302 content::WindowedNotificationObserver signal(
303 chrome::NOTIFICATION_PANEL_CLOSED,
304 content::Source<Panel>(panel));
305 [titlebar simulateCloseButtonClick];
306 signal.Wait();
307 EXPECT_EQ(0, manager->num_panels());
308 }
309
310 // Verify some menu items being properly enabled/disabled for panels.
311 TEST_F(PanelBrowserWindowCocoaTest, MenuItems) {
312 Panel* panel = CreateTestPanel("Test Panel");
313
314 scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]);
315 NSMenuItem* close_tab_menu_item = CreateMenuItem(menu, IDC_CLOSE_TAB);
316 NSMenuItem* close_window_menu_item = CreateMenuItem(menu, IDC_CLOSE_WINDOW);
317 NSMenuItem* find_menu_item = CreateMenuItem(menu, IDC_FIND);
318 NSMenuItem* find_previous_menu_item = CreateMenuItem(menu, IDC_FIND_PREVIOUS);
319 NSMenuItem* find_next_menu_item = CreateMenuItem(menu, IDC_FIND_NEXT);
320 NSMenuItem* fullscreen_menu_item = CreateMenuItem(menu, IDC_FULLSCREEN);
321 NSMenuItem* presentation_menu_item =
322 CreateMenuItem(menu, IDC_PRESENTATION_MODE);
323 NSMenuItem* sync_menu_item = CreateMenuItem(menu, IDC_SHOW_SYNC_SETUP);
324
325 PanelBrowserWindowCocoa* native_window =
326 static_cast<PanelBrowserWindowCocoa*>(panel->native_panel());
327 PanelWindowControllerCocoa* panel_controller = native_window->controller_;
328 for (NSMenuItem *item in [menu itemArray])
329 [item setTarget:panel_controller];
330
331 [menu update]; // Trigger validation of menu items.
332 EXPECT_FALSE([close_tab_menu_item isEnabled]);
333 EXPECT_TRUE([close_window_menu_item isEnabled]);
334 EXPECT_TRUE([find_menu_item isEnabled]);
335 EXPECT_TRUE([find_previous_menu_item isEnabled]);
336 EXPECT_TRUE([find_next_menu_item isEnabled]);
337 EXPECT_FALSE([fullscreen_menu_item isEnabled]);
338 EXPECT_FALSE([presentation_menu_item isEnabled]);
339 EXPECT_FALSE([sync_menu_item isEnabled]);
340
341 ClosePanelAndWait(panel);
342 }
343
344 TEST_F(PanelBrowserWindowCocoaTest, KeyEvent) {
345 Panel* panel = CreateTestPanel("Test Panel");
346 NSEvent* event = [NSEvent keyEventWithType:NSKeyDown
347 location:NSZeroPoint
348 modifierFlags:NSControlKeyMask
349 timestamp:0.0
350 windowNumber:0
351 context:nil
352 characters:@""
353 charactersIgnoringModifiers:@""
354 isARepeat:NO
355 keyCode:kVK_Tab];
356 PanelBrowserWindowCocoa* native_window =
357 static_cast<PanelBrowserWindowCocoa*>(panel->native_panel());
358 [BrowserWindowUtils handleKeyboardEvent:event
359 inWindow:[native_window->controller_ window]];
360 ClosePanelAndWait(panel);
361 }
362
363 // Verify that the theme provider is properly plumbed through.
364 TEST_F(PanelBrowserWindowCocoaTest, ThemeProvider) {
365 Panel* panel = CreateTestPanel("Test Panel");
366 ASSERT_TRUE(panel);
367
368 PanelBrowserWindowCocoa* native_window =
369 static_cast<PanelBrowserWindowCocoa*>(panel->native_panel());
370 ASSERT_TRUE(native_window);
371 EXPECT_TRUE(NULL != [[native_window->controller_ window] themeProvider]);
372 ClosePanelAndWait(panel);
373 }
374
375 TEST_F(PanelBrowserWindowCocoaTest, SetTitle) {
376 NSString *appName = @"Test Panel";
377 Panel* panel = CreateTestPanel(base::SysNSStringToUTF8(appName));
378 ASSERT_TRUE(panel);
379
380 PanelBrowserWindowCocoa* native_window =
381 static_cast<PanelBrowserWindowCocoa*>(panel->native_panel());
382 ASSERT_TRUE(native_window);
383 NSString* previousTitle = [[native_window->controller_ window] title];
384 EXPECT_NSNE(appName, previousTitle);
385 [native_window->controller_ updateTitleBar];
386 chrome::testing::NSRunLoopRunAllPending();
387 NSString* currentTitle = [[native_window->controller_ window] title];
388 EXPECT_NSEQ(appName, currentTitle);
389 EXPECT_NSNE(currentTitle, previousTitle);
390 ClosePanelAndWait(panel);
391 }
392
393 TEST_F(PanelBrowserWindowCocoaTest, ActivatePanel) {
394 Panel* panel = CreateTestPanel("Test Panel");
395 Panel* panel2 = CreateTestPanel("Test Panel 2");
396 ASSERT_TRUE(panel);
397 ASSERT_TRUE(panel2);
398
399 PanelBrowserWindowCocoa* native_window =
400 static_cast<PanelBrowserWindowCocoa*>(panel->native_panel());
401 ASSERT_TRUE(native_window);
402 PanelBrowserWindowCocoa* native_window2 =
403 static_cast<PanelBrowserWindowCocoa*>(panel2->native_panel());
404 ASSERT_TRUE(native_window2);
405
406 // No one has a good answer why but apparently windows can't take keyboard
407 // focus outside of interactive UI tests. BrowserWindowController uses the
408 // same way of testing this.
409 native_window->ActivatePanel();
410 NSWindow* frontmostWindow = [[NSApp orderedWindows] objectAtIndex:0];
411 EXPECT_NSEQ(frontmostWindow, [native_window->controller_ window]);
412
413 native_window2->ActivatePanel();
414 frontmostWindow = [[NSApp orderedWindows] objectAtIndex:0];
415 EXPECT_NSEQ(frontmostWindow, [native_window2->controller_ window]);
416
417 ClosePanelAndWait(panel);
418 ClosePanelAndWait(panel2);
419 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/panels/panel_browser_window_cocoa.mm ('k') | chrome/browser/ui/panels/panel_browser_window_gtk.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698