Revert of Move SecurityLevel into a class of its own (patchset #19 id:420001 of https...
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / location_bar / location_bar_view_mac.mm
blobea1395aec319b248c69d6471e5f29f83656ba9b3
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/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/location_bar_controller.h"
23 #include "chrome/browser/extensions/tab_helper.h"
24 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/browser/search/instant_service.h"
26 #include "chrome/browser/search/instant_service_factory.h"
27 #include "chrome/browser/search/search.h"
28 #include "chrome/browser/search_engines/template_url_service_factory.h"
29 #include "chrome/browser/translate/chrome_translate_client.h"
30 #include "chrome/browser/translate/translate_service.h"
31 #include "chrome/browser/ui/browser_instant_controller.h"
32 #include "chrome/browser/ui/browser_list.h"
33 #import "chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.h"
34 #import "chrome/browser/ui/cocoa/extensions/extension_popup_controller.h"
35 #import "chrome/browser/ui/cocoa/first_run_bubble_controller.h"
36 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h"
37 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.h"
38 #import "chrome/browser/ui/cocoa/location_bar/content_setting_decoration.h"
39 #import "chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.h"
40 #import "chrome/browser/ui/cocoa/location_bar/generated_credit_card_decoration.h"
41 #import "chrome/browser/ui/cocoa/location_bar/keyword_hint_decoration.h"
42 #import "chrome/browser/ui/cocoa/location_bar/location_icon_decoration.h"
43 #import "chrome/browser/ui/cocoa/location_bar/manage_passwords_decoration.h"
44 #import "chrome/browser/ui/cocoa/location_bar/mic_search_decoration.h"
45 #import "chrome/browser/ui/cocoa/location_bar/page_action_decoration.h"
46 #import "chrome/browser/ui/cocoa/location_bar/selected_keyword_decoration.h"
47 #import "chrome/browser/ui/cocoa/location_bar/star_decoration.h"
48 #import "chrome/browser/ui/cocoa/location_bar/translate_decoration.h"
49 #import "chrome/browser/ui/cocoa/location_bar/zoom_decoration.h"
50 #import "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
51 #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
52 #include "chrome/browser/ui/content_settings/content_setting_image_model.h"
53 #import "chrome/browser/ui/omnibox/omnibox_popup_model.h"
54 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
55 #include "chrome/browser/ui/tabs/tab_strip_model.h"
56 #include "chrome/browser/ui/toolbar/toolbar_model.h"
57 #include "chrome/common/chrome_switches.h"
58 #include "chrome/common/pref_names.h"
59 #include "components/search_engines/template_url.h"
60 #include "components/search_engines/template_url_service.h"
61 #include "components/translate/core/browser/language_state.h"
62 #include "components/ui/zoom/zoom_controller.h"
63 #include "components/ui/zoom/zoom_event_manager.h"
64 #include "content/public/browser/web_contents.h"
65 #include "extensions/browser/extension_system.h"
66 #include "extensions/common/extension.h"
67 #include "grit/components_scaled_resources.h"
68 #include "grit/theme_resources.h"
69 #include "net/base/net_util.h"
70 #include "skia/ext/skia_utils_mac.h"
71 #import "ui/base/cocoa/cocoa_base_utils.h"
72 #include "ui/base/l10n/l10n_util_mac.h"
73 #include "ui/gfx/image/image.h"
75 using content::WebContents;
77 namespace {
79 // Vertical space between the bottom edge of the location_bar and the first run
80 // bubble arrow point.
81 const static int kFirstRunBubbleYOffset = 1;
83 }  // namespace
85 // TODO(shess): This code is mostly copied from the gtk
86 // implementation.  Make sure it's all appropriate and flesh it out.
88 LocationBarViewMac::LocationBarViewMac(AutocompleteTextField* field,
89                                        CommandUpdater* command_updater,
90                                        Profile* profile,
91                                        Browser* browser)
92     : LocationBar(profile),
93       OmniboxEditController(command_updater),
94       omnibox_view_(new OmniboxViewMac(this, profile, command_updater, field)),
95       field_(field),
96       location_icon_decoration_(new LocationIconDecoration(this)),
97       selected_keyword_decoration_(new SelectedKeywordDecoration()),
98       ev_bubble_decoration_(
99           new EVBubbleDecoration(location_icon_decoration_.get())),
100       star_decoration_(new StarDecoration(command_updater)),
101       translate_decoration_(new TranslateDecoration(command_updater)),
102       zoom_decoration_(new ZoomDecoration(this)),
103       keyword_hint_decoration_(new KeywordHintDecoration()),
104       mic_search_decoration_(new MicSearchDecoration(command_updater)),
105       generated_credit_card_decoration_(
106           new GeneratedCreditCardDecoration(this)),
107       manage_passwords_decoration_(
108           new ManagePasswordsDecoration(command_updater, this)),
109       browser_(browser),
110       weak_ptr_factory_(this) {
111   for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
112     DCHECK_EQ(i, content_setting_decorations_.size());
113     ContentSettingsType type = static_cast<ContentSettingsType>(i);
114     content_setting_decorations_.push_back(
115         new ContentSettingDecoration(type, this, profile));
116   }
118   edit_bookmarks_enabled_.Init(
119       bookmarks::prefs::kEditBookmarksEnabled, profile->GetPrefs(),
120       base::Bind(&LocationBarViewMac::OnEditBookmarksEnabledChanged,
121                  base::Unretained(this)));
123   browser_->search_model()->AddObserver(this);
125   ui_zoom::ZoomEventManager::GetForBrowserContext(profile)
126       ->AddZoomEventManagerObserver(this);
128   [[field_ cell] setIsPopupMode:
129       !browser->SupportsWindowFeature(Browser::FEATURE_TABSTRIP)];
131   // Sets images for the decorations, and performs a layout. This call ensures
132   // that this class is in a consistent state after initialization.
133   OnChanged();
136 LocationBarViewMac::~LocationBarViewMac() {
137   // Disconnect from cell in case it outlives us.
138   [[field_ cell] clearDecorations];
140   browser_->search_model()->RemoveObserver(this);
141   ui_zoom::ZoomEventManager::GetForBrowserContext(profile())
142       ->RemoveZoomEventManagerObserver(this);
145 void LocationBarViewMac::ShowFirstRunBubble() {
146   // We need the browser window to be shown before we can show the bubble, but
147   // we get called before that's happened.
148   base::MessageLoop::current()->PostTask(
149       FROM_HERE, base::Bind(&LocationBarViewMac::ShowFirstRunBubbleInternal,
150                             weak_ptr_factory_.GetWeakPtr()));
153 GURL LocationBarViewMac::GetDestinationURL() const {
154   return destination_url();
157 WindowOpenDisposition LocationBarViewMac::GetWindowOpenDisposition() const {
158   return disposition();
161 ui::PageTransition LocationBarViewMac::GetPageTransition() const {
162   return transition();
165 void LocationBarViewMac::AcceptInput() {
166   WindowOpenDisposition disposition =
167       ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
168   omnibox_view_->model()->AcceptInput(disposition, false);
171 void LocationBarViewMac::FocusLocation(bool select_all) {
172   omnibox_view_->FocusLocation(select_all);
175 void LocationBarViewMac::FocusSearch() {
176   omnibox_view_->SetForcedQuery();
179 void LocationBarViewMac::UpdateContentSettingsIcons() {
180   if (RefreshContentSettingsDecorations())
181     OnDecorationsChanged();
184 void LocationBarViewMac::UpdateManagePasswordsIconAndBubble() {
185   WebContents* web_contents = GetWebContents();
186   if (!web_contents)
187     return;
188   ManagePasswordsUIController::FromWebContents(web_contents)
189       ->UpdateIconAndBubbleState(manage_passwords_decoration_->icon());
190   OnDecorationsChanged();
193 void LocationBarViewMac::UpdatePageActions() {
194   RefreshPageActionDecorations();
195   Layout();
197   [field_ updateMouseTracking];
198   [field_ setNeedsDisplay:YES];
201 void LocationBarViewMac::UpdateBookmarkStarVisibility() {
202   star_decoration_->SetVisible(IsStarEnabled());
205 void LocationBarViewMac::UpdateLocationBarVisibility(bool visible,
206                                                      bool animate) {
207   // Not implemented on Mac.
210 bool LocationBarViewMac::ShowPageActionPopup(
211     const extensions::Extension* extension, bool grant_active_tab) {
212   for (ScopedVector<PageActionDecoration>::iterator iter =
213            page_action_decorations_.begin();
214        iter != page_action_decorations_.end(); ++iter) {
215     if ((*iter)->GetExtension() == extension)
216       return (*iter)->ActivatePageAction(grant_active_tab);
217   }
218   return false;
221 void LocationBarViewMac::UpdateOpenPDFInReaderPrompt() {
222   // Not implemented on Mac.
225 void LocationBarViewMac::UpdateGeneratedCreditCardView() {
226   generated_credit_card_decoration_->Update();
229 void LocationBarViewMac::SaveStateToContents(WebContents* contents) {
230   // TODO(shess): Why SaveStateToContents vs SaveStateToTab?
231   omnibox_view_->SaveStateToTab(contents);
234 void LocationBarViewMac::Revert() {
235   omnibox_view_->RevertAll();
238 const OmniboxView* LocationBarViewMac::GetOmniboxView() const {
239   return omnibox_view_.get();
242 OmniboxView* LocationBarViewMac::GetOmniboxView() {
243   return omnibox_view_.get();
246 LocationBarTesting* LocationBarViewMac::GetLocationBarForTesting() {
247   return this;
250 // TODO(pamg): Change all these, here and for other platforms, to size_t.
251 int LocationBarViewMac::PageActionCount() {
252   return static_cast<int>(page_action_decorations_.size());
255 int LocationBarViewMac::PageActionVisibleCount() {
256   int result = 0;
257   for (size_t i = 0; i < page_action_decorations_.size(); ++i) {
258     if (page_action_decorations_[i]->IsVisible())
259       ++result;
260   }
261   return result;
264 ExtensionAction* LocationBarViewMac::GetPageAction(size_t index) {
265   if (index < page_action_decorations_.size())
266     return page_action_decorations_[index]->GetPageAction();
267   NOTREACHED();
268   return NULL;
271 ExtensionAction* LocationBarViewMac::GetVisiblePageAction(size_t index) {
272   size_t current = 0;
273   for (size_t i = 0; i < page_action_decorations_.size(); ++i) {
274     if (page_action_decorations_[i]->IsVisible()) {
275       if (current == index)
276         return page_action_decorations_[i]->GetPageAction();
278       ++current;
279     }
280   }
282   NOTREACHED();
283   return NULL;
286 void LocationBarViewMac::TestPageActionPressed(size_t index) {
287   DCHECK_LT(index, static_cast<size_t>(PageActionVisibleCount()));
288   size_t current = 0;
289   for (PageActionDecoration* decoration : page_action_decorations_) {
290     if (decoration->IsVisible()) {
291       if (current == index) {
292         decoration->OnMousePressed(NSZeroRect, NSZeroPoint);
293         return;
294       }
295       ++current;
296     }
297   }
300 bool LocationBarViewMac::GetBookmarkStarVisibility() {
301   DCHECK(star_decoration_.get());
302   return star_decoration_->IsVisible();
305 void LocationBarViewMac::SetEditable(bool editable) {
306   [field_ setEditable:editable ? YES : NO];
307   UpdateBookmarkStarVisibility();
308   UpdateZoomDecoration(/*default_zoom_changed=*/false);
309   UpdatePageActions();
310   Layout();
313 bool LocationBarViewMac::IsEditable() {
314   return [field_ isEditable] ? true : false;
317 void LocationBarViewMac::SetStarred(bool starred) {
318   if (star_decoration_->starred() == starred)
319     return;
321   star_decoration_->SetStarred(starred);
322   UpdateBookmarkStarVisibility();
323   OnDecorationsChanged();
326 void LocationBarViewMac::SetTranslateIconLit(bool on) {
327   translate_decoration_->SetLit(on);
328   OnDecorationsChanged();
331 void LocationBarViewMac::ZoomChangedForActiveTab(bool can_show_bubble) {
332   bool changed = UpdateZoomDecoration(/*default_zoom_changed=*/false);
333   if (changed)
334     OnDecorationsChanged();
336   if (can_show_bubble && zoom_decoration_->IsVisible())
337     zoom_decoration_->ShowBubble(YES);
340 bool LocationBarViewMac::IsStarEnabled() const {
341   return browser_defaults::bookmarks_enabled &&
342          [field_ isEditable] &&
343          !GetToolbarModel()->input_in_progress() &&
344          edit_bookmarks_enabled_.GetValue() &&
345          !IsBookmarkStarHiddenByExtension();
348 NSPoint LocationBarViewMac::GetBookmarkBubblePoint() const {
349   DCHECK(IsStarEnabled());
350   return [field_ bubblePointForDecoration:star_decoration_.get()];
353 NSPoint LocationBarViewMac::GetTranslateBubblePoint() const {
354   return [field_ bubblePointForDecoration:translate_decoration_.get()];
357 NSPoint LocationBarViewMac::GetManagePasswordsBubblePoint() const {
358   return [field_ bubblePointForDecoration:manage_passwords_decoration_.get()];
361 NSPoint LocationBarViewMac::GetPageInfoBubblePoint() const {
362   if (ev_bubble_decoration_->IsVisible()) {
363     return [field_ bubblePointForDecoration:ev_bubble_decoration_.get()];
364   } else {
365     return [field_ bubblePointForDecoration:location_icon_decoration_.get()];
366   }
369 NSPoint LocationBarViewMac::GetGeneratedCreditCardBubblePoint() const {
370   return
371       [field_ bubblePointForDecoration:generated_credit_card_decoration_.get()];
374 void LocationBarViewMac::OnDecorationsChanged() {
375   // TODO(shess): The field-editor frame and cursor rects should not
376   // change, here.
377   [field_ updateMouseTracking];
378   [field_ resetFieldEditorFrameIfNeeded];
379   [field_ setNeedsDisplay:YES];
382 // TODO(shess): This function should over time grow to closely match
383 // the views Layout() function.
384 void LocationBarViewMac::Layout() {
385   AutocompleteTextFieldCell* cell = [field_ cell];
387   // Reset the left-hand decorations.
388   // TODO(shess): Shortly, this code will live somewhere else, like in
389   // the constructor.  I am still wrestling with how best to deal with
390   // right-hand decorations, which are not a static set.
391   [cell clearDecorations];
392   [cell addLeftDecoration:location_icon_decoration_.get()];
393   [cell addLeftDecoration:selected_keyword_decoration_.get()];
394   [cell addLeftDecoration:ev_bubble_decoration_.get()];
395   [cell addRightDecoration:star_decoration_.get()];
396   [cell addRightDecoration:translate_decoration_.get()];
397   [cell addRightDecoration:zoom_decoration_.get()];
398   [cell addRightDecoration:generated_credit_card_decoration_.get()];
399   [cell addRightDecoration:manage_passwords_decoration_.get()];
401   // Note that display order is right to left.
402   for (size_t i = 0; i < page_action_decorations_.size(); ++i) {
403     [cell addRightDecoration:page_action_decorations_[i]];
404   }
406   for (ScopedVector<ContentSettingDecoration>::iterator i =
407        content_setting_decorations_.begin();
408        i != content_setting_decorations_.end(); ++i) {
409     [cell addRightDecoration:*i];
410   }
412   [cell addRightDecoration:keyword_hint_decoration_.get()];
413   [cell addRightDecoration:mic_search_decoration_.get()];
415   // By default only the location icon is visible.
416   location_icon_decoration_->SetVisible(true);
417   selected_keyword_decoration_->SetVisible(false);
418   ev_bubble_decoration_->SetVisible(false);
419   keyword_hint_decoration_->SetVisible(false);
421   // Get the keyword to use for keyword-search and hinting.
422   const base::string16 keyword = omnibox_view_->model()->keyword();
423   base::string16 short_name;
424   bool is_extension_keyword = false;
425   if (!keyword.empty()) {
426     short_name = TemplateURLServiceFactory::GetForProfile(profile())->
427         GetKeywordShortName(keyword, &is_extension_keyword);
428   }
430   const bool is_keyword_hint = omnibox_view_->model()->is_keyword_hint();
431   if (!keyword.empty() && !is_keyword_hint) {
432     // Switch from location icon to keyword mode.
433     location_icon_decoration_->SetVisible(false);
434     selected_keyword_decoration_->SetVisible(true);
435     selected_keyword_decoration_->SetKeyword(short_name, is_extension_keyword);
436     selected_keyword_decoration_->SetImage(GetKeywordImage(keyword));
437   } else if ((GetToolbarModel()->GetSecurityLevel(false) ==
438               ToolbarModel::EV_SECURE)) {
439     // Switch from location icon to show the EV bubble instead.
440     location_icon_decoration_->SetVisible(false);
441     ev_bubble_decoration_->SetVisible(true);
443     base::string16 label(GetToolbarModel()->GetEVCertName());
444     ev_bubble_decoration_->SetFullLabel(base::SysUTF16ToNSString(label));
445   } else if (!keyword.empty() && is_keyword_hint) {
446     keyword_hint_decoration_->SetKeyword(short_name,
447                                          is_extension_keyword);
448     keyword_hint_decoration_->SetVisible(true);
449   }
451   // These need to change anytime the layout changes.
452   // TODO(shess): Anytime the field editor might have changed, the
453   // cursor rects almost certainly should have changed.  The tooltips
454   // might change even when the rects don't change.
455   OnDecorationsChanged();
458 void LocationBarViewMac::RedrawDecoration(LocationBarDecoration* decoration) {
459   AutocompleteTextFieldCell* cell = [field_ cell];
460   NSRect frame = [cell frameForDecoration:decoration
461                                   inFrame:[field_ bounds]];
462   if (!NSIsEmptyRect(frame))
463     [field_ setNeedsDisplayInRect:frame];
466 void LocationBarViewMac::SetPreviewEnabledPageAction(
467     ExtensionAction* page_action, bool preview_enabled) {
468   DCHECK(page_action);
469   WebContents* contents = GetWebContents();
470   if (!contents)
471     return;
472   RefreshPageActionDecorations();
473   Layout();
475   PageActionDecoration* decoration = GetPageActionDecoration(page_action);
476   DCHECK(decoration);
477   if (!decoration)
478     return;
480   decoration->set_preview_enabled(preview_enabled);
481   decoration->UpdateVisibility(contents);
484 NSRect LocationBarViewMac::GetPageActionFrame(ExtensionAction* page_action) {
485   PageActionDecoration* decoration = GetPageActionDecoration(page_action);
486   if (!decoration)
487     return NSZeroRect;
489   AutocompleteTextFieldCell* cell = [field_ cell];
490   NSRect frame = [cell frameForDecoration:decoration inFrame:[field_ bounds]];
491   return frame;
494 NSPoint LocationBarViewMac::GetPageActionBubblePoint(
495     ExtensionAction* page_action) {
496   PageActionDecoration* decoration = GetPageActionDecoration(page_action);
497   if (!decoration)
498     return NSZeroPoint;
500   NSRect frame = GetPageActionFrame(page_action);
501   if (NSIsEmptyRect(frame)) {
502     // The bubble point positioning assumes that the page action is visible. If
503     // not, something else needs to be done otherwise the bubble will appear
504     // near the top left corner (unanchored).
505     NOTREACHED();
506     return NSZeroPoint;
507   }
509   NSPoint bubble_point = decoration->GetBubblePointInFrame(frame);
510   return [field_ convertPoint:bubble_point toView:nil];
513 void LocationBarViewMac::ResetTabState(WebContents* contents) {
514   omnibox_view_->ResetTabState(contents);
517 void LocationBarViewMac::Update(const WebContents* contents) {
518   UpdateManagePasswordsIconAndBubble();
519   UpdateBookmarkStarVisibility();
520   UpdateTranslateDecoration();
521   UpdateZoomDecoration(/*default_zoom_changed=*/false);
522   RefreshPageActionDecorations();
523   RefreshContentSettingsDecorations();
524   UpdateMicSearchDecorationVisibility();
525   UpdateGeneratedCreditCardView();
526   if (contents)
527     omnibox_view_->OnTabChanged(contents);
528   else
529     omnibox_view_->Update();
530   OnChanged();
533 void LocationBarViewMac::OnChanged() {
534   // Update the location-bar icon.
535   const int resource_id = omnibox_view_->GetIcon();
536   NSImage* image = OmniboxViewMac::ImageForResource(resource_id);
537   location_icon_decoration_->SetImage(image);
538   ev_bubble_decoration_->SetImage(image);
539   Layout();
541   InstantService* instant_service =
542       InstantServiceFactory::GetForProfile(profile());
543   if (instant_service) {
544     gfx::Rect bounds(NSRectToCGRect([field_ frame]));
545     instant_service->OnOmniboxStartMarginChanged(bounds.x());
546   }
549 void LocationBarViewMac::OnSetFocus() {
550   // Update the keyword and search hint states.
551   OnChanged();
554 void LocationBarViewMac::ShowURL() {
555   omnibox_view_->ShowURL();
558 InstantController* LocationBarViewMac::GetInstant() {
559   return browser_->instant_controller() ?
560       browser_->instant_controller()->instant() : NULL;
563 WebContents* LocationBarViewMac::GetWebContents() {
564   return browser_->tab_strip_model()->GetActiveWebContents();
567 ToolbarModel* LocationBarViewMac::GetToolbarModel() {
568   return browser_->toolbar_model();
571 const ToolbarModel* LocationBarViewMac::GetToolbarModel() const {
572   return browser_->toolbar_model();
575 NSImage* LocationBarViewMac::GetKeywordImage(const base::string16& keyword) {
576   const TemplateURL* template_url = TemplateURLServiceFactory::GetForProfile(
577       profile())->GetTemplateURLForKeyword(keyword);
578   if (template_url &&
579       (template_url->GetType() == TemplateURL::OMNIBOX_API_EXTENSION)) {
580     return extensions::OmniboxAPI::Get(profile())->
581         GetOmniboxIcon(template_url->GetExtensionId()).AsNSImage();
582   }
584   return OmniboxViewMac::ImageForResource(IDR_OMNIBOX_SEARCH);
587 void LocationBarViewMac::ModelChanged(const SearchModel::State& old_state,
588                                       const SearchModel::State& new_state) {
589   if (UpdateMicSearchDecorationVisibility())
590     Layout();
593 void LocationBarViewMac::PostNotification(NSString* notification) {
594   [[NSNotificationCenter defaultCenter] postNotificationName:notification
595                                         object:[NSValue valueWithPointer:this]];
598 PageActionDecoration* LocationBarViewMac::GetPageActionDecoration(
599     ExtensionAction* page_action) {
600   DCHECK(page_action);
601   for (size_t i = 0; i < page_action_decorations_.size(); ++i) {
602     if (page_action_decorations_[i]->GetPageAction() == page_action)
603       return page_action_decorations_[i];
604   }
605   // If |page_action| is the browser action of an extension, no element in
606   // |page_action_decorations_| will match.
607   NOTREACHED();
608   return NULL;
611 void LocationBarViewMac::DeletePageActionDecorations() {
612   // TODO(shess): Deleting these decorations could result in the cell
613   // refering to them before things are laid out again.  Meanwhile, at
614   // least fail safe.
615   [[field_ cell] clearDecorations];
617   page_action_decorations_.clear();
620 void LocationBarViewMac::OnEditBookmarksEnabledChanged() {
621   UpdateBookmarkStarVisibility();
622   OnChanged();
625 void LocationBarViewMac::RefreshPageActionDecorations() {
626   if (!IsEditable()) {
627     DeletePageActionDecorations();
628     return;
629   }
631   WebContents* web_contents = GetWebContents();
632   if (!web_contents) {
633     DeletePageActionDecorations();
634     return;
635   }
637   std::vector<ExtensionAction*> new_page_actions =
638       extensions::TabHelper::FromWebContents(web_contents)->
639           location_bar_controller()->GetCurrentActions();
641   if (PageActionsDiffer(new_page_actions)) {
642     DeletePageActionDecorations();
643     for (size_t i = 0; i < new_page_actions.size(); ++i) {
644       page_action_decorations_.push_back(
645           new PageActionDecoration(this, browser_, new_page_actions[i]));
646     }
647   }
649   GURL url = GetToolbarModel()->GetURL();
650   for (size_t i = 0; i < page_action_decorations_.size(); ++i) {
651     page_action_decorations_[i]->UpdateVisibility(
652         GetToolbarModel()->input_in_progress() ? NULL : web_contents);
653   }
656 bool LocationBarViewMac::PageActionsDiffer(
657     const std::vector<ExtensionAction*>& page_actions) const {
658   if (page_action_decorations_.size() != page_actions.size())
659     return true;
661   for (size_t index = 0; index < page_actions.size(); ++index) {
662     PageActionDecoration* decoration = page_action_decorations_[index];
663     if (decoration->GetPageAction() != page_actions[index])
664       return true;
665   }
667   return false;
670 bool LocationBarViewMac::RefreshContentSettingsDecorations() {
671   const bool input_in_progress = GetToolbarModel()->input_in_progress();
672   WebContents* web_contents = input_in_progress ?
673       NULL : browser_->tab_strip_model()->GetActiveWebContents();
674   bool icons_updated = false;
675   for (size_t i = 0; i < content_setting_decorations_.size(); ++i) {
676     icons_updated |=
677         content_setting_decorations_[i]->UpdateFromWebContents(web_contents);
678   }
679   return icons_updated;
682 void LocationBarViewMac::ShowFirstRunBubbleInternal() {
683   if (!field_ || ![field_ window])
684     return;
686   // The first run bubble's left edge should line up with the left edge of the
687   // omnibox. This is different from other bubbles, which line up at a point
688   // set by their top arrow. Because the BaseBubbleController adjusts the
689   // window origin left to account for the arrow spacing, the first run bubble
690   // moves the window origin right by this spacing, so that the
691   // BaseBubbleController will move it back to the correct position.
692   const NSPoint kOffset = NSMakePoint(
693       info_bubble::kBubbleArrowXOffset + info_bubble::kBubbleArrowWidth/2.0,
694       kFirstRunBubbleYOffset);
695   [FirstRunBubbleController showForView:field_
696                                  offset:kOffset
697                                 browser:browser_
698                                 profile:profile()];
701 void LocationBarViewMac::UpdateTranslateDecoration() {
702   if (!TranslateService::IsTranslateBubbleEnabled())
703     return;
705   WebContents* web_contents = GetWebContents();
706   if (!web_contents)
707     return;
708   translate::LanguageState& language_state =
709       ChromeTranslateClient::FromWebContents(web_contents)->GetLanguageState();
710   bool enabled = language_state.translate_enabled();
711   command_updater()->UpdateCommandEnabled(IDC_TRANSLATE_PAGE, enabled);
712   translate_decoration_->SetVisible(enabled);
713   translate_decoration_->SetLit(language_state.IsPageTranslated());
716 bool LocationBarViewMac::UpdateZoomDecoration(bool default_zoom_changed) {
717   WebContents* web_contents = GetWebContents();
718   if (!web_contents)
719     return false;
721   return zoom_decoration_->UpdateIfNecessary(
722       ui_zoom::ZoomController::FromWebContents(web_contents),
723       default_zoom_changed);
726 void LocationBarViewMac::OnDefaultZoomLevelChanged() {
727   if (UpdateZoomDecoration(/*default_zoom_changed=*/true))
728     OnDecorationsChanged();
731 bool LocationBarViewMac::UpdateMicSearchDecorationVisibility() {
732   bool is_visible = !GetToolbarModel()->input_in_progress() &&
733                     browser_->search_model()->voice_search_supported();
734   if (mic_search_decoration_->IsVisible() == is_visible)
735     return false;
736   mic_search_decoration_->SetVisible(is_visible);
737   return true;