find_bar_cocoa_controller.mm revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 <Cocoa/Cocoa.h> 6 7#include "base/auto_reset.h" 8#include "base/mac/bundle_locations.h" 9#include "base/mac/mac_util.h" 10#include "base/strings/sys_string_conversions.h" 11#include "grit/theme_resources.h" 12#include "grit/ui_resources.h" 13#include "chrome/browser/ui/browser_finder.h" 14#include "chrome/browser/ui/browser_window.h" 15#include "chrome/browser/ui/cocoa/browser_window_controller.h" 16#import "chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h" 17#import "chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h" 18#import "chrome/browser/ui/cocoa/find_bar/find_bar_text_field.h" 19#import "chrome/browser/ui/cocoa/find_bar/find_bar_text_field_cell.h" 20#import "chrome/browser/ui/cocoa/image_button_cell.h" 21#import "chrome/browser/ui/cocoa/nsview_additions.h" 22#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h" 23#include "chrome/browser/ui/find_bar/find_bar_controller.h" 24#include "chrome/browser/ui/find_bar/find_tab_helper.h" 25#include "content/public/browser/render_view_host.h" 26#include "content/public/browser/web_contents.h" 27#include "content/public/browser/web_contents_view.h" 28#import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h" 29#import "ui/base/cocoa/find_pasteboard.h" 30#import "ui/base/cocoa/focus_tracker.h" 31 32using content::NativeWebKeyboardEvent; 33 34const float kFindBarOpenDuration = 0.2; 35const float kFindBarCloseDuration = 0.15; 36const float kFindBarMoveDuration = 0.15; 37const float kRightEdgeOffset = 25; 38 39 40@interface FindBarCocoaController (PrivateMethods) <NSAnimationDelegate> 41// Returns the appropriate frame for a hidden find bar. 42- (NSRect)hiddenFindBarFrame; 43 44// Animates the given |view| to the given |endFrame| within |duration| seconds. 45// Returns a new NSViewAnimation. 46- (NSViewAnimation*)createAnimationForView:(NSView*)view 47 toFrame:(NSRect)endFrame 48 duration:(float)duration; 49 50// Sets the frame of |findBarView_|. |duration| is ignored if |animate| is NO. 51- (void)setFindBarFrame:(NSRect)endFrame 52 animate:(BOOL)animate 53 duration:(float)duration; 54 55// Returns the horizontal position the FindBar should use in order to avoid 56// overlapping with the current find result, if there's one. 57- (float)findBarHorizontalPosition; 58 59// Adjusts the horizontal position if necessary to avoid overlapping with the 60// current find result. 61- (void)moveFindBarIfNecessary:(BOOL)animate; 62 63// Puts |text| into the find bar and enables the buttons, but doesn't start a 64// new search for |text|. 65- (void)prepopulateText:(NSString*)text; 66 67// Clears the find results for all tabs in browser associated with this find 68// bar. If |suppressPboardUpdateActions_| is true then the current tab is not 69// cleared. 70- (void)clearFindResultsForCurrentBrowser; 71 72- (BrowserWindowController*)browserWindowController; 73@end 74 75@implementation FindBarCocoaController 76 77@synthesize findBarView = findBarView_; 78 79- (id)initWithBrowser:(Browser*)browser { 80 if ((self = [super initWithNibName:@"FindBar" 81 bundle:base::mac::FrameworkBundle()])) { 82 [[NSNotificationCenter defaultCenter] 83 addObserver:self 84 selector:@selector(findPboardUpdated:) 85 name:kFindPasteboardChangedNotification 86 object:[FindPasteboard sharedInstance]]; 87 browser_ = browser; 88 } 89 return self; 90} 91 92- (void)dealloc { 93 // All animations should have been explicitly stopped before a tab is closed. 94 DCHECK(!showHideAnimation_.get()); 95 DCHECK(!moveAnimation_.get()); 96 [[NSNotificationCenter defaultCenter] removeObserver:self]; 97 [super dealloc]; 98} 99 100- (void)setFindBarBridge:(FindBarBridge*)findBarBridge { 101 DCHECK(!findBarBridge_); // should only be called once. 102 findBarBridge_ = findBarBridge; 103} 104 105- (void)awakeFromNib { 106 [[closeButton_ cell] setImageID:IDR_CLOSE_1 107 forButtonState:image_button_cell::kDefaultState]; 108 [[closeButton_ cell] setImageID:IDR_CLOSE_1_H 109 forButtonState:image_button_cell::kHoverState]; 110 [[closeButton_ cell] setImageID:IDR_CLOSE_1_P 111 forButtonState:image_button_cell::kPressedState]; 112 [[closeButton_ cell] setImageID:IDR_CLOSE_1 113 forButtonState:image_button_cell::kDisabledState]; 114 115 [findBarView_ setFrame:[self hiddenFindBarFrame]]; 116 defaultWidth_ = NSWidth([findBarView_ frame]); 117 118 [self prepopulateText:[[FindPasteboard sharedInstance] findText]]; 119} 120 121- (IBAction)close:(id)sender { 122 if (findBarBridge_) 123 findBarBridge_->GetFindBarController()->EndFindSession( 124 FindBarController::kKeepSelectionOnPage, 125 FindBarController::kKeepResultsInFindBox); 126 127 // Turn off hover state on close button else the button will remain 128 // hovered when we bring the find bar back up. 129 // crbug.com/227424 130 [[closeButton_ cell] setIsMouseInside:NO]; 131} 132 133- (IBAction)previousResult:(id)sender { 134 if (findBarBridge_) { 135 FindTabHelper* findTabHelper = FindTabHelper::FromWebContents( 136 findBarBridge_->GetFindBarController()->web_contents()); 137 findTabHelper->StartFinding( 138 base::SysNSStringToUTF16([findText_ stringValue]), 139 false, false); 140 } 141} 142 143- (IBAction)nextResult:(id)sender { 144 if (findBarBridge_) { 145 FindTabHelper* findTabHelper = FindTabHelper::FromWebContents( 146 findBarBridge_->GetFindBarController()->web_contents()); 147 findTabHelper->StartFinding( 148 base::SysNSStringToUTF16([findText_ stringValue]), 149 true, false); 150 } 151} 152 153- (void)findPboardUpdated:(NSNotification*)notification { 154 if (!suppressPboardUpdateActions_) 155 [self prepopulateText:[[FindPasteboard sharedInstance] findText]]; 156 [self clearFindResultsForCurrentBrowser]; 157} 158 159- (void)positionFindBarViewAtMaxY:(CGFloat)maxY maxWidth:(CGFloat)maxWidth { 160 NSView* containerView = [self view]; 161 CGFloat containerHeight = NSHeight([containerView frame]); 162 CGFloat containerWidth = std::min(maxWidth, defaultWidth_); 163 164 // Adjust where we'll actually place the find bar. 165 maxY += [containerView cr_lineWidth]; 166 maxY_ = maxY; 167 CGFloat x = [self findBarHorizontalPosition]; 168 NSRect newFrame = NSMakeRect(x, maxY - containerHeight, 169 containerWidth, containerHeight); 170 171 if (moveAnimation_.get() != nil) { 172 NSRect frame = [containerView frame]; 173 [moveAnimation_ stopAnimation]; 174 // Restore to the X position before the animation was stopped. The Y 175 // position is immediately adjusted. 176 frame.origin.y = newFrame.origin.y; 177 [containerView setFrame:frame]; 178 moveAnimation_.reset([self createAnimationForView:containerView 179 toFrame:newFrame 180 duration:kFindBarMoveDuration]); 181 } else { 182 [containerView setFrame:newFrame]; 183 } 184} 185 186- (BOOL)isOffTheRecordProfile { 187 return browser_ && browser_->profile() && 188 browser_->profile()->IsOffTheRecord(); 189} 190 191// NSControl delegate method. 192- (void)controlTextDidChange:(NSNotification*)aNotification { 193 if (!findBarBridge_) 194 return; 195 196 content::WebContents* webContents = 197 findBarBridge_->GetFindBarController()->web_contents(); 198 if (!webContents) 199 return; 200 FindTabHelper* findTabHelper = FindTabHelper::FromWebContents(webContents); 201 202 NSString* findText = [findText_ stringValue]; 203 if (![self isOffTheRecordProfile]) { 204 base::AutoReset<BOOL> suppressReset(&suppressPboardUpdateActions_, YES); 205 [[FindPasteboard sharedInstance] setFindText:findText]; 206 } 207 208 if ([findText length] > 0) { 209 findTabHelper-> 210 StartFinding(base::SysNSStringToUTF16(findText), true, false); 211 } else { 212 // The textbox is empty so we reset. 213 findTabHelper->StopFinding(FindBarController::kClearSelectionOnPage); 214 [self updateUIForFindResult:findTabHelper->find_result() 215 withText:base::string16()]; 216 } 217} 218 219// NSControl delegate method 220- (BOOL)control:(NSControl*)control 221 textView:(NSTextView*)textView 222 doCommandBySelector:(SEL)command { 223 if (command == @selector(insertNewline:)) { 224 // Pressing Return 225 NSEvent* event = [NSApp currentEvent]; 226 227 if ([event modifierFlags] & NSShiftKeyMask) 228 [previousButton_ performClick:nil]; 229 else 230 [nextButton_ performClick:nil]; 231 232 return YES; 233 } else if (command == @selector(insertLineBreak:)) { 234 // Pressing Ctrl-Return 235 if (findBarBridge_) { 236 findBarBridge_->GetFindBarController()->EndFindSession( 237 FindBarController::kActivateSelectionOnPage, 238 FindBarController::kClearResultsInFindBox); 239 } 240 return YES; 241 } else if (command == @selector(pageUp:) || 242 command == @selector(pageUpAndModifySelection:) || 243 command == @selector(scrollPageUp:) || 244 command == @selector(pageDown:) || 245 command == @selector(pageDownAndModifySelection:) || 246 command == @selector(scrollPageDown:) || 247 command == @selector(scrollToBeginningOfDocument:) || 248 command == @selector(scrollToEndOfDocument:) || 249 command == @selector(moveUp:) || 250 command == @selector(moveDown:)) { 251 content::WebContents* web_contents = 252 findBarBridge_->GetFindBarController()->web_contents(); 253 if (!web_contents) 254 return NO; 255 256 // Sanity-check to make sure we got a keyboard event. 257 NSEvent* event = [NSApp currentEvent]; 258 if ([event type] != NSKeyDown && [event type] != NSKeyUp) 259 return NO; 260 261 // Forward the event to the renderer. 262 // TODO(rohitrao): Should this call -[BaseView keyEvent:]? Is there code in 263 // that function that we want to keep or avoid? Calling 264 // |ForwardKeyboardEvent()| directly ignores edit commands, which breaks 265 // cmd-up/down if we ever decide to include |moveToBeginningOfDocument:| in 266 // the list above. 267 content::RenderViewHost* render_view_host = 268 web_contents->GetRenderViewHost(); 269 render_view_host->ForwardKeyboardEvent(NativeWebKeyboardEvent(event)); 270 return YES; 271 } 272 273 return NO; 274} 275 276// Methods from FindBar 277- (void)showFindBar:(BOOL)animate { 278 // Save the currently-focused view. |findBarView_| is in the view 279 // hierarchy by now. showFindBar can be called even when the 280 // findbar is already open, so do not overwrite an already saved 281 // view. 282 if (!focusTracker_.get()) 283 focusTracker_.reset( 284 [[FocusTracker alloc] initWithWindow:[findBarView_ window]]); 285 286 // The browser window might have changed while the FindBar was hidden. 287 // Update its position now. 288 [[self browserWindowController] layoutSubviews]; 289 290 // Move to the correct horizontal position first, to prevent the FindBar 291 // from jumping around when switching tabs. 292 // Prevent jumping while the FindBar is animating (hiding, then showing) too. 293 if (![self isFindBarVisible]) 294 [self moveFindBarIfNecessary:NO]; 295 296 // Animate the view into place. 297 NSRect frame = [findBarView_ frame]; 298 frame.origin = NSZeroPoint; 299 [self setFindBarFrame:frame animate:animate duration:kFindBarOpenDuration]; 300} 301 302- (void)hideFindBar:(BOOL)animate { 303 NSRect frame = [self hiddenFindBarFrame]; 304 [self setFindBarFrame:frame animate:animate duration:kFindBarCloseDuration]; 305} 306 307- (void)stopAnimation { 308 if (showHideAnimation_.get()) { 309 [showHideAnimation_ stopAnimation]; 310 showHideAnimation_.reset(nil); 311 } 312 if (moveAnimation_.get()) { 313 [moveAnimation_ stopAnimation]; 314 moveAnimation_.reset(nil); 315 } 316} 317 318- (void)setFocusAndSelection { 319 [[findText_ window] makeFirstResponder:findText_]; 320 321 // Enable the buttons if the find text is non-empty. 322 BOOL buttonsEnabled = ([[findText_ stringValue] length] > 0) ? YES : NO; 323 [previousButton_ setEnabled:buttonsEnabled]; 324 [nextButton_ setEnabled:buttonsEnabled]; 325} 326 327- (void)restoreSavedFocus { 328 if (!(focusTracker_.get() && 329 [focusTracker_ restoreFocusInWindow:[findBarView_ window]])) { 330 // Fall back to giving focus to the tab contents. 331 findBarBridge_->GetFindBarController()->web_contents()->GetView()->Focus(); 332 } 333 focusTracker_.reset(nil); 334} 335 336- (void)setFindText:(NSString*)findText 337 selectedRange:(const NSRange&)selectedRange { 338 [findText_ setStringValue:findText]; 339 340 if (![self isOffTheRecordProfile]) { 341 // Make sure the text in the find bar always ends up in the find pasteboard 342 // (and, via notifications, in the other find bars too). 343 base::AutoReset<BOOL> suppressReset(&suppressPboardUpdateActions_, YES); 344 [[FindPasteboard sharedInstance] setFindText:findText]; 345 } 346 347 NSText* editor = [findText_ currentEditor]; 348 if (selectedRange.location != NSNotFound) 349 [editor setSelectedRange:selectedRange]; 350} 351 352- (NSString*)findText { 353 return [findText_ stringValue]; 354} 355 356- (NSRange)selectedRange { 357 NSText* editor = [findText_ currentEditor]; 358 return (editor != nil) ? [editor selectedRange] : NSMakeRange(NSNotFound, 0); 359} 360 361- (NSString*)matchCountText { 362 return [[findText_ findBarTextFieldCell] resultsString]; 363} 364 365- (void)updateFindBarForChangedWebContents { 366 content::WebContents* contents = 367 findBarBridge_->GetFindBarController()->web_contents(); 368 if (!contents) 369 return; 370 FindTabHelper* findTabHelper = FindTabHelper::FromWebContents(contents); 371 372 // If the find UI is visible but the results are cleared then also clear 373 // the results label and update the buttons. 374 if (findTabHelper->find_ui_active() && 375 findTabHelper->previous_find_text().empty()) { 376 BOOL buttonsEnabled = [[findText_ stringValue] length] > 0 ? YES : NO; 377 [previousButton_ setEnabled:buttonsEnabled]; 378 [nextButton_ setEnabled:buttonsEnabled]; 379 [[findText_ findBarTextFieldCell] clearResults]; 380 } 381} 382 383- (void)clearResults:(const FindNotificationDetails&)results { 384 // Just call updateUIForFindResult, which will take care of clearing 385 // the search text and the results label. 386 [self updateUIForFindResult:results withText:base::string16()]; 387} 388 389- (void)updateUIForFindResult:(const FindNotificationDetails&)result 390 withText:(const base::string16&)findText { 391 // If we don't have any results and something was passed in, then 392 // that means someone pressed Cmd-G while the Find box was 393 // closed. In that case we need to repopulate the Find box with what 394 // was passed in. 395 if ([[findText_ stringValue] length] == 0 && !findText.empty()) { 396 [findText_ setStringValue:base::SysUTF16ToNSString(findText)]; 397 [findText_ selectText:self]; 398 } 399 400 // Make sure Find Next and Find Previous are enabled if we found any matches. 401 BOOL buttonsEnabled = result.number_of_matches() > 0; 402 [previousButton_ setEnabled:buttonsEnabled]; 403 [nextButton_ setEnabled:buttonsEnabled]; 404 405 // Update the results label. 406 BOOL validRange = result.active_match_ordinal() != -1 && 407 result.number_of_matches() != -1; 408 NSString* searchString = [findText_ stringValue]; 409 if ([searchString length] > 0 && validRange) { 410 [[findText_ findBarTextFieldCell] 411 setActiveMatch:result.active_match_ordinal() 412 of:result.number_of_matches()]; 413 } else { 414 // If there was no text entered, we don't show anything in the results area. 415 [[findText_ findBarTextFieldCell] clearResults]; 416 } 417 418 [findText_ resetFieldEditorFrameIfNeeded]; 419 420 // If we found any results, reset the focus tracker, so we always 421 // restore focus to the tab contents. 422 if (result.number_of_matches() > 0) 423 focusTracker_.reset(nil); 424 425 // Adjust the FindBar position, even when there are no matches (so that it 426 // goes back to the default position, if required). 427 [self moveFindBarIfNecessary:[self isFindBarVisible]]; 428} 429 430- (BOOL)isFindBarVisible { 431 // Find bar is visible if any part of it is on the screen. 432 return NSIntersectsRect([[self view] bounds], [findBarView_ frame]); 433} 434 435- (BOOL)isFindBarAnimating { 436 return (showHideAnimation_.get() != nil) || (moveAnimation_.get() != nil); 437} 438 439// NSAnimation delegate methods. 440- (void)animationDidEnd:(NSAnimation*)animation { 441 // Autorelease the animations (cannot use release because the animation object 442 // is still on the stack. 443 if (animation == showHideAnimation_.get()) { 444 [showHideAnimation_.release() autorelease]; 445 } else if (animation == moveAnimation_.get()) { 446 [moveAnimation_.release() autorelease]; 447 } else { 448 NOTREACHED(); 449 } 450 451 // If the find bar is not visible, make it actually hidden, so it'll no longer 452 // respond to key events. 453 [findBarView_ setHidden:![self isFindBarVisible]]; 454 [[self browserWindowController] onFindBarVisibilityChanged]; 455} 456 457- (gfx::Point)findBarWindowPosition { 458 gfx::Rect viewRect(NSRectToCGRect([[self view] frame])); 459 // Convert Cocoa coordinates (Y growing up) to Y growing down. 460 // Offset from |maxY_|, which represents the content view's top, instead 461 // of from the superview, which represents the whole browser window. 462 viewRect.set_y(maxY_ - viewRect.bottom()); 463 return viewRect.origin(); 464} 465 466- (int)findBarWidth { 467 return NSWidth([[self view] frame]); 468} 469 470@end 471 472@implementation FindBarCocoaController (PrivateMethods) 473 474- (NSRect)hiddenFindBarFrame { 475 NSRect frame = [findBarView_ frame]; 476 NSRect containerBounds = [[self view] bounds]; 477 frame.origin = NSMakePoint(NSMinX(containerBounds), NSMaxY(containerBounds)); 478 return frame; 479} 480 481- (NSViewAnimation*)createAnimationForView:(NSView*)view 482 toFrame:(NSRect)endFrame 483 duration:(float)duration { 484 NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: 485 view, NSViewAnimationTargetKey, 486 [NSValue valueWithRect:endFrame], NSViewAnimationEndFrameKey, nil]; 487 488 NSViewAnimation* animation = 489 [[NSViewAnimation alloc] 490 initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]]; 491 [animation gtm_setDuration:duration 492 eventMask:NSLeftMouseUpMask]; 493 [animation setDelegate:self]; 494 [animation startAnimation]; 495 return animation; 496} 497 498- (void)setFindBarFrame:(NSRect)endFrame 499 animate:(BOOL)animate 500 duration:(float)duration { 501 // Save the current frame. 502 NSRect startFrame = [findBarView_ frame]; 503 504 // Stop any existing animations. 505 [showHideAnimation_ stopAnimation]; 506 507 if (!animate) { 508 [findBarView_ setFrame:endFrame]; 509 [findBarView_ setHidden:![self isFindBarVisible]]; 510 [[self browserWindowController] onFindBarVisibilityChanged]; 511 showHideAnimation_.reset(nil); 512 return; 513 } 514 515 // If animating, ensure that the find bar is not hidden. Hidden status will be 516 // updated at the end of the animation. 517 [findBarView_ setHidden:NO]; 518 //[[self browserWindowController] onFindBarVisibilityChanged]; 519 520 // Reset the frame to what was saved above. 521 [findBarView_ setFrame:startFrame]; 522 523 [[self browserWindowController] onFindBarVisibilityChanged]; 524 525 showHideAnimation_.reset([self createAnimationForView:findBarView_ 526 toFrame:endFrame 527 duration:duration]); 528} 529 530- (float)findBarHorizontalPosition { 531 // Get the rect of the FindBar. 532 NSView* view = [self view]; 533 NSRect frame = [view frame]; 534 gfx::Rect viewRect(NSRectToCGRect(frame)); 535 536 if (!findBarBridge_ || !findBarBridge_->GetFindBarController()) 537 return frame.origin.x; 538 content::WebContents* contents = 539 findBarBridge_->GetFindBarController()->web_contents(); 540 if (!contents) 541 return frame.origin.x; 542 543 // Get the size of the container. 544 gfx::Rect containerRect(contents->GetView()->GetContainerSize()); 545 546 // Position the FindBar on the top right corner. 547 viewRect.set_x( 548 containerRect.width() - viewRect.width() - kRightEdgeOffset); 549 // Convert from Cocoa coordinates (Y growing up) to Y growing down. 550 // Notice that the view frame's Y offset is relative to the whole window, 551 // while GetLocationForFindbarView() expects it relative to the 552 // content's boundaries. |maxY_| has the correct placement in Cocoa coords, 553 // so we just have to invert the Y coordinate. 554 viewRect.set_y(maxY_ - viewRect.bottom()); 555 556 // Get the rect of the current find result, if there is one. 557 const FindNotificationDetails& findResult = 558 FindTabHelper::FromWebContents(contents)->find_result(); 559 if (findResult.number_of_matches() == 0) 560 return viewRect.x(); 561 gfx::Rect selectionRect(findResult.selection_rect()); 562 563 // Adjust |view_rect| to avoid the |selection_rect| within |container_rect|. 564 gfx::Rect newPos = FindBarController::GetLocationForFindbarView( 565 viewRect, containerRect, selectionRect); 566 567 return newPos.x(); 568} 569 570- (void)moveFindBarIfNecessary:(BOOL)animate { 571 // Don't animate during tests. 572 if (FindBarBridge::disable_animations_during_testing_) 573 animate = NO; 574 575 NSView* view = [self view]; 576 NSRect frame = [view frame]; 577 float x = [self findBarHorizontalPosition]; 578 if (frame.origin.x == x) 579 return; 580 581 if (animate) { 582 [moveAnimation_ stopAnimation]; 583 // Restore to the position before the animation was stopped. 584 [view setFrame:frame]; 585 frame.origin.x = x; 586 moveAnimation_.reset([self createAnimationForView:view 587 toFrame:frame 588 duration:kFindBarMoveDuration]); 589 } else { 590 frame.origin.x = x; 591 [view setFrame:frame]; 592 } 593} 594 595- (void)prepopulateText:(NSString*)text { 596 [self setFindText:text selectedRange:NSMakeRange(NSNotFound, 0)]; 597 598 // Has to happen after |ClearResults()| above. 599 BOOL buttonsEnabled = [text length] > 0 ? YES : NO; 600 [previousButton_ setEnabled:buttonsEnabled]; 601 [nextButton_ setEnabled:buttonsEnabled]; 602} 603 604- (void)clearFindResultsForCurrentBrowser { 605 if (!browser_) 606 return; 607 608 content::WebContents* activeWebContents = 609 findBarBridge_->GetFindBarController()->web_contents(); 610 611 TabStripModel* tabStripModel = browser_->tab_strip_model(); 612 for (int i = 0; i < tabStripModel->count(); ++i) { 613 content::WebContents* webContents = tabStripModel->GetWebContentsAt(i); 614 if (suppressPboardUpdateActions_ && activeWebContents == webContents) 615 continue; 616 FindTabHelper* findTabHelper = 617 FindTabHelper::FromWebContents(webContents); 618 findTabHelper->StopFinding(FindBarController::kClearSelectionOnPage); 619 findBarBridge_->ClearResults(findTabHelper->find_result()); 620 } 621} 622 623- (BrowserWindowController*)browserWindowController { 624 if (!browser_) 625 return nil; 626 return [BrowserWindowController 627 browserWindowControllerForWindow:browser_->window()->GetNativeWindow()]; 628} 629 630@end 631