[Metrics] Make MetricsStateManager take a callback param to check if UMA is enabled.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / location_bar / location_bar_view_mac.mm
blob533d48ac56642c6133cff05abb53cc05f0af6498
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 #include "chrome/app/chrome_command_ids.h"
16 #import "chrome/browser/app_controller_mac.h"
17 #include "chrome/browser/chrome_notification_types.h"
18 #include "chrome/browser/command_updater.h"
19 #include "chrome/browser/defaults.h"
20 #include "chrome/browser/extensions/api/omnibox/omnibox_api.h"
21 #include "chrome/browser/extensions/api/tabs/tabs_api.h"
22 #include "chrome/browser/extensions/extension_action.h"
23 #include "chrome/browser/extensions/extension_service.h"
24 #include "chrome/browser/extensions/location_bar_controller.h"
25 #include "chrome/browser/extensions/tab_helper.h"
26 #include "chrome/browser/profiles/profile.h"
27 #include "chrome/browser/search/instant_service.h"
28 #include "chrome/browser/search/instant_service_factory.h"
29 #include "chrome/browser/search/search.h"
30 #include "chrome/browser/search_engines/template_url.h"
31 #include "chrome/browser/search_engines/template_url_service.h"
32 #include "chrome/browser/search_engines/template_url_service_factory.h"
33 #include "chrome/browser/translate/translate_service.h"
34 #include "chrome/browser/translate/translate_tab_helper.h"
35 #include "chrome/browser/ui/browser_instant_controller.h"
36 #include "chrome/browser/ui/browser_list.h"
37 #import "chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h"
38 #import "chrome/browser/ui/cocoa/extensions/extension_popup_controller.h"
39 #import "chrome/browser/ui/cocoa/first_run_bubble_controller.h"
40 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h"
41 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.h"
42 #import "chrome/browser/ui/cocoa/location_bar/content_setting_decoration.h"
43 #import "chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.h"
44 #import "chrome/browser/ui/cocoa/location_bar/generated_credit_card_decoration.h"
45 #import "chrome/browser/ui/cocoa/location_bar/keyword_hint_decoration.h"
46 #import "chrome/browser/ui/cocoa/location_bar/location_icon_decoration.h"
47 #import "chrome/browser/ui/cocoa/location_bar/mic_search_decoration.h"
48 #import "chrome/browser/ui/cocoa/location_bar/origin_chip_decoration.h"
49 #import "chrome/browser/ui/cocoa/location_bar/page_action_decoration.h"
50 #import "chrome/browser/ui/cocoa/location_bar/search_button_decoration.h"
51 #import "chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.h"
52 #import "chrome/browser/ui/cocoa/location_bar/star_decoration.h"
53 #import "chrome/browser/ui/cocoa/location_bar/translate_decoration.h"
54 #import "chrome/browser/ui/cocoa/location_bar/zoom_decoration.h"
55 #import "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
56 #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
57 #include "chrome/browser/ui/content_settings/content_setting_image_model.h"
58 #include "chrome/browser/ui/omnibox/location_bar_util.h"
59 #import "chrome/browser/ui/omnibox/omnibox_popup_model.h"
60 #include "chrome/browser/ui/tabs/tab_strip_model.h"
61 #include "chrome/browser/ui/toolbar/toolbar_model.h"
62 #include "chrome/browser/ui/zoom/zoom_controller.h"
63 #include "chrome/common/chrome_switches.h"
64 #include "chrome/common/pref_names.h"
65 #include "components/translate/core/browser/language_state.h"
66 #include "content/public/browser/notification_service.h"
67 #include "content/public/browser/web_contents.h"
68 #include "extensions/browser/extension_system.h"
69 #include "extensions/common/extension.h"
70 #include "extensions/common/permissions/permissions_data.h"
71 #include "grit/generated_resources.h"
72 #include "grit/theme_resources.h"
73 #include "net/base/net_util.h"
74 #include "skia/ext/skia_utils_mac.h"
75 #import "ui/base/cocoa/cocoa_base_utils.h"
76 #include "ui/base/l10n/l10n_util_mac.h"
77 #include "ui/base/resource/resource_bundle.h"
78 #include "ui/gfx/image/image.h"
80 using content::WebContents;
82 namespace {
84 // Vertical space between the bottom edge of the location_bar and the first run
85 // bubble arrow point.
86 const static int kFirstRunBubbleYOffset = 1;
88 // Functor for moving BookmarkManagerPrivate page actions to the right via
89 // stable_partition.
90 class IsPageActionViewRightAligned {
91  public:
92   explicit IsPageActionViewRightAligned(ExtensionService* extension_service)
93       : extension_service_(extension_service) {}
95   bool operator()(PageActionDecoration* page_action_decoration) {
96     return extensions::PermissionsData::HasAPIPermission(
97         extension_service_->GetExtensionById(
98             page_action_decoration->page_action()->extension_id(),
99             false),
100         extensions::APIPermission::kBookmarkManagerPrivate);
101   }
103  private:
104   ExtensionService* extension_service_;
106   // NOTE: Can't DISALLOW_COPY_AND_ASSIGN as we pass this object by value to
107   // std::stable_partition().
112 // TODO(shess): This code is mostly copied from the gtk
113 // implementation.  Make sure it's all appropriate and flesh it out.
115 LocationBarViewMac::LocationBarViewMac(AutocompleteTextField* field,
116                                        CommandUpdater* command_updater,
117                                        Profile* profile,
118                                        Browser* browser)
119     : LocationBar(profile),
120       OmniboxEditController(command_updater),
121       omnibox_view_(new OmniboxViewMac(this, profile, command_updater, field)),
122       field_(field),
123       location_icon_decoration_(new LocationIconDecoration(this)),
124       selected_keyword_decoration_(new SelectedKeywordDecoration()),
125       ev_bubble_decoration_(
126           new EVBubbleDecoration(location_icon_decoration_.get())),
127       star_decoration_(new StarDecoration(command_updater)),
128       translate_decoration_(new TranslateDecoration(command_updater)),
129       zoom_decoration_(new ZoomDecoration(this)),
130       keyword_hint_decoration_(new KeywordHintDecoration()),
131       mic_search_decoration_(new MicSearchDecoration(command_updater)),
132       generated_credit_card_decoration_(
133           new GeneratedCreditCardDecoration(this)),
134       search_button_decoration_(new SearchButtonDecoration(this)),
135       browser_(browser),
136       weak_ptr_factory_(this) {
138   for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
139     DCHECK_EQ(i, content_setting_decorations_.size());
140     ContentSettingsType type = static_cast<ContentSettingsType>(i);
141     content_setting_decorations_.push_back(
142         new ContentSettingDecoration(type, this, profile));
143   }
145   registrar_.Add(
146       this, chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED,
147       content::NotificationService::AllSources());
148   content::Source<Profile> profile_source = content::Source<Profile>(profile);
149   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOCATION_BAR_UPDATED,
150                  profile_source);
151   registrar_.Add(
152       this, chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED, profile_source);
153   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
154                  profile_source);
156   edit_bookmarks_enabled_.Init(
157       prefs::kEditBookmarksEnabled, profile->GetPrefs(),
158       base::Bind(&LocationBarViewMac::OnEditBookmarksEnabledChanged,
159                  base::Unretained(this)));
161   browser_->search_model()->AddObserver(this);
163   [[field_ cell] setIsPopupMode:
164       !browser->SupportsWindowFeature(Browser::FEATURE_TABSTRIP)];
166   if (chrome::ShouldDisplayOriginChip())
167     origin_chip_decoration_.reset(new OriginChipDecoration(
168         this, location_icon_decoration_.get()));
171 LocationBarViewMac::~LocationBarViewMac() {
172   // Disconnect from cell in case it outlives us.
173   [[field_ cell] clearDecorations];
175   browser_->search_model()->RemoveObserver(this);
178 void LocationBarViewMac::ShowFirstRunBubble() {
179   // We need the browser window to be shown before we can show the bubble, but
180   // we get called before that's happened.
181   base::MessageLoop::current()->PostTask(
182       FROM_HERE, base::Bind(&LocationBarViewMac::ShowFirstRunBubbleInternal,
183                             weak_ptr_factory_.GetWeakPtr()));
186 GURL LocationBarViewMac::GetDestinationURL() const {
187   return destination_url();
190 WindowOpenDisposition LocationBarViewMac::GetWindowOpenDisposition() const {
191   return disposition();
194 content::PageTransition LocationBarViewMac::GetPageTransition() const {
195   return transition();
198 void LocationBarViewMac::AcceptInput() {
199   WindowOpenDisposition disposition =
200       ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
201   omnibox_view_->model()->AcceptInput(disposition, false);
204 void LocationBarViewMac::FocusLocation(bool select_all) {
205   omnibox_view_->FocusLocation(select_all);
208 void LocationBarViewMac::FocusSearch() {
209   omnibox_view_->SetForcedQuery();
212 void LocationBarViewMac::UpdateContentSettingsIcons() {
213   if (RefreshContentSettingsDecorations())
214     OnDecorationsChanged();
217 void LocationBarViewMac::UpdatePageActions() {
218   size_t count_before = page_action_decorations_.size();
219   RefreshPageActionDecorations();
220   Layout();
221   if (page_action_decorations_.size() != count_before) {
222     content::NotificationService::current()->Notify(
223         chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED,
224         content::Source<LocationBar>(this),
225         content::NotificationService::NoDetails());
226   }
229 void LocationBarViewMac::InvalidatePageActions() {
230   size_t count_before = page_action_decorations_.size();
231   DeletePageActionDecorations();
232   Layout();
233   if (page_action_decorations_.size() != count_before) {
234     content::NotificationService::current()->Notify(
235         chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED,
236         content::Source<LocationBar>(this),
237         content::NotificationService::NoDetails());
238   }
241 void LocationBarViewMac::UpdateOpenPDFInReaderPrompt() {
242   // Not implemented on Mac.
245 void LocationBarViewMac::UpdateGeneratedCreditCardView() {
246   generated_credit_card_decoration_->Update();
249 void LocationBarViewMac::SaveStateToContents(WebContents* contents) {
250   // TODO(shess): Why SaveStateToContents vs SaveStateToTab?
251   omnibox_view_->SaveStateToTab(contents);
254 void LocationBarViewMac::Revert() {
255   omnibox_view_->RevertAll();
258 const OmniboxView* LocationBarViewMac::GetOmniboxView() const {
259   return omnibox_view_.get();
262 OmniboxView* LocationBarViewMac::GetOmniboxView() {
263   return omnibox_view_.get();
266 LocationBarTesting* LocationBarViewMac::GetLocationBarForTesting() {
267   return this;
270 // TODO(pamg): Change all these, here and for other platforms, to size_t.
271 int LocationBarViewMac::PageActionCount() {
272   return static_cast<int>(page_action_decorations_.size());
275 int LocationBarViewMac::PageActionVisibleCount() {
276   int result = 0;
277   for (size_t i = 0; i < page_action_decorations_.size(); ++i) {
278     if (page_action_decorations_[i]->IsVisible())
279       ++result;
280   }
281   return result;
284 ExtensionAction* LocationBarViewMac::GetPageAction(size_t index) {
285   if (index < page_action_decorations_.size())
286     return page_action_decorations_[index]->page_action();
287   NOTREACHED();
288   return NULL;
291 ExtensionAction* LocationBarViewMac::GetVisiblePageAction(size_t index) {
292   size_t current = 0;
293   for (size_t i = 0; i < page_action_decorations_.size(); ++i) {
294     if (page_action_decorations_[i]->IsVisible()) {
295       if (current == index)
296         return page_action_decorations_[i]->page_action();
298       ++current;
299     }
300   }
302   NOTREACHED();
303   return NULL;
306 void LocationBarViewMac::TestPageActionPressed(size_t index) {
307   DCHECK_LT(index, page_action_decorations_.size());
308   if (index < page_action_decorations_.size())
309     page_action_decorations_[index]->OnMousePressed(NSZeroRect, NSZeroPoint);
312 bool LocationBarViewMac::GetBookmarkStarVisibility() {
313   DCHECK(star_decoration_.get());
314   return star_decoration_->IsVisible();
317 void LocationBarViewMac::SetEditable(bool editable) {
318   [field_ setEditable:editable ? YES : NO];
319   UpdateStarDecorationVisibility();
320   UpdateZoomDecoration();
321   UpdatePageActions();
322   Layout();
325 bool LocationBarViewMac::IsEditable() {
326   return [field_ isEditable] ? true : false;
329 void LocationBarViewMac::SetStarred(bool starred) {
330   star_decoration_->SetStarred(starred);
331   UpdateStarDecorationVisibility();
332   OnDecorationsChanged();
335 void LocationBarViewMac::SetTranslateIconLit(bool on) {
336   translate_decoration_->SetLit(on);
337   OnDecorationsChanged();
340 void LocationBarViewMac::ZoomChangedForActiveTab(bool can_show_bubble) {
341   UpdateZoomDecoration();
342   OnDecorationsChanged();
344   if (can_show_bubble && zoom_decoration_->IsVisible())
345     zoom_decoration_->ShowBubble(YES);
348 bool LocationBarViewMac::IsStarEnabled() const {
349   return browser_defaults::bookmarks_enabled &&
350          [field_ isEditable] &&
351          !GetToolbarModel()->input_in_progress() &&
352          edit_bookmarks_enabled_.GetValue() &&
353          !IsBookmarkStarHiddenByExtension();
356 NSPoint LocationBarViewMac::GetBookmarkBubblePoint() const {
357   DCHECK(IsStarEnabled());
358   return [field_ bubblePointForDecoration:star_decoration_.get()];
361 NSPoint LocationBarViewMac::GetTranslateBubblePoint() const {
362   return [field_ bubblePointForDecoration:translate_decoration_.get()];
365 NSPoint LocationBarViewMac::GetPageInfoBubblePoint() const {
366   if (origin_chip_decoration_ && origin_chip_decoration_->IsVisible()) {
367     return [field_ bubblePointForDecoration:origin_chip_decoration_.get()];
368   } else if (ev_bubble_decoration_->IsVisible()) {
369     return [field_ bubblePointForDecoration:ev_bubble_decoration_.get()];
370   } else {
371     return [field_ bubblePointForDecoration:location_icon_decoration_.get()];
372   }
375 NSPoint LocationBarViewMac::GetGeneratedCreditCardBubblePoint() const {
376   return
377       [field_ bubblePointForDecoration:generated_credit_card_decoration_.get()];
380 void LocationBarViewMac::OnDecorationsChanged() {
381   // TODO(shess): The field-editor frame and cursor rects should not
382   // change, here.
383   [field_ updateMouseTracking];
384   [field_ resetFieldEditorFrameIfNeeded];
385   [field_ setNeedsDisplay:YES];
388 // TODO(shess): This function should over time grow to closely match
389 // the views Layout() function.
390 void LocationBarViewMac::Layout() {
391   AutocompleteTextFieldCell* cell = [field_ cell];
393   // Reset the left-hand decorations.
394   // TODO(shess): Shortly, this code will live somewhere else, like in
395   // the constructor.  I am still wrestling with how best to deal with
396   // right-hand decorations, which are not a static set.
397   [cell clearDecorations];
398   if (origin_chip_decoration_.get())
399     [cell addLeftDecoration:origin_chip_decoration_.get()];
400   [cell addLeftDecoration:location_icon_decoration_.get()];
401   [cell addLeftDecoration:selected_keyword_decoration_.get()];
402   if (!origin_chip_decoration_.get())
403     [cell addLeftDecoration:ev_bubble_decoration_.get()];
404   [cell addRightDecoration:search_button_decoration_.get()];
405   [cell addRightDecoration:star_decoration_.get()];
406   [cell addRightDecoration:translate_decoration_.get()];
407   [cell addRightDecoration:zoom_decoration_.get()];
408   [cell addRightDecoration:generated_credit_card_decoration_.get()];
410   // Note that display order is right to left.
411   for (size_t i = 0; i < page_action_decorations_.size(); ++i) {
412     [cell addRightDecoration:page_action_decorations_[i]];
413   }
415   for (ScopedVector<ContentSettingDecoration>::iterator i =
416        content_setting_decorations_.begin();
417        i != content_setting_decorations_.end(); ++i) {
418     [cell addRightDecoration:*i];
419   }
421   [cell addRightDecoration:keyword_hint_decoration_.get()];
422   [cell addRightDecoration:mic_search_decoration_.get()];
424   // By default only the location icon is visible.
425   location_icon_decoration_->SetVisible(!origin_chip_decoration_.get() ||
426                                         !origin_chip_decoration_->IsVisible());
427   selected_keyword_decoration_->SetVisible(false);
428   ev_bubble_decoration_->SetVisible(false);
429   keyword_hint_decoration_->SetVisible(false);
431   // Get the keyword to use for keyword-search and hinting.
432   const base::string16 keyword = omnibox_view_->model()->keyword();
433   base::string16 short_name;
434   bool is_extension_keyword = false;
435   if (!keyword.empty()) {
436     short_name = TemplateURLServiceFactory::GetForProfile(profile())->
437         GetKeywordShortName(keyword, &is_extension_keyword);
438   }
440   const bool is_keyword_hint = omnibox_view_->model()->is_keyword_hint();
441   if (!keyword.empty() && !is_keyword_hint) {
442     // Switch from location icon to keyword mode.
443     location_icon_decoration_->SetVisible(false);
444     selected_keyword_decoration_->SetVisible(true);
445     selected_keyword_decoration_->SetKeyword(short_name, is_extension_keyword);
446     selected_keyword_decoration_->SetImage(GetKeywordImage(keyword));
447   } else if ((GetToolbarModel()->GetSecurityLevel(false) ==
448               ToolbarModel::EV_SECURE) && !origin_chip_decoration_.get()) {
449     // Switch from location icon to show the EV bubble instead.
450     location_icon_decoration_->SetVisible(false);
451     ev_bubble_decoration_->SetVisible(true);
453     base::string16 label(GetToolbarModel()->GetEVCertName());
454     ev_bubble_decoration_->SetFullLabel(base::SysUTF16ToNSString(label));
455   } else if (!keyword.empty() && is_keyword_hint) {
456     keyword_hint_decoration_->SetKeyword(short_name,
457                                          is_extension_keyword);
458     keyword_hint_decoration_->SetVisible(true);
459   }
461   // These need to change anytime the layout changes.
462   // TODO(shess): Anytime the field editor might have changed, the
463   // cursor rects almost certainly should have changed.  The tooltips
464   // might change even when the rects don't change.
465   OnDecorationsChanged();
468 void LocationBarViewMac::RedrawDecoration(LocationBarDecoration* decoration) {
469   AutocompleteTextFieldCell* cell = [field_ cell];
470   NSRect frame = [cell frameForDecoration:decoration
471                                   inFrame:[field_ bounds]];
472   if (!NSIsEmptyRect(frame))
473     [field_ setNeedsDisplayInRect:frame];
476 void LocationBarViewMac::SetPreviewEnabledPageAction(
477     ExtensionAction* page_action, bool preview_enabled) {
478   DCHECK(page_action);
479   WebContents* contents = GetWebContents();
480   if (!contents)
481     return;
482   RefreshPageActionDecorations();
483   Layout();
485   PageActionDecoration* decoration = GetPageActionDecoration(page_action);
486   DCHECK(decoration);
487   if (!decoration)
488     return;
490   decoration->set_preview_enabled(preview_enabled);
491   decoration->UpdateVisibility(contents, GetToolbarModel()->GetURL());
494 NSRect LocationBarViewMac::GetPageActionFrame(ExtensionAction* page_action) {
495   PageActionDecoration* decoration = GetPageActionDecoration(page_action);
496   if (!decoration)
497     return NSZeroRect;
499   AutocompleteTextFieldCell* cell = [field_ cell];
500   NSRect frame = [cell frameForDecoration:decoration inFrame:[field_ bounds]];
501   return frame;
504 NSPoint LocationBarViewMac::GetPageActionBubblePoint(
505     ExtensionAction* page_action) {
506   PageActionDecoration* decoration = GetPageActionDecoration(page_action);
507   if (!decoration)
508     return NSZeroPoint;
510   NSRect frame = GetPageActionFrame(page_action);
511   if (NSIsEmptyRect(frame)) {
512     // The bubble point positioning assumes that the page action is visible. If
513     // not, something else needs to be done otherwise the bubble will appear
514     // near the top left corner (unanchored).
515     NOTREACHED();
516     return NSZeroPoint;
517   }
519   NSPoint bubble_point = decoration->GetBubblePointInFrame(frame);
520   return [field_ convertPoint:bubble_point toView:nil];
523 void LocationBarViewMac::Update(const WebContents* contents) {
524   UpdateStarDecorationVisibility();
525   UpdateTranslateDecoration();
526   UpdateZoomDecoration();
527   RefreshPageActionDecorations();
528   RefreshContentSettingsDecorations();
529   UpdateMicSearchDecorationVisibility();
530   UpdateGeneratedCreditCardView();
531   if (contents)
532     omnibox_view_->OnTabChanged(contents);
533   else
534     omnibox_view_->Update();
535   OnChanged();
538 void LocationBarViewMac::OnChanged() {
539   // Update the location-bar icon.
540   const int resource_id = omnibox_view_->GetIcon();
541   NSImage* image = OmniboxViewMac::ImageForResource(resource_id);
542   location_icon_decoration_->SetImage(image);
543   ev_bubble_decoration_->SetImage(image);
545   if (origin_chip_decoration_.get())
546     origin_chip_decoration_->Update();
548   ToolbarModel* toolbar_model = GetToolbarModel();
549   const chrome::DisplaySearchButtonConditions conditions =
550       chrome::GetDisplaySearchButtonConditions();
551   const bool meets_conditions =
552       (conditions == chrome::DISPLAY_SEARCH_BUTTON_ALWAYS) ||
553       ((conditions != chrome::DISPLAY_SEARCH_BUTTON_NEVER) &&
554        (toolbar_model->WouldPerformSearchTermReplacement(true) ||
555         ((conditions == chrome::DISPLAY_SEARCH_BUTTON_FOR_STR_OR_IIP) &&
556          toolbar_model->input_in_progress())));
557   search_button_decoration_->SetVisible(
558       ![[field_ cell] isPopupMode] && meets_conditions);
559   search_button_decoration_->SetIcon(
560       (resource_id == IDR_OMNIBOX_SEARCH) ?
561           IDR_OMNIBOX_SEARCH_BUTTON_LOUPE : IDR_OMNIBOX_SEARCH_BUTTON_ARROW);
563   Layout();
565   InstantService* instant_service =
566       InstantServiceFactory::GetForProfile(profile());
567   if (instant_service) {
568     gfx::Rect bounds(NSRectToCGRect([field_ frame]));
569     instant_service->OnOmniboxStartMarginChanged(bounds.x());
570   }
573 void LocationBarViewMac::OnSetFocus() {
574   // Update the keyword and search hint states.
575   OnChanged();
578 void LocationBarViewMac::ShowURL() {
579   omnibox_view_->ShowURL();
582 void LocationBarViewMac::HideURL() {
583   omnibox_view_->HideURL();
586 InstantController* LocationBarViewMac::GetInstant() {
587   return browser_->instant_controller() ?
588       browser_->instant_controller()->instant() : NULL;
591 WebContents* LocationBarViewMac::GetWebContents() {
592   return browser_->tab_strip_model()->GetActiveWebContents();
595 ToolbarModel* LocationBarViewMac::GetToolbarModel() {
596   return browser_->toolbar_model();
599 const ToolbarModel* LocationBarViewMac::GetToolbarModel() const {
600   return browser_->toolbar_model();
603 NSImage* LocationBarViewMac::GetKeywordImage(const base::string16& keyword) {
604   const TemplateURL* template_url = TemplateURLServiceFactory::GetForProfile(
605       profile())->GetTemplateURLForKeyword(keyword);
606   if (template_url &&
607       (template_url->GetType() == TemplateURL::OMNIBOX_API_EXTENSION)) {
608     return extensions::OmniboxAPI::Get(profile())->
609         GetOmniboxIcon(template_url->GetExtensionId()).AsNSImage();
610   }
612   return OmniboxViewMac::ImageForResource(IDR_OMNIBOX_SEARCH);
615 void LocationBarViewMac::Observe(int type,
616                                  const content::NotificationSource& source,
617                                  const content::NotificationDetails& details) {
618   switch (type) {
619     case chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED: {
620       WebContents* contents = GetWebContents();
621       if (content::Details<WebContents>(contents) != details)
622         return;
624       [field_ updateMouseTracking];
625       [field_ setNeedsDisplay:YES];
626       break;
627     }
629     case chrome::NOTIFICATION_EXTENSION_LOCATION_BAR_UPDATED: {
630       // Only update if the updated action box was for the active tab contents.
631       WebContents* target_tab = content::Details<WebContents>(details).ptr();
632       if (target_tab == GetWebContents())
633         UpdatePageActions();
634       break;
635     }
637     case chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED:
638     case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED:
639       Update(NULL);
640       break;
642     default:
643       NOTREACHED() << "Unexpected notification";
644       break;
645   }
648 void LocationBarViewMac::ModelChanged(const SearchModel::State& old_state,
649                                       const SearchModel::State& new_state) {
650   if (UpdateMicSearchDecorationVisibility())
651     Layout();
654 void LocationBarViewMac::ActivatePageAction(const std::string& extension_id) {
655   for (size_t i = 0; i < page_action_decorations_.size(); ++i) {
656     if (page_action_decorations_[i]->page_action()->extension_id() ==
657         extension_id) {
658       page_action_decorations_[i]->ActivatePageAction();
659       return;
660     }
661   }
664 void LocationBarViewMac::PostNotification(NSString* notification) {
665   [[NSNotificationCenter defaultCenter] postNotificationName:notification
666                                         object:[NSValue valueWithPointer:this]];
669 PageActionDecoration* LocationBarViewMac::GetPageActionDecoration(
670     ExtensionAction* page_action) {
671   DCHECK(page_action);
672   for (size_t i = 0; i < page_action_decorations_.size(); ++i) {
673     if (page_action_decorations_[i]->page_action() == page_action)
674       return page_action_decorations_[i];
675   }
676   // If |page_action| is the browser action of an extension, no element in
677   // |page_action_decorations_| will match.
678   NOTREACHED();
679   return NULL;
683 void LocationBarViewMac::DeletePageActionDecorations() {
684   // TODO(shess): Deleting these decorations could result in the cell
685   // refering to them before things are laid out again.  Meanwhile, at
686   // least fail safe.
687   [[field_ cell] clearDecorations];
689   page_action_decorations_.clear();
692 void LocationBarViewMac::OnEditBookmarksEnabledChanged() {
693   UpdateStarDecorationVisibility();
694   OnChanged();
697 void LocationBarViewMac::RefreshPageActionDecorations() {
698   if (!IsEditable()) {
699     DeletePageActionDecorations();
700     return;
701   }
703   WebContents* web_contents = GetWebContents();
704   if (!web_contents) {
705     DeletePageActionDecorations();  // Necessary?
706     return;
707   }
709   std::vector<ExtensionAction*> new_page_actions =
710       extensions::TabHelper::FromWebContents(web_contents)->
711           location_bar_controller()->GetCurrentActions();
713   if (new_page_actions != page_actions_) {
714     page_actions_.swap(new_page_actions);
715     DeletePageActionDecorations();
716     for (size_t i = 0; i < page_actions_.size(); ++i) {
717       page_action_decorations_.push_back(
718           new PageActionDecoration(this, browser_, page_actions_[i]));
719     }
721     // Move rightmost extensions to the start.
722     std::stable_partition(
723         page_action_decorations_.begin(),
724         page_action_decorations_.end(),
725         IsPageActionViewRightAligned(
726             extensions::ExtensionSystem::Get(profile())->extension_service()));
727   }
729   GURL url = GetToolbarModel()->GetURL();
730   for (size_t i = 0; i < page_action_decorations_.size(); ++i) {
731     page_action_decorations_[i]->UpdateVisibility(
732         GetToolbarModel()->input_in_progress() ? NULL : web_contents, url);
733   }
736 bool LocationBarViewMac::RefreshContentSettingsDecorations() {
737   const bool input_in_progress = GetToolbarModel()->input_in_progress();
738   WebContents* web_contents = input_in_progress ?
739       NULL : browser_->tab_strip_model()->GetActiveWebContents();
740   bool icons_updated = false;
741   for (size_t i = 0; i < content_setting_decorations_.size(); ++i) {
742     icons_updated |=
743         content_setting_decorations_[i]->UpdateFromWebContents(web_contents);
744   }
745   return icons_updated;
748 void LocationBarViewMac::ShowFirstRunBubbleInternal() {
749   if (!field_ || ![field_ window])
750     return;
752   // The first run bubble's left edge should line up with the left edge of the
753   // omnibox. This is different from other bubbles, which line up at a point
754   // set by their top arrow. Because the BaseBubbleController adjusts the
755   // window origin left to account for the arrow spacing, the first run bubble
756   // moves the window origin right by this spacing, so that the
757   // BaseBubbleController will move it back to the correct position.
758   const NSPoint kOffset = NSMakePoint(
759       info_bubble::kBubbleArrowXOffset + info_bubble::kBubbleArrowWidth/2.0,
760       kFirstRunBubbleYOffset);
761   [FirstRunBubbleController showForView:field_
762                                  offset:kOffset
763                                 browser:browser_
764                                 profile:profile()];
767 void LocationBarViewMac::UpdateTranslateDecoration() {
768   if (!TranslateService::IsTranslateBubbleEnabled())
769     return;
771   WebContents* web_contents = GetWebContents();
772   if (!web_contents)
773     return;
774   LanguageState& language_state =
775       TranslateTabHelper::FromWebContents(web_contents)->GetLanguageState();
776   bool enabled = language_state.translate_enabled();
777   command_updater()->UpdateCommandEnabled(IDC_TRANSLATE_PAGE, enabled);
778   translate_decoration_->SetVisible(enabled);
779   translate_decoration_->SetLit(language_state.IsPageTranslated());
782 void LocationBarViewMac::UpdateZoomDecoration() {
783   WebContents* web_contents = GetWebContents();
784   if (!web_contents)
785     return;
787   zoom_decoration_->Update(ZoomController::FromWebContents(web_contents));
790 void LocationBarViewMac::UpdateStarDecorationVisibility() {
791   star_decoration_->SetVisible(IsStarEnabled());
794 bool LocationBarViewMac::UpdateMicSearchDecorationVisibility() {
795   bool is_visible = !GetToolbarModel()->input_in_progress() &&
796                     browser_->search_model()->voice_search_supported();
797   if (mic_search_decoration_->IsVisible() == is_visible)
798     return false;
799   mic_search_decoration_->SetVisible(is_visible);
800   return true;