Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / location_bar / location_bar_view_mac.mm
blobc86592fc7b16706dbaced10c54f3cac80f1af596
1 // Copyright 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.
5 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/stl_util.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/sys_string_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #import "chrome/browser/app_controller_mac.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/command_updater.h"
18 #include "chrome/browser/defaults.h"
19 #include "chrome/browser/extensions/api/omnibox/omnibox_api.h"
20 #include "chrome/browser/extensions/api/tabs/tabs_api.h"
21 #include "chrome/browser/extensions/extension_action.h"
22 #include "chrome/browser/extensions/extension_service.h"
23 #include "chrome/browser/extensions/location_bar_controller.h"
24 #include "chrome/browser/extensions/tab_helper.h"
25 #include "chrome/browser/search/search.h"
26 #include "chrome/browser/search_engines/template_url.h"
27 #include "chrome/browser/search_engines/template_url_service.h"
28 #include "chrome/browser/search_engines/template_url_service_factory.h"
29 #include "chrome/browser/ui/browser_instant_controller.h"
30 #include "chrome/browser/ui/browser_list.h"
31 #import "chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h"
32 #import "chrome/browser/ui/cocoa/extensions/extension_popup_controller.h"
33 #import "chrome/browser/ui/cocoa/first_run_bubble_controller.h"
34 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h"
35 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.h"
36 #import "chrome/browser/ui/cocoa/location_bar/content_setting_decoration.h"
37 #import "chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.h"
38 #import "chrome/browser/ui/cocoa/location_bar/generated_credit_card_decoration.h"
39 #import "chrome/browser/ui/cocoa/location_bar/keyword_hint_decoration.h"
40 #import "chrome/browser/ui/cocoa/location_bar/location_icon_decoration.h"
41 #import "chrome/browser/ui/cocoa/location_bar/mic_search_decoration.h"
42 #import "chrome/browser/ui/cocoa/location_bar/page_action_decoration.h"
43 #import "chrome/browser/ui/cocoa/location_bar/search_button_decoration.h"
44 #import "chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.h"
45 #import "chrome/browser/ui/cocoa/location_bar/star_decoration.h"
46 #import "chrome/browser/ui/cocoa/location_bar/zoom_decoration.h"
47 #import "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
48 #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
49 #include "chrome/browser/ui/content_settings/content_setting_image_model.h"
50 #include "chrome/browser/ui/omnibox/location_bar_util.h"
51 #import "chrome/browser/ui/omnibox/omnibox_popup_model.h"
52 #include "chrome/browser/ui/tabs/tab_strip_model.h"
53 #include "chrome/browser/ui/toolbar/toolbar_model.h"
54 #include "chrome/browser/ui/zoom/zoom_controller.h"
55 #include "chrome/common/chrome_switches.h"
56 #include "chrome/common/pref_names.h"
57 #include "content/public/browser/notification_service.h"
58 #include "content/public/browser/web_contents.h"
59 #include "extensions/common/extension.h"
60 #include "extensions/common/permissions/permissions_data.h"
61 #include "grit/generated_resources.h"
62 #include "grit/theme_resources.h"
63 #include "net/base/net_util.h"
64 #include "skia/ext/skia_utils_mac.h"
65 #import "ui/base/cocoa/cocoa_event_utils.h"
66 #include "ui/base/l10n/l10n_util_mac.h"
67 #include "ui/base/resource/resource_bundle.h"
68 #include "ui/gfx/image/image.h"
70 using content::WebContents;
72 namespace {
74 // Vertical space between the bottom edge of the location_bar and the first run
75 // bubble arrow point.
76 const static int kFirstRunBubbleYOffset = 1;
78 // Functor for moving BookmarkManagerPrivate page actions to the right via
79 // stable_partition.
80 class IsPageActionViewRightAligned {
81  public:
82   explicit IsPageActionViewRightAligned(ExtensionService* extension_service)
83       : extension_service_(extension_service) {}
85   bool operator()(PageActionDecoration* page_action_decoration) {
86     return extensions::PermissionsData::HasAPIPermission(
87         extension_service_->GetExtensionById(
88             page_action_decoration->page_action()->extension_id(),
89             false),
90         extensions::APIPermission::kBookmarkManagerPrivate);
91   }
93  private:
94   ExtensionService* extension_service_;
96   // NOTE: Can't DISALLOW_COPY_AND_ASSIGN as we pass this object by value to
97   // std::stable_partition().
102 // TODO(shess): This code is mostly copied from the gtk
103 // implementation.  Make sure it's all appropriate and flesh it out.
105 LocationBarViewMac::LocationBarViewMac(
106     AutocompleteTextField* field,
107     CommandUpdater* command_updater,
108     Profile* profile,
109     Browser* browser)
110     : LocationBar(profile),
111       OmniboxEditController(command_updater),
112       omnibox_view_(new OmniboxViewMac(this, profile, command_updater, field)),
113       field_(field),
114       location_icon_decoration_(new LocationIconDecoration(this)),
115       selected_keyword_decoration_(new SelectedKeywordDecoration()),
116       ev_bubble_decoration_(
117           new EVBubbleDecoration(location_icon_decoration_.get())),
118       star_decoration_(new StarDecoration(command_updater)),
119       zoom_decoration_(new ZoomDecoration(this)),
120       keyword_hint_decoration_(new KeywordHintDecoration()),
121       mic_search_decoration_(new MicSearchDecoration(command_updater)),
122       generated_credit_card_decoration_(
123           new GeneratedCreditCardDecoration(this)),
124       search_button_decoration_(new SearchButtonDecoration(this)),
125       browser_(browser),
126       weak_ptr_factory_(this) {
128   for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
129     DCHECK_EQ(i, content_setting_decorations_.size());
130     ContentSettingsType type = static_cast<ContentSettingsType>(i);
131     content_setting_decorations_.push_back(
132         new ContentSettingDecoration(type, this, profile));
133   }
135   registrar_.Add(
136       this, chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED,
137       content::NotificationService::AllSources());
138   content::Source<Profile> profile_source = content::Source<Profile>(profile);
139   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOCATION_BAR_UPDATED,
140                  profile_source);
141   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, profile_source);
142   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, profile_source);
144   edit_bookmarks_enabled_.Init(
145       prefs::kEditBookmarksEnabled, profile->GetPrefs(),
146       base::Bind(&LocationBarViewMac::OnEditBookmarksEnabledChanged,
147                  base::Unretained(this)));
149   browser_->search_model()->AddObserver(this);
151   [[field_ cell] setIsPopupMode:
152       !browser->SupportsWindowFeature(Browser::FEATURE_TABSTRIP)];
155 LocationBarViewMac::~LocationBarViewMac() {
156   // Disconnect from cell in case it outlives us.
157   [[field_ cell] clearDecorations];
159   browser_->search_model()->RemoveObserver(this);
162 void LocationBarViewMac::ShowFirstRunBubble() {
163   // We need the browser window to be shown before we can show the bubble, but
164   // we get called before that's happened.
165   base::MessageLoop::current()->PostTask(
166       FROM_HERE, base::Bind(&LocationBarViewMac::ShowFirstRunBubbleInternal,
167                             weak_ptr_factory_.GetWeakPtr()));
170 GURL LocationBarViewMac::GetDestinationURL() const {
171   return destination_url();
174 WindowOpenDisposition LocationBarViewMac::GetWindowOpenDisposition() const {
175   return disposition();
178 content::PageTransition LocationBarViewMac::GetPageTransition() const {
179   return transition();
182 void LocationBarViewMac::AcceptInput() {
183   WindowOpenDisposition disposition =
184       ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
185   omnibox_view_->model()->AcceptInput(disposition, false);
188 void LocationBarViewMac::FocusLocation(bool select_all) {
189   omnibox_view_->FocusLocation(select_all);
192 void LocationBarViewMac::FocusSearch() {
193   omnibox_view_->SetForcedQuery();
196 void LocationBarViewMac::UpdateContentSettingsIcons() {
197   if (RefreshContentSettingsDecorations())
198     OnDecorationsChanged();
201 void LocationBarViewMac::UpdatePageActions() {
202   size_t count_before = page_action_decorations_.size();
203   RefreshPageActionDecorations();
204   Layout();
205   if (page_action_decorations_.size() != count_before) {
206     content::NotificationService::current()->Notify(
207         chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED,
208         content::Source<LocationBar>(this),
209         content::NotificationService::NoDetails());
210   }
213 void LocationBarViewMac::InvalidatePageActions() {
214   size_t count_before = page_action_decorations_.size();
215   DeletePageActionDecorations();
216   Layout();
217   if (page_action_decorations_.size() != count_before) {
218     content::NotificationService::current()->Notify(
219         chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED,
220         content::Source<LocationBar>(this),
221         content::NotificationService::NoDetails());
222   }
225 void LocationBarViewMac::UpdateOpenPDFInReaderPrompt() {
226   // Not implemented on Mac.
229 void LocationBarViewMac::UpdateGeneratedCreditCardView() {
230   generated_credit_card_decoration_->Update();
233 void LocationBarViewMac::SaveStateToContents(WebContents* contents) {
234   // TODO(shess): Why SaveStateToContents vs SaveStateToTab?
235   omnibox_view_->SaveStateToTab(contents);
238 void LocationBarViewMac::Revert() {
239   omnibox_view_->RevertAll();
242 const OmniboxView* LocationBarViewMac::GetOmniboxView() const {
243   return omnibox_view_.get();
246 OmniboxView* LocationBarViewMac::GetOmniboxView() {
247   return omnibox_view_.get();
250 LocationBarTesting* LocationBarViewMac::GetLocationBarForTesting() {
251   return this;
254 // TODO(pamg): Change all these, here and for other platforms, to size_t.
255 int LocationBarViewMac::PageActionCount() {
256   return static_cast<int>(page_action_decorations_.size());
259 int LocationBarViewMac::PageActionVisibleCount() {
260   int result = 0;
261   for (size_t i = 0; i < page_action_decorations_.size(); ++i) {
262     if (page_action_decorations_[i]->IsVisible())
263       ++result;
264   }
265   return result;
268 ExtensionAction* LocationBarViewMac::GetPageAction(size_t index) {
269   if (index < page_action_decorations_.size())
270     return page_action_decorations_[index]->page_action();
271   NOTREACHED();
272   return NULL;
275 ExtensionAction* LocationBarViewMac::GetVisiblePageAction(size_t index) {
276   size_t current = 0;
277   for (size_t i = 0; i < page_action_decorations_.size(); ++i) {
278     if (page_action_decorations_[i]->IsVisible()) {
279       if (current == index)
280         return page_action_decorations_[i]->page_action();
282       ++current;
283     }
284   }
286   NOTREACHED();
287   return NULL;
290 void LocationBarViewMac::TestPageActionPressed(size_t index) {
291   DCHECK_LT(index, page_action_decorations_.size());
292   if (index < page_action_decorations_.size())
293     page_action_decorations_[index]->OnMousePressed(NSZeroRect);
296 bool LocationBarViewMac::GetBookmarkStarVisibility() {
297   DCHECK(star_decoration_.get());
298   return star_decoration_->IsVisible();
301 void LocationBarViewMac::SetEditable(bool editable) {
302   [field_ setEditable:editable ? YES : NO];
303   UpdateStarDecorationVisibility();
304   UpdateZoomDecoration();
305   UpdatePageActions();
306   Layout();
309 bool LocationBarViewMac::IsEditable() {
310   return [field_ isEditable] ? true : false;
313 void LocationBarViewMac::SetStarred(bool starred) {
314   star_decoration_->SetStarred(starred);
315   UpdateStarDecorationVisibility();
316   OnDecorationsChanged();
319 void LocationBarViewMac::ZoomChangedForActiveTab(bool can_show_bubble) {
320   UpdateZoomDecoration();
321   OnDecorationsChanged();
323   if (can_show_bubble && zoom_decoration_->IsVisible())
324     zoom_decoration_->ShowBubble(YES);
327 bool LocationBarViewMac::IsStarEnabled() const {
328   return browser_defaults::bookmarks_enabled &&
329          [field_ isEditable] &&
330          !GetToolbarModel()->input_in_progress() &&
331          edit_bookmarks_enabled_.GetValue() &&
332          !IsBookmarkStarHiddenByExtension();
335 NSPoint LocationBarViewMac::GetBookmarkBubblePoint() const {
336   DCHECK(IsStarEnabled());
338   AutocompleteTextFieldCell* cell = [field_ cell];
339   const NSRect frame = [cell frameForDecoration:star_decoration_.get()
340                                         inFrame:[field_ bounds]];
341   const NSPoint point = star_decoration_->GetBubblePointInFrame(frame);
342   return [field_ convertPoint:point toView:nil];
345 NSPoint LocationBarViewMac::GetPageInfoBubblePoint() const {
346   AutocompleteTextFieldCell* cell = [field_ cell];
347   if (ev_bubble_decoration_->IsVisible()) {
348     const NSRect frame = [cell frameForDecoration:ev_bubble_decoration_.get()
349                                           inFrame:[field_ bounds]];
350     const NSPoint point = ev_bubble_decoration_->GetBubblePointInFrame(frame);
351     return [field_ convertPoint:point toView:nil];
352   } else {
353     const NSRect frame =
354         [cell frameForDecoration:location_icon_decoration_.get()
355                          inFrame:[field_ bounds]];
356     const NSPoint point =
357         location_icon_decoration_->GetBubblePointInFrame(frame);
358     return [field_ convertPoint:point toView:nil];
359   }
362 NSPoint LocationBarViewMac::GetGeneratedCreditCardBubblePoint() const {
363   AutocompleteTextFieldCell* cell = [field_ cell];
364   const NSRect frame =
365       [cell frameForDecoration:generated_credit_card_decoration_.get()
366                        inFrame:[field_ bounds]];
367   const NSPoint point =
368       generated_credit_card_decoration_->GetBubblePointInFrame(frame);
369   return [field_ convertPoint:point toView:nil];
372 void LocationBarViewMac::OnDecorationsChanged() {
373   // TODO(shess): The field-editor frame and cursor rects should not
374   // change, here.
375   [field_ updateMouseTracking];
376   [field_ resetFieldEditorFrameIfNeeded];
377   [field_ setNeedsDisplay:YES];
380 // TODO(shess): This function should over time grow to closely match
381 // the views Layout() function.
382 void LocationBarViewMac::Layout() {
383   AutocompleteTextFieldCell* cell = [field_ cell];
385   // Reset the left-hand decorations.
386   // TODO(shess): Shortly, this code will live somewhere else, like in
387   // the constructor.  I am still wrestling with how best to deal with
388   // right-hand decorations, which are not a static set.
389   [cell clearDecorations];
390   [cell addLeftDecoration:location_icon_decoration_.get()];
391   [cell addLeftDecoration:selected_keyword_decoration_.get()];
392   [cell addLeftDecoration:ev_bubble_decoration_.get()];
393   [cell addRightDecoration:search_button_decoration_.get()];
394   [cell addRightDecoration:star_decoration_.get()];
395   [cell addRightDecoration:zoom_decoration_.get()];
396   [cell addRightDecoration:generated_credit_card_decoration_.get()];
398   // Note that display order is right to left.
399   for (size_t i = 0; i < page_action_decorations_.size(); ++i) {
400     [cell addRightDecoration:page_action_decorations_[i]];
401   }
403   for (ScopedVector<ContentSettingDecoration>::iterator i =
404        content_setting_decorations_.begin();
405        i != content_setting_decorations_.end(); ++i) {
406     [cell addRightDecoration:*i];
407   }
409   [cell addRightDecoration:keyword_hint_decoration_.get()];
410   [cell addRightDecoration:mic_search_decoration_.get()];
412   // By default only the location icon is visible.
413   location_icon_decoration_->SetVisible(true);
414   selected_keyword_decoration_->SetVisible(false);
415   ev_bubble_decoration_->SetVisible(false);
416   keyword_hint_decoration_->SetVisible(false);
418   // Get the keyword to use for keyword-search and hinting.
419   const base::string16 keyword = omnibox_view_->model()->keyword();
420   base::string16 short_name;
421   bool is_extension_keyword = false;
422   if (!keyword.empty()) {
423     short_name = TemplateURLServiceFactory::GetForProfile(profile())->
424         GetKeywordShortName(keyword, &is_extension_keyword);
425   }
427   const bool is_keyword_hint = omnibox_view_->model()->is_keyword_hint();
428   if (!keyword.empty() && !is_keyword_hint) {
429     // Switch from location icon to keyword mode.
430     location_icon_decoration_->SetVisible(false);
431     selected_keyword_decoration_->SetVisible(true);
432     selected_keyword_decoration_->SetKeyword(short_name, is_extension_keyword);
433     selected_keyword_decoration_->SetImage(GetKeywordImage(keyword));
434   } else if (GetToolbarModel()->GetSecurityLevel(false) ==
435              ToolbarModel::EV_SECURE) {
436     // Switch from location icon to show the EV bubble instead.
437     location_icon_decoration_->SetVisible(false);
438     ev_bubble_decoration_->SetVisible(true);
440     base::string16 label(GetToolbarModel()->GetEVCertName());
441     ev_bubble_decoration_->SetFullLabel(base::SysUTF16ToNSString(label));
442   } else if (!keyword.empty() && is_keyword_hint) {
443     keyword_hint_decoration_->SetKeyword(short_name,
444                                          is_extension_keyword);
445     keyword_hint_decoration_->SetVisible(true);
446   }
448   // These need to change anytime the layout changes.
449   // TODO(shess): Anytime the field editor might have changed, the
450   // cursor rects almost certainly should have changed.  The tooltips
451   // might change even when the rects don't change.
452   OnDecorationsChanged();
455 void LocationBarViewMac::RedrawDecoration(LocationBarDecoration* decoration) {
456   AutocompleteTextFieldCell* cell = [field_ cell];
457   NSRect frame = [cell frameForDecoration:decoration
458                                   inFrame:[field_ bounds]];
459   if (!NSIsEmptyRect(frame))
460     [field_ setNeedsDisplayInRect:frame];
463 void LocationBarViewMac::SetPreviewEnabledPageAction(
464     ExtensionAction* page_action, bool preview_enabled) {
465   DCHECK(page_action);
466   WebContents* contents = GetWebContents();
467   if (!contents)
468     return;
469   RefreshPageActionDecorations();
470   Layout();
472   PageActionDecoration* decoration = GetPageActionDecoration(page_action);
473   DCHECK(decoration);
474   if (!decoration)
475     return;
477   decoration->set_preview_enabled(preview_enabled);
478   decoration->UpdateVisibility(contents, GetToolbarModel()->GetURL());
481 NSRect LocationBarViewMac::GetPageActionFrame(ExtensionAction* page_action) {
482   PageActionDecoration* decoration = GetPageActionDecoration(page_action);
483   if (!decoration)
484     return NSZeroRect;
486   AutocompleteTextFieldCell* cell = [field_ cell];
487   NSRect frame = [cell frameForDecoration:decoration inFrame:[field_ bounds]];
488   return frame;
491 NSPoint LocationBarViewMac::GetPageActionBubblePoint(
492     ExtensionAction* page_action) {
493   PageActionDecoration* decoration = GetPageActionDecoration(page_action);
494   if (!decoration)
495     return NSZeroPoint;
497   NSRect frame = GetPageActionFrame(page_action);
498   if (NSIsEmptyRect(frame)) {
499     // The bubble point positioning assumes that the page action is visible. If
500     // not, something else needs to be done otherwise the bubble will appear
501     // near the top left corner (unanchored).
502     NOTREACHED();
503     return NSZeroPoint;
504   }
506   NSPoint bubble_point = decoration->GetBubblePointInFrame(frame);
507   return [field_ convertPoint:bubble_point toView:nil];
510 void LocationBarViewMac::Update(const WebContents* contents) {
511   UpdateStarDecorationVisibility();
512   UpdateZoomDecoration();
513   RefreshPageActionDecorations();
514   RefreshContentSettingsDecorations();
515   UpdateMicSearchDecorationVisibility();
516   UpdateGeneratedCreditCardView();
517   if (contents)
518     omnibox_view_->OnTabChanged(contents);
519   else
520     omnibox_view_->Update();
521   OnChanged();
524 void LocationBarViewMac::OnChanged() {
525   // Update the location-bar icon.
526   const int resource_id = omnibox_view_->GetIcon();
527   NSImage* image = OmniboxViewMac::ImageForResource(resource_id);
528   location_icon_decoration_->SetImage(image);
529   ev_bubble_decoration_->SetImage(image);
531   ToolbarModel* toolbar_model = GetToolbarModel();
532   const chrome::DisplaySearchButtonConditions conditions =
533       chrome::GetDisplaySearchButtonConditions();
534   const bool meets_conditions =
535       (conditions == chrome::DISPLAY_SEARCH_BUTTON_ALWAYS) ||
536       ((conditions != chrome::DISPLAY_SEARCH_BUTTON_NEVER) &&
537        (toolbar_model->WouldPerformSearchTermReplacement(true) ||
538         ((conditions == chrome::DISPLAY_SEARCH_BUTTON_FOR_STR_OR_IIP) &&
539          toolbar_model->input_in_progress())));
540   search_button_decoration_->SetVisible(
541       ![[field_ cell] isPopupMode] && meets_conditions);
542   search_button_decoration_->SetIcon(
543       (resource_id == IDR_OMNIBOX_SEARCH) ?
544           IDR_OMNIBOX_SEARCH_BUTTON_LOUPE : IDR_OMNIBOX_SEARCH_BUTTON_ARROW);
546   Layout();
548   if (browser_->instant_controller()) {
549     browser_->instant_controller()->SetOmniboxBounds(
550         gfx::Rect(NSRectToCGRect([field_ frame])));
551   }
554 void LocationBarViewMac::OnSetFocus() {
555   // Update the keyword and search hint states.
556   OnChanged();
559 InstantController* LocationBarViewMac::GetInstant() {
560   return browser_->instant_controller() ?
561       browser_->instant_controller()->instant() : NULL;
564 WebContents* LocationBarViewMac::GetWebContents() {
565   return browser_->tab_strip_model()->GetActiveWebContents();
568 ToolbarModel* LocationBarViewMac::GetToolbarModel() {
569   return browser_->toolbar_model();
572 const ToolbarModel* LocationBarViewMac::GetToolbarModel() const {
573   return browser_->toolbar_model();
576 NSImage* LocationBarViewMac::GetKeywordImage(const base::string16& keyword) {
577   const TemplateURL* template_url = TemplateURLServiceFactory::GetForProfile(
578       profile())->GetTemplateURLForKeyword(keyword);
579   if (template_url &&
580       (template_url->GetType() == TemplateURL::OMNIBOX_API_EXTENSION)) {
581     return extensions::OmniboxAPI::Get(profile())->
582         GetOmniboxIcon(template_url->GetExtensionId()).AsNSImage();
583   }
585   return OmniboxViewMac::ImageForResource(IDR_OMNIBOX_SEARCH);
588 void LocationBarViewMac::Observe(int type,
589                                  const content::NotificationSource& source,
590                                  const content::NotificationDetails& details) {
591   switch (type) {
592     case chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED: {
593       WebContents* contents = GetWebContents();
594       if (content::Details<WebContents>(contents) != details)
595         return;
597       [field_ updateMouseTracking];
598       [field_ setNeedsDisplay:YES];
599       break;
600     }
602     case chrome::NOTIFICATION_EXTENSION_LOCATION_BAR_UPDATED: {
603       // Only update if the updated action box was for the active tab contents.
604       WebContents* target_tab = content::Details<WebContents>(details).ptr();
605       if (target_tab == GetWebContents())
606         UpdatePageActions();
607       break;
608     }
610     case chrome::NOTIFICATION_EXTENSION_LOADED:
611     case chrome::NOTIFICATION_EXTENSION_UNLOADED:
612       Update(NULL);
613       break;
615     default:
616       NOTREACHED() << "Unexpected notification";
617       break;
618   }
621 void LocationBarViewMac::ModelChanged(const SearchModel::State& old_state,
622                                       const SearchModel::State& new_state) {
623   if (UpdateMicSearchDecorationVisibility())
624     Layout();
627 void LocationBarViewMac::PostNotification(NSString* notification) {
628   [[NSNotificationCenter defaultCenter] postNotificationName:notification
629                                         object:[NSValue valueWithPointer:this]];
632 PageActionDecoration* LocationBarViewMac::GetPageActionDecoration(
633     ExtensionAction* page_action) {
634   DCHECK(page_action);
635   for (size_t i = 0; i < page_action_decorations_.size(); ++i) {
636     if (page_action_decorations_[i]->page_action() == page_action)
637       return page_action_decorations_[i];
638   }
639   // If |page_action| is the browser action of an extension, no element in
640   // |page_action_decorations_| will match.
641   NOTREACHED();
642   return NULL;
646 void LocationBarViewMac::DeletePageActionDecorations() {
647   // TODO(shess): Deleting these decorations could result in the cell
648   // refering to them before things are laid out again.  Meanwhile, at
649   // least fail safe.
650   [[field_ cell] clearDecorations];
652   page_action_decorations_.clear();
655 void LocationBarViewMac::OnEditBookmarksEnabledChanged() {
656   UpdateStarDecorationVisibility();
657   OnChanged();
660 void LocationBarViewMac::RefreshPageActionDecorations() {
661   if (!IsEditable()) {
662     DeletePageActionDecorations();
663     return;
664   }
666   WebContents* web_contents = GetWebContents();
667   if (!web_contents) {
668     DeletePageActionDecorations();  // Necessary?
669     return;
670   }
672   std::vector<ExtensionAction*> new_page_actions =
673       extensions::TabHelper::FromWebContents(web_contents)->
674           location_bar_controller()->GetCurrentActions();
676   if (new_page_actions != page_actions_) {
677     page_actions_.swap(new_page_actions);
678     DeletePageActionDecorations();
679     for (size_t i = 0; i < page_actions_.size(); ++i) {
680       page_action_decorations_.push_back(
681           new PageActionDecoration(this, browser_, page_actions_[i]));
682     }
684     // Move rightmost extensions to the start.
685     std::stable_partition(
686         page_action_decorations_.begin(),
687         page_action_decorations_.end(),
688         IsPageActionViewRightAligned(
689             extensions::ExtensionSystem::Get(profile())->extension_service()));
690   }
692   GURL url = GetToolbarModel()->GetURL();
693   for (size_t i = 0; i < page_action_decorations_.size(); ++i) {
694     page_action_decorations_[i]->UpdateVisibility(
695         GetToolbarModel()->input_in_progress() ? NULL : web_contents, url);
696   }
699 bool LocationBarViewMac::RefreshContentSettingsDecorations() {
700   const bool input_in_progress = GetToolbarModel()->input_in_progress();
701   WebContents* web_contents = input_in_progress ?
702       NULL : browser_->tab_strip_model()->GetActiveWebContents();
703   bool icons_updated = false;
704   for (size_t i = 0; i < content_setting_decorations_.size(); ++i) {
705     icons_updated |=
706         content_setting_decorations_[i]->UpdateFromWebContents(web_contents);
707   }
708   return icons_updated;
711 void LocationBarViewMac::ShowFirstRunBubbleInternal() {
712   if (!field_ || ![field_ window])
713     return;
715   // The first run bubble's left edge should line up with the left edge of the
716   // omnibox. This is different from other bubbles, which line up at a point
717   // set by their top arrow. Because the BaseBubbleController adjusts the
718   // window origin left to account for the arrow spacing, the first run bubble
719   // moves the window origin right by this spacing, so that the
720   // BaseBubbleController will move it back to the correct position.
721   const NSPoint kOffset = NSMakePoint(
722       info_bubble::kBubbleArrowXOffset + info_bubble::kBubbleArrowWidth/2.0,
723       kFirstRunBubbleYOffset);
724   [FirstRunBubbleController showForView:field_
725                                  offset:kOffset
726                                 browser:browser_
727                                 profile:profile()];
730 void LocationBarViewMac::UpdateZoomDecoration() {
731   WebContents* web_contents = GetWebContents();
732   if (!web_contents)
733     return;
735   zoom_decoration_->Update(ZoomController::FromWebContents(web_contents));
738 void LocationBarViewMac::UpdateStarDecorationVisibility() {
739   star_decoration_->SetVisible(IsStarEnabled());
742 bool LocationBarViewMac::UpdateMicSearchDecorationVisibility() {
743   bool is_visible = !GetToolbarModel()->input_in_progress() &&
744                     browser_->search_model()->voice_search_supported();
745   if (mic_search_decoration_->IsVisible() == is_visible)
746     return false;
747   mic_search_decoration_->SetVisible(is_visible);
748   return true;