1 // Copyright (c) 2011 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/cocoa/location_bar/location_bar_view_mac.h" 6 7 #include "base/stl_util-inl.h" 8 #include "base/string_util.h" 9 #include "base/sys_string_conversions.h" 10 #include "base/utf_string_conversions.h" 11 #include "chrome/app/chrome_command_ids.h" 12 #include "chrome/browser/alternate_nav_url_fetcher.h" 13 #import "chrome/browser/app_controller_mac.h" 14 #import "chrome/browser/autocomplete/autocomplete_edit_view_mac.h" 15 #import "chrome/browser/autocomplete/autocomplete_popup_model.h" 16 #include "chrome/browser/command_updater.h" 17 #include "chrome/browser/content_setting_bubble_model.h" 18 #include "chrome/browser/content_setting_image_model.h" 19 #include "chrome/browser/defaults.h" 20 #include "chrome/browser/extensions/extension_browser_event_router.h" 21 #include "chrome/browser/extensions/extension_service.h" 22 #include "chrome/browser/extensions/extension_tabs_module.h" 23 #include "chrome/browser/instant/instant_controller.h" 24 #include "chrome/browser/profiles/profile.h" 25 #include "chrome/browser/search_engines/template_url.h" 26 #include "chrome/browser/search_engines/template_url_model.h" 27 #include "chrome/browser/ui/browser_list.h" 28 #import "chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h" 29 #include "chrome/browser/ui/cocoa/event_utils.h" 30 #import "chrome/browser/ui/cocoa/extensions/extension_action_context_menu.h" 31 #import "chrome/browser/ui/cocoa/extensions/extension_popup_controller.h" 32 #import "chrome/browser/ui/cocoa/first_run_bubble_controller.h" 33 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h" 34 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.h" 35 #import "chrome/browser/ui/cocoa/location_bar/content_setting_decoration.h" 36 #import "chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.h" 37 #import "chrome/browser/ui/cocoa/location_bar/keyword_hint_decoration.h" 38 #import "chrome/browser/ui/cocoa/location_bar/location_icon_decoration.h" 39 #import "chrome/browser/ui/cocoa/location_bar/page_action_decoration.h" 40 #import "chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.h" 41 #import "chrome/browser/ui/cocoa/location_bar/star_decoration.h" 42 #include "chrome/browser/ui/omnibox/location_bar_util.h" 43 #include "chrome/common/extensions/extension.h" 44 #include "chrome/common/extensions/extension_action.h" 45 #include "chrome/common/extensions/extension_resource.h" 46 #include "chrome/common/pref_names.h" 47 #include "content/browser/tab_contents/navigation_entry.h" 48 #include "content/browser/tab_contents/tab_contents.h" 49 #include "content/common/notification_service.h" 50 #include "grit/generated_resources.h" 51 #include "grit/theme_resources.h" 52 #include "net/base/net_util.h" 53 #include "skia/ext/skia_utils_mac.h" 54 #include "third_party/skia/include/core/SkBitmap.h" 55 #include "ui/base/l10n/l10n_util_mac.h" 56 #include "ui/base/resource/resource_bundle.h" 57 58 namespace { 59 60 // Vertical space between the bottom edge of the location_bar and the first run 61 // bubble arrow point. 62 const static int kFirstRunBubbleYOffset = 1; 63 64 } 65 66 // TODO(shess): This code is mostly copied from the gtk 67 // implementation. Make sure it's all appropriate and flesh it out. 68 69 LocationBarViewMac::LocationBarViewMac( 70 AutocompleteTextField* field, 71 CommandUpdater* command_updater, 72 ToolbarModel* toolbar_model, 73 Profile* profile, 74 Browser* browser) 75 : edit_view_(new AutocompleteEditViewMac(this, toolbar_model, profile, 76 command_updater, field)), 77 command_updater_(command_updater), 78 field_(field), 79 disposition_(CURRENT_TAB), 80 location_icon_decoration_(new LocationIconDecoration(this)), 81 selected_keyword_decoration_( 82 new SelectedKeywordDecoration( 83 AutocompleteEditViewMac::GetFieldFont())), 84 ev_bubble_decoration_( 85 new EVBubbleDecoration(location_icon_decoration_.get(), 86 AutocompleteEditViewMac::GetFieldFont())), 87 star_decoration_(new StarDecoration(command_updater)), 88 keyword_hint_decoration_( 89 new KeywordHintDecoration(AutocompleteEditViewMac::GetFieldFont())), 90 profile_(profile), 91 browser_(browser), 92 toolbar_model_(toolbar_model), 93 transition_(PageTransition::TYPED), 94 first_run_bubble_(this) { 95 for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { 96 DCHECK_EQ(i, content_setting_decorations_.size()); 97 ContentSettingsType type = static_cast<ContentSettingsType>(i); 98 content_setting_decorations_.push_back( 99 new ContentSettingDecoration(type, this, profile_)); 100 } 101 102 registrar_.Add(this, 103 NotificationType::EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED, 104 NotificationService::AllSources()); 105 106 edit_bookmarks_enabled_.Init(prefs::kEditBookmarksEnabled, 107 profile_->GetPrefs(), this); 108 } 109 110 LocationBarViewMac::~LocationBarViewMac() { 111 // Disconnect from cell in case it outlives us. 112 [[field_ cell] clearDecorations]; 113 } 114 115 void LocationBarViewMac::ShowFirstRunBubble(FirstRun::BubbleType bubble_type) { 116 // We need the browser window to be shown before we can show the bubble, but 117 // we get called before that's happened. 118 Task* task = first_run_bubble_.NewRunnableMethod( 119 &LocationBarViewMac::ShowFirstRunBubbleInternal, bubble_type); 120 MessageLoop::current()->PostTask(FROM_HERE, task); 121 } 122 123 void LocationBarViewMac::ShowFirstRunBubbleInternal( 124 FirstRun::BubbleType bubble_type) { 125 if (!field_ || ![field_ window]) 126 return; 127 128 // The first run bubble's left edge should line up with the left edge of the 129 // omnibox. This is different from other bubbles, which line up at a point 130 // set by their top arrow. Because the BaseBubbleController adjusts the 131 // window origin left to account for the arrow spacing, the first run bubble 132 // moves the window origin right by this spacing, so that the 133 // BaseBubbleController will move it back to the correct position. 134 const NSPoint kOffset = NSMakePoint( 135 info_bubble::kBubbleArrowXOffset + info_bubble::kBubbleArrowWidth/2.0, 136 kFirstRunBubbleYOffset); 137 [FirstRunBubbleController showForView:field_ offset:kOffset profile:profile_]; 138 } 139 140 std::wstring LocationBarViewMac::GetInputString() const { 141 return location_input_; 142 } 143 144 void LocationBarViewMac::SetSuggestedText(const string16& text, 145 InstantCompleteBehavior behavior) { 146 edit_view_->model()->SetSuggestedText(text, behavior); 147 } 148 149 WindowOpenDisposition LocationBarViewMac::GetWindowOpenDisposition() const { 150 return disposition_; 151 } 152 153 PageTransition::Type LocationBarViewMac::GetPageTransition() const { 154 return transition_; 155 } 156 157 void LocationBarViewMac::AcceptInput() { 158 WindowOpenDisposition disposition = 159 event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]); 160 edit_view_->model()->AcceptInput(disposition, false); 161 } 162 163 void LocationBarViewMac::FocusLocation(bool select_all) { 164 edit_view_->FocusLocation(select_all); 165 } 166 167 void LocationBarViewMac::FocusSearch() { 168 edit_view_->SetForcedQuery(); 169 } 170 171 void LocationBarViewMac::UpdateContentSettingsIcons() { 172 if (RefreshContentSettingsDecorations()) { 173 [field_ updateCursorAndToolTipRects]; 174 [field_ setNeedsDisplay:YES]; 175 } 176 } 177 178 void LocationBarViewMac::UpdatePageActions() { 179 size_t count_before = page_action_decorations_.size(); 180 RefreshPageActionDecorations(); 181 Layout(); 182 if (page_action_decorations_.size() != count_before) { 183 NotificationService::current()->Notify( 184 NotificationType::EXTENSION_PAGE_ACTION_COUNT_CHANGED, 185 Source<LocationBar>(this), 186 NotificationService::NoDetails()); 187 } 188 } 189 190 void LocationBarViewMac::InvalidatePageActions() { 191 size_t count_before = page_action_decorations_.size(); 192 DeletePageActionDecorations(); 193 Layout(); 194 if (page_action_decorations_.size() != count_before) { 195 NotificationService::current()->Notify( 196 NotificationType::EXTENSION_PAGE_ACTION_COUNT_CHANGED, 197 Source<LocationBar>(this), 198 NotificationService::NoDetails()); 199 } 200 } 201 202 void LocationBarViewMac::SaveStateToContents(TabContents* contents) { 203 // TODO(shess): Why SaveStateToContents vs SaveStateToTab? 204 edit_view_->SaveStateToTab(contents); 205 } 206 207 void LocationBarViewMac::Update(const TabContents* contents, 208 bool should_restore_state) { 209 bool star_enabled = IsStarEnabled(); 210 command_updater_->UpdateCommandEnabled(IDC_BOOKMARK_PAGE, star_enabled); 211 star_decoration_->SetVisible(star_enabled); 212 RefreshPageActionDecorations(); 213 RefreshContentSettingsDecorations(); 214 // AutocompleteEditView restores state if the tab is non-NULL. 215 edit_view_->Update(should_restore_state ? contents : NULL); 216 OnChanged(); 217 } 218 219 void LocationBarViewMac::OnAutocompleteAccept(const GURL& url, 220 WindowOpenDisposition disposition, 221 PageTransition::Type transition, 222 const GURL& alternate_nav_url) { 223 // WARNING: don't add an early return here. The calls after the if must 224 // happen. 225 if (url.is_valid()) { 226 location_input_ = UTF8ToWide(url.spec()); 227 disposition_ = disposition; 228 transition_ = transition; 229 230 if (command_updater_) { 231 if (!alternate_nav_url.is_valid()) { 232 command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL); 233 } else { 234 AlternateNavURLFetcher* fetcher = 235 new AlternateNavURLFetcher(alternate_nav_url); 236 // The AlternateNavURLFetcher will listen for the pending navigation 237 // notification that will be issued as a result of the "open URL." It 238 // will automatically install itself into that navigation controller. 239 command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL); 240 if (fetcher->state() == AlternateNavURLFetcher::NOT_STARTED) { 241 // I'm not sure this should be reachable, but I'm not also sure enough 242 // that it shouldn't to stick in a NOTREACHED(). In any case, this is 243 // harmless. 244 delete fetcher; 245 } else { 246 // The navigation controller will delete the fetcher. 247 } 248 } 249 } 250 } 251 } 252 253 void LocationBarViewMac::OnChanged() { 254 // Update the location-bar icon. 255 const int resource_id = edit_view_->GetIcon(); 256 NSImage* image = AutocompleteEditViewMac::ImageForResource(resource_id); 257 location_icon_decoration_->SetImage(image); 258 ev_bubble_decoration_->SetImage(image); 259 Layout(); 260 } 261 262 void LocationBarViewMac::OnSelectionBoundsChanged() { 263 NOTIMPLEMENTED(); 264 } 265 266 void LocationBarViewMac::OnInputInProgress(bool in_progress) { 267 toolbar_model_->set_input_in_progress(in_progress); 268 Update(NULL, false); 269 } 270 271 void LocationBarViewMac::OnSetFocus() { 272 // Update the keyword and search hint states. 273 OnChanged(); 274 } 275 276 void LocationBarViewMac::OnKillFocus() { 277 // Do nothing. 278 } 279 280 SkBitmap LocationBarViewMac::GetFavicon() const { 281 NOTIMPLEMENTED(); 282 return SkBitmap(); 283 } 284 285 string16 LocationBarViewMac::GetTitle() const { 286 NOTIMPLEMENTED(); 287 return string16(); 288 } 289 290 InstantController* LocationBarViewMac::GetInstant() { 291 return browser_->instant(); 292 } 293 294 TabContentsWrapper* LocationBarViewMac::GetTabContentsWrapper() const { 295 return browser_->GetSelectedTabContentsWrapper(); 296 } 297 298 void LocationBarViewMac::Revert() { 299 edit_view_->RevertAll(); 300 } 301 302 const AutocompleteEditView* LocationBarViewMac::location_entry() const { 303 return edit_view_.get(); 304 } 305 306 AutocompleteEditView* LocationBarViewMac::location_entry() { 307 return edit_view_.get(); 308 } 309 310 LocationBarTesting* LocationBarViewMac::GetLocationBarForTesting() { 311 return this; 312 } 313 314 // TODO(pamg): Change all these, here and for other platforms, to size_t. 315 int LocationBarViewMac::PageActionCount() { 316 return static_cast<int>(page_action_decorations_.size()); 317 } 318 319 int LocationBarViewMac::PageActionVisibleCount() { 320 int result = 0; 321 for (size_t i = 0; i < page_action_decorations_.size(); ++i) { 322 if (page_action_decorations_[i]->IsVisible()) 323 ++result; 324 } 325 return result; 326 } 327 328 TabContents* LocationBarViewMac::GetTabContents() const { 329 return browser_->GetSelectedTabContents(); 330 } 331 332 PageActionDecoration* LocationBarViewMac::GetPageActionDecoration( 333 ExtensionAction* page_action) { 334 DCHECK(page_action); 335 for (size_t i = 0; i < page_action_decorations_.size(); ++i) { 336 if (page_action_decorations_[i]->page_action() == page_action) 337 return page_action_decorations_[i]; 338 } 339 // If |page_action| is the browser action of an extension, no element in 340 // |page_action_decorations_| will match. 341 NOTREACHED(); 342 return NULL; 343 } 344 345 void LocationBarViewMac::SetPreviewEnabledPageAction( 346 ExtensionAction* page_action, bool preview_enabled) { 347 DCHECK(page_action); 348 TabContents* contents = GetTabContents(); 349 if (!contents) 350 return; 351 RefreshPageActionDecorations(); 352 Layout(); 353 354 PageActionDecoration* decoration = GetPageActionDecoration(page_action); 355 DCHECK(decoration); 356 if (!decoration) 357 return; 358 359 decoration->set_preview_enabled(preview_enabled); 360 decoration->UpdateVisibility(contents, 361 GURL(WideToUTF8(toolbar_model_->GetText()))); 362 } 363 364 NSPoint LocationBarViewMac::GetPageActionBubblePoint( 365 ExtensionAction* page_action) { 366 PageActionDecoration* decoration = GetPageActionDecoration(page_action); 367 if (!decoration) 368 return NSZeroPoint; 369 370 AutocompleteTextFieldCell* cell = [field_ cell]; 371 NSRect frame = [cell frameForDecoration:decoration inFrame:[field_ bounds]]; 372 DCHECK(!NSIsEmptyRect(frame)); 373 if (NSIsEmptyRect(frame)) 374 return NSZeroPoint; 375 376 NSPoint bubble_point = decoration->GetBubblePointInFrame(frame); 377 return [field_ convertPoint:bubble_point toView:nil]; 378 } 379 380 NSRect LocationBarViewMac::GetBlockedPopupRect() const { 381 const size_t kPopupIndex = CONTENT_SETTINGS_TYPE_POPUPS; 382 const LocationBarDecoration* decoration = 383 content_setting_decorations_[kPopupIndex]; 384 if (!decoration || !decoration->IsVisible()) 385 return NSZeroRect; 386 387 AutocompleteTextFieldCell* cell = [field_ cell]; 388 const NSRect frame = [cell frameForDecoration:decoration 389 inFrame:[field_ bounds]]; 390 return [field_ convertRect:frame toView:nil]; 391 } 392 393 ExtensionAction* LocationBarViewMac::GetPageAction(size_t index) { 394 if (index < page_action_decorations_.size()) 395 return page_action_decorations_[index]->page_action(); 396 NOTREACHED(); 397 return NULL; 398 } 399 400 ExtensionAction* LocationBarViewMac::GetVisiblePageAction(size_t index) { 401 size_t current = 0; 402 for (size_t i = 0; i < page_action_decorations_.size(); ++i) { 403 if (page_action_decorations_[i]->IsVisible()) { 404 if (current == index) 405 return page_action_decorations_[i]->page_action(); 406 407 ++current; 408 } 409 } 410 411 NOTREACHED(); 412 return NULL; 413 } 414 415 void LocationBarViewMac::TestPageActionPressed(size_t index) { 416 DCHECK_LT(index, page_action_decorations_.size()); 417 if (index < page_action_decorations_.size()) 418 page_action_decorations_[index]->OnMousePressed(NSZeroRect); 419 } 420 421 void LocationBarViewMac::SetEditable(bool editable) { 422 [field_ setEditable:editable ? YES : NO]; 423 star_decoration_->SetVisible(IsStarEnabled()); 424 UpdatePageActions(); 425 Layout(); 426 } 427 428 bool LocationBarViewMac::IsEditable() { 429 return [field_ isEditable] ? true : false; 430 } 431 432 void LocationBarViewMac::SetStarred(bool starred) { 433 star_decoration_->SetStarred(starred); 434 435 // TODO(shess): The field-editor frame and cursor rects should not 436 // change, here. 437 [field_ updateCursorAndToolTipRects]; 438 [field_ resetFieldEditorFrameIfNeeded]; 439 [field_ setNeedsDisplay:YES]; 440 } 441 442 NSPoint LocationBarViewMac::GetBookmarkBubblePoint() const { 443 AutocompleteTextFieldCell* cell = [field_ cell]; 444 const NSRect frame = [cell frameForDecoration:star_decoration_.get() 445 inFrame:[field_ bounds]]; 446 const NSPoint point = star_decoration_->GetBubblePointInFrame(frame); 447 return [field_ convertPoint:point toView:nil]; 448 } 449 450 NSPoint LocationBarViewMac::GetPageInfoBubblePoint() const { 451 AutocompleteTextFieldCell* cell = [field_ cell]; 452 if (ev_bubble_decoration_->IsVisible()) { 453 const NSRect frame = [cell frameForDecoration:ev_bubble_decoration_.get() 454 inFrame:[field_ bounds]]; 455 const NSPoint point = ev_bubble_decoration_->GetBubblePointInFrame(frame); 456 return [field_ convertPoint:point toView:nil]; 457 } else { 458 const NSRect frame = 459 [cell frameForDecoration:location_icon_decoration_.get() 460 inFrame:[field_ bounds]]; 461 const NSPoint point = 462 location_icon_decoration_->GetBubblePointInFrame(frame); 463 return [field_ convertPoint:point toView:nil]; 464 } 465 } 466 467 NSImage* LocationBarViewMac::GetKeywordImage(const string16& keyword) { 468 const TemplateURL* template_url = 469 profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword); 470 if (template_url && template_url->IsExtensionKeyword()) { 471 const SkBitmap& bitmap = profile_->GetExtensionService()-> 472 GetOmniboxIcon(template_url->GetExtensionId()); 473 return gfx::SkBitmapToNSImage(bitmap); 474 } 475 476 return AutocompleteEditViewMac::ImageForResource(IDR_OMNIBOX_SEARCH); 477 } 478 479 void LocationBarViewMac::Observe(NotificationType type, 480 const NotificationSource& source, 481 const NotificationDetails& details) { 482 switch (type.value) { 483 case NotificationType::EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED: { 484 TabContents* contents = GetTabContents(); 485 if (Details<TabContents>(contents) != details) 486 return; 487 488 [field_ updateCursorAndToolTipRects]; 489 [field_ setNeedsDisplay:YES]; 490 break; 491 } 492 493 case NotificationType::PREF_CHANGED: 494 star_decoration_->SetVisible(IsStarEnabled()); 495 OnChanged(); 496 break; 497 498 default: 499 NOTREACHED() << "Unexpected notification"; 500 break; 501 } 502 } 503 504 void LocationBarViewMac::PostNotification(NSString* notification) { 505 [[NSNotificationCenter defaultCenter] postNotificationName:notification 506 object:[NSValue valueWithPointer:this]]; 507 } 508 509 bool LocationBarViewMac::RefreshContentSettingsDecorations() { 510 const bool input_in_progress = toolbar_model_->input_in_progress(); 511 TabContents* tab_contents = 512 input_in_progress ? NULL : browser_->GetSelectedTabContents(); 513 bool icons_updated = false; 514 for (size_t i = 0; i < content_setting_decorations_.size(); ++i) { 515 icons_updated |= 516 content_setting_decorations_[i]->UpdateFromTabContents(tab_contents); 517 } 518 return icons_updated; 519 } 520 521 void LocationBarViewMac::DeletePageActionDecorations() { 522 // TODO(shess): Deleting these decorations could result in the cell 523 // refering to them before things are laid out again. Meanwhile, at 524 // least fail safe. 525 [[field_ cell] clearDecorations]; 526 527 page_action_decorations_.reset(); 528 } 529 530 void LocationBarViewMac::RefreshPageActionDecorations() { 531 if (!IsEditable()) { 532 DeletePageActionDecorations(); 533 return; 534 } 535 536 ExtensionService* service = profile_->GetExtensionService(); 537 if (!service) 538 return; 539 540 std::vector<ExtensionAction*> page_actions; 541 for (size_t i = 0; i < service->extensions()->size(); ++i) { 542 if (service->extensions()->at(i)->page_action()) 543 page_actions.push_back(service->extensions()->at(i)->page_action()); 544 } 545 546 // On startup we sometimes haven't loaded any extensions. This makes sure 547 // we catch up when the extensions (and any Page Actions) load. 548 if (page_actions.size() != page_action_decorations_.size()) { 549 DeletePageActionDecorations(); // Delete the old views (if any). 550 551 for (size_t i = 0; i < page_actions.size(); ++i) { 552 page_action_decorations_.push_back( 553 new PageActionDecoration(this, profile_, page_actions[i])); 554 } 555 } 556 557 if (page_action_decorations_.empty()) 558 return; 559 560 TabContents* contents = GetTabContents(); 561 if (!contents) 562 return; 563 564 GURL url = GURL(WideToUTF8(toolbar_model_->GetText())); 565 for (size_t i = 0; i < page_action_decorations_.size(); ++i) { 566 page_action_decorations_[i]->UpdateVisibility( 567 toolbar_model_->input_in_progress() ? NULL : contents, url); 568 } 569 } 570 571 // TODO(shess): This function should over time grow to closely match 572 // the views Layout() function. 573 void LocationBarViewMac::Layout() { 574 AutocompleteTextFieldCell* cell = [field_ cell]; 575 576 // Reset the left-hand decorations. 577 // TODO(shess): Shortly, this code will live somewhere else, like in 578 // the constructor. I am still wrestling with how best to deal with 579 // right-hand decorations, which are not a static set. 580 [cell clearDecorations]; 581 [cell addLeftDecoration:location_icon_decoration_.get()]; 582 [cell addLeftDecoration:selected_keyword_decoration_.get()]; 583 [cell addLeftDecoration:ev_bubble_decoration_.get()]; 584 [cell addRightDecoration:star_decoration_.get()]; 585 586 // Note that display order is right to left. 587 for (size_t i = 0; i < page_action_decorations_.size(); ++i) { 588 [cell addRightDecoration:page_action_decorations_[i]]; 589 } 590 for (size_t i = 0; i < content_setting_decorations_.size(); ++i) { 591 [cell addRightDecoration:content_setting_decorations_[i]]; 592 } 593 594 [cell addRightDecoration:keyword_hint_decoration_.get()]; 595 596 // By default only the location icon is visible. 597 location_icon_decoration_->SetVisible(true); 598 selected_keyword_decoration_->SetVisible(false); 599 ev_bubble_decoration_->SetVisible(false); 600 keyword_hint_decoration_->SetVisible(false); 601 602 // Get the keyword to use for keyword-search and hinting. 603 const string16 keyword = edit_view_->model()->keyword(); 604 string16 short_name; 605 bool is_extension_keyword = false; 606 if (!keyword.empty()) { 607 short_name = profile_->GetTemplateURLModel()-> 608 GetKeywordShortName(keyword, &is_extension_keyword); 609 } 610 611 const bool is_keyword_hint = edit_view_->model()->is_keyword_hint(); 612 613 if (!keyword.empty() && !is_keyword_hint) { 614 // Switch from location icon to keyword mode. 615 location_icon_decoration_->SetVisible(false); 616 selected_keyword_decoration_->SetVisible(true); 617 selected_keyword_decoration_->SetKeyword(short_name, is_extension_keyword); 618 selected_keyword_decoration_->SetImage(GetKeywordImage(keyword)); 619 } else if (toolbar_model_->GetSecurityLevel() == ToolbarModel::EV_SECURE) { 620 // Switch from location icon to show the EV bubble instead. 621 location_icon_decoration_->SetVisible(false); 622 ev_bubble_decoration_->SetVisible(true); 623 624 std::wstring label(toolbar_model_->GetEVCertName()); 625 ev_bubble_decoration_->SetFullLabel(base::SysWideToNSString(label)); 626 } else if (!keyword.empty() && is_keyword_hint) { 627 keyword_hint_decoration_->SetKeyword(short_name, 628 is_extension_keyword); 629 keyword_hint_decoration_->SetVisible(true); 630 } 631 632 // These need to change anytime the layout changes. 633 // TODO(shess): Anytime the field editor might have changed, the 634 // cursor rects almost certainly should have changed. The tooltips 635 // might change even when the rects don't change. 636 [field_ resetFieldEditorFrameIfNeeded]; 637 [field_ updateCursorAndToolTipRects]; 638 639 [field_ setNeedsDisplay:YES]; 640 } 641 642 bool LocationBarViewMac::IsStarEnabled() { 643 return [field_ isEditable] && 644 browser_defaults::bookmarks_enabled && 645 !toolbar_model_->input_in_progress() && 646 edit_bookmarks_enabled_.GetValue(); 647 } 648