OLD | NEW |
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 <Cocoa/Cocoa.h> | 5 #import <Cocoa/Cocoa.h> |
6 | 6 |
7 #import "base/mac/scoped_nsobject.h" | 7 #import "base/mac/scoped_nsobject.h" |
8 #include "base/prefs/pref_service.h" | 8 #include "base/prefs/pref_service.h" |
9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
10 #include "chrome/app/chrome_command_ids.h" | 10 #include "chrome/app/chrome_command_ids.h" |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 initWithCommands:browser()->command_controller()->command_updater() | 91 initWithCommands:browser()->command_controller()->command_updater() |
92 profile:profile() | 92 profile:profile() |
93 browser:browser() | 93 browser:browser() |
94 resizeDelegate:resizeDelegate_.get()]); | 94 resizeDelegate:resizeDelegate_.get()]); |
95 EXPECT_TRUE([bar_ view]); | 95 EXPECT_TRUE([bar_ view]); |
96 NSView* parent = [test_window() contentView]; | 96 NSView* parent = [test_window() contentView]; |
97 [parent addSubview:[bar_ view]]; | 97 [parent addSubview:[bar_ view]]; |
98 } | 98 } |
99 | 99 |
100 void TearDown() override { | 100 void TearDown() override { |
101 bar_.reset(); // browser() must outlive the ToolbarController. | 101 // Releasing ToolbarController doesn't actually free it at this point, since |
| 102 // the NSViewController retains a reference to it from the nib loading. |
| 103 // As browser() is released in the superclass TearDown, call |
| 104 // -[ToolbarController browserWillBeDestroyed] to prevent a use after free |
| 105 // issue on the |browser_| pointer in LocationBarViewMac when |
| 106 // ToolbarController is actually freed (some time after this method is run). |
| 107 [bar_ browserWillBeDestroyed]; |
| 108 bar_.reset(); |
102 CocoaProfileTest::TearDown(); | 109 CocoaProfileTest::TearDown(); |
103 } | 110 } |
104 | 111 |
105 // Make sure the enabled state of the view is the same as the corresponding | 112 // Make sure the enabled state of the view is the same as the corresponding |
106 // command in the updater. The views are in the declaration order of outlets. | 113 // command in the updater. The views are in the declaration order of outlets. |
107 void CompareState(CommandUpdater* updater, NSArray* views) { | 114 void CompareState(CommandUpdater* updater, NSArray* views) { |
108 EXPECT_EQ(updater->IsCommandEnabled(IDC_BACK), | 115 EXPECT_EQ(updater->IsCommandEnabled(IDC_BACK), |
109 [[views objectAtIndex:kBackIndex] isEnabled] ? true : false); | 116 [[views objectAtIndex:kBackIndex] isEnabled] ? true : false); |
110 EXPECT_EQ(updater->IsCommandEnabled(IDC_FORWARD), | 117 EXPECT_EQ(updater->IsCommandEnabled(IDC_FORWARD), |
111 [[views objectAtIndex:kForwardIndex] isEnabled] ? true : false); | 118 [[views objectAtIndex:kForwardIndex] isEnabled] ? true : false); |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 TEST_F(ToolbarControllerTest, TranslateBubblePoint) { | 346 TEST_F(ToolbarControllerTest, TranslateBubblePoint) { |
340 const NSPoint translatePoint = [bar_ translateBubblePoint]; | 347 const NSPoint translatePoint = [bar_ translateBubblePoint]; |
341 const NSRect barFrame = | 348 const NSRect barFrame = |
342 [[bar_ view] convertRect:[[bar_ view] bounds] toView:nil]; | 349 [[bar_ view] convertRect:[[bar_ view] bounds] toView:nil]; |
343 EXPECT_TRUE(NSPointInRect(translatePoint, barFrame)); | 350 EXPECT_TRUE(NSPointInRect(translatePoint, barFrame)); |
344 } | 351 } |
345 | 352 |
346 TEST_F(ToolbarControllerTest, HoverButtonForEvent) { | 353 TEST_F(ToolbarControllerTest, HoverButtonForEvent) { |
347 base::scoped_nsobject<HitView> view( | 354 base::scoped_nsobject<HitView> view( |
348 [[HitView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)]); | 355 [[HitView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)]); |
| 356 NSView* toolbarView = [bar_ view]; |
349 [bar_ setView:view]; | 357 [bar_ setView:view]; |
350 NSEvent* event = [NSEvent mouseEventWithType:NSMouseMoved | 358 NSEvent* event = [NSEvent mouseEventWithType:NSMouseMoved |
351 location:NSMakePoint(10,10) | 359 location:NSMakePoint(10,10) |
352 modifierFlags:0 | 360 modifierFlags:0 |
353 timestamp:0 | 361 timestamp:0 |
354 windowNumber:0 | 362 windowNumber:0 |
355 context:nil | 363 context:nil |
356 eventNumber:0 | 364 eventNumber:0 |
357 clickCount:0 | 365 clickCount:0 |
358 pressure:0.0]; | 366 pressure:0.0]; |
359 | 367 |
360 // NOT a match. | 368 // NOT a match. |
361 [view setHitTestReturn:bar_.get()]; | 369 [view setHitTestReturn:bar_.get()]; |
362 EXPECT_FALSE([bar_ hoverButtonForEvent:event]); | 370 EXPECT_FALSE([bar_ hoverButtonForEvent:event]); |
363 | 371 |
364 // Not yet... | 372 // Not yet... |
365 base::scoped_nsobject<NSButton> button([[NSButton alloc] init]); | 373 base::scoped_nsobject<NSButton> button([[NSButton alloc] init]); |
366 [view setHitTestReturn:button]; | 374 [view setHitTestReturn:button]; |
367 EXPECT_FALSE([bar_ hoverButtonForEvent:event]); | 375 EXPECT_FALSE([bar_ hoverButtonForEvent:event]); |
368 | 376 |
369 // Now! | 377 // Now! |
370 base::scoped_nsobject<ImageButtonCell> cell( | 378 base::scoped_nsobject<ImageButtonCell> cell( |
371 [[ImageButtonCell alloc] init]); | 379 [[ImageButtonCell alloc] init]); |
372 [button setCell:cell.get()]; | 380 [button setCell:cell.get()]; |
373 EXPECT_TRUE([bar_ hoverButtonForEvent:nil]); | 381 EXPECT_TRUE([bar_ hoverButtonForEvent:nil]); |
| 382 |
| 383 // Restore the original view so that |
| 384 // -[ToolbarController browserWillBeDestroyed] will run correctly. |
| 385 [bar_ setView:toolbarView]; |
374 } | 386 } |
375 | 387 |
376 class BrowserRemovedObserver : public chrome::BrowserListObserver { | 388 class BrowserRemovedObserver : public chrome::BrowserListObserver { |
377 public: | 389 public: |
378 BrowserRemovedObserver() { BrowserList::AddObserver(this); } | 390 BrowserRemovedObserver() { BrowserList::AddObserver(this); } |
379 ~BrowserRemovedObserver() override { BrowserList::RemoveObserver(this); } | 391 ~BrowserRemovedObserver() override { BrowserList::RemoveObserver(this); } |
380 void WaitUntilBrowserRemoved() { run_loop_.Run(); } | 392 void WaitUntilBrowserRemoved() { run_loop_.Run(); } |
381 void OnBrowserRemoved(Browser* browser) override { run_loop_.Quit(); } | 393 void OnBrowserRemoved(Browser* browser) override { run_loop_.Quit(); } |
382 | 394 |
383 private: | 395 private: |
384 base::RunLoop run_loop_; | 396 base::RunLoop run_loop_; |
385 | 397 |
386 DISALLOW_COPY_AND_ASSIGN(BrowserRemovedObserver); | 398 DISALLOW_COPY_AND_ASSIGN(BrowserRemovedObserver); |
387 }; | 399 }; |
388 | 400 |
389 // Test that ToolbarController can be destroyed after the Browser. | |
390 // This can happen because the ToolbarController is retained by both the | |
391 // BrowserWindowController and -[ToolbarController view], the latter of which is | |
392 // autoreleased. | |
393 TEST_F(ToolbarControllerTest, ToolbarDestroyedAfterBrowser) { | |
394 BrowserRemovedObserver observer; | |
395 // This is normally called by BrowserWindowController, but since |bar_| is not | |
396 // owned by one, call it here. | |
397 [bar_ browserWillBeDestroyed]; | |
398 CloseBrowserWindow(); | |
399 observer.WaitUntilBrowserRemoved(); | |
400 // |bar_| is released in TearDown(). | |
401 } | |
402 | |
403 } // namespace | 401 } // namespace |
OLD | NEW |