diff options
author | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-16 23:45:38 +0000 |
---|---|---|
committer | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-16 23:45:38 +0000 |
commit | 3263b45534a37c63cbc6d43506cf8cd9bb30bbef (patch) | |
tree | 08e2c955f659f9e518847b7e80e439c9f7a27ba0 /chrome/browser/cocoa | |
parent | 7803a0551ee242b5da6f646f1165276e13514818 (diff) | |
download | chromium_src-3263b45534a37c63cbc6d43506cf8cd9bb30bbef.zip chromium_src-3263b45534a37c63cbc6d43506cf8cd9bb30bbef.tar.gz chromium_src-3263b45534a37c63cbc6d43506cf8cd9bb30bbef.tar.bz2 |
Mac: Content blocked icons.
Also rewrite how omnibox icons are handled, to make it less repetitive to add the content blocked icons. Remove a O(n^2) while I'm at it.
BUG=35594,34894
TEST=Go to a page with popups. "popups blocked" icon should appear in omnibox. It should have a tooltip, and a normal arrow cursor on mouse over. Switching tabs should make it go away, coming back to the tab with the blocked popup should make it go back. Page actions should still work (tooltips, clicking, context menu, display). Security icon should still work. Install rss extension; the preview bubble should point to the right icon.
http://imgur.com/Yo0Ss
Review URL: http://codereview.chromium.org/600133
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@39158 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/cocoa')
10 files changed, 319 insertions, 181 deletions
diff --git a/chrome/browser/cocoa/autocomplete_text_field.mm b/chrome/browser/cocoa/autocomplete_text_field.mm index 2f263f7..488a8f2 100644 --- a/chrome/browser/cocoa/autocomplete_text_field.mm +++ b/chrome/browser/cocoa/autocomplete_text_field.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -115,21 +115,12 @@ return; } - // If the user clicked the security hint icon in the cell, display the page - // info window. - const NSRect hintIconFrame = [cell securityImageFrameForFrame:bounds]; - if (NSMouseInRect(location, hintIconFrame, flipped)) { - [cell onSecurityIconMousePressed]; - return; - } - + // If the user clicked on one of the icons (security icon, Page Actions, etc), + // let the icon handle the click. const BOOL ctrlKey = ([theEvent modifierFlags] & NSControlKeyMask) != 0; - // If the user left-clicked a Page Action icon, execute its action. - const size_t pageActionCount = [cell pageActionCount]; - for (size_t i = 0; i < pageActionCount; ++i) { - NSRect pageActionFrame = [cell pageActionFrameForIndex:i inFrame:bounds]; - if (NSMouseInRect(location, pageActionFrame, flipped) && !ctrlKey) { - [cell onPageActionMousePressedIn:pageActionFrame forIndex:i]; + for (AutocompleteTextFieldIcon* icon in [cell layedOutIcons:bounds]) { + if (NSMouseInRect(location, [icon rect], flipped) && !ctrlKey) { + [icon view]->OnMousePressed([icon rect]); return; } } @@ -204,14 +195,8 @@ [self addCursorRect:fieldBounds cursor:[NSCursor IBeamCursor]]; AutocompleteTextFieldCell* cell = [self autocompleteTextFieldCell]; - NSRect iconRect = [cell securityImageFrameForFrame:fieldBounds]; - [self addCursorRect:iconRect cursor:[NSCursor arrowCursor]]; - - const size_t pageActionCount = [cell pageActionCount]; - for (size_t i = 0; i < pageActionCount; ++i) { - iconRect = [cell pageActionFrameForIndex:i inFrame:fieldBounds]; - [self addCursorRect:iconRect cursor:[NSCursor arrowCursor]]; - } + for (AutocompleteTextFieldIcon* icon in [cell layedOutIcons:fieldBounds]) + [self addCursorRect:[icon rect] cursor:[NSCursor arrowCursor]]; } - (void)updateCursorAndToolTipRects { @@ -226,14 +211,13 @@ [currentToolTips_ removeAllObjects]; AutocompleteTextFieldCell* cell = [self autocompleteTextFieldCell]; - const size_t pageActionCount = [cell pageActionCount]; - for (size_t i = 0; i < pageActionCount; ++i) { - NSRect iconRect = [cell pageActionFrameForIndex:i inFrame:[self bounds]]; - NSString* tooltip = [cell pageActionToolTipForIndex:i]; + for (AutocompleteTextFieldIcon* icon in [cell layedOutIcons:[self bounds]]) { + NSRect iconRect = [icon rect]; + NSString* tooltip = [icon view]->GetToolTip(); if (!tooltip) continue; - // -[NSView addToolTipRect:owner:userData] does _not_ retain the owner! + // -[NSView addToolTipRect:owner:userData] does _not_ retain its |owner:|. // Put the string in a collection so it can't be dealloced while in use. [currentToolTips_ addObject:tooltip]; [self addToolTipRect:iconRect owner:tooltip userData:nil]; diff --git a/chrome/browser/cocoa/autocomplete_text_field_cell.h b/chrome/browser/cocoa/autocomplete_text_field_cell.h index bcd595e..3763e2c 100644 --- a/chrome/browser/cocoa/autocomplete_text_field_cell.h +++ b/chrome/browser/cocoa/autocomplete_text_field_cell.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -11,6 +11,24 @@ class ExtensionAction; +// Holds a |LocationBarImageView| and its current rect. Do not keep references +// to this object, only use it directly after calling |-layedOutIcons:|. +@interface AutocompleteTextFieldIcon : NSObject { + // The frame rect of |view_|. + NSRect rect_; + + // weak, owned by LocationBarViewMac. + LocationBarViewMac::LocationBarImageView* view_; +} + +// Returns a new AutocompleteTextFieldIcon object. ++ (AutocompleteTextFieldIcon*) + iconWithRect:(NSRect)rect + view:(LocationBarViewMac::LocationBarImageView*)view; +@property(assign, nonatomic) NSRect rect; +@property(assign, nonatomic) LocationBarViewMac::LocationBarImageView* view; +@end + // AutocompleteTextFieldCell extends StyledTextFieldCell to provide support for // certain decorations to be applied to the field. These are the search hint // ("Type to search" on the right-hand side), the keyword hint ("Press [Tab] to @@ -35,6 +53,9 @@ class ExtensionAction; // Display is exclusive WRT the |hintString_| and |keywordString_|. // This may be NULL during testing. LocationBarViewMac::PageActionViewList* page_action_views_; + + // List of content blocked icons. This may be NULL during testing. + LocationBarViewMac::ContentBlockedViews* content_blocked_views_; } // Chooses |partialString| if |width| won't fit |fullString|. Strings @@ -58,34 +79,21 @@ class ExtensionAction; - (void)setSecurityImageView:(LocationBarViewMac::SecurityImageView*)view; - (void)setPageActionViewList:(LocationBarViewMac::PageActionViewList*)list; +- (void)setContentBlockedViewList: + (LocationBarViewMac::ContentBlockedViews*)views; -// Returns the total number of installed Page Actions, visible or not. -- (size_t)pageActionCount; +// Returns an array of the visible AutocompleteTextFieldIcon objects. Returns +// only visible icons. +- (NSArray*)layedOutIcons:(NSRect)cellFrame; -// Called when the security icon is visible and clicked. Passed through to the -// security_image_view_ to handle the click (i.e., show the page info dialog). -- (void)onSecurityIconMousePressed; - -// Returns the portion of the cell to use for displaying the security (SSL lock) -// icon, leaving space for its label if any. -- (NSRect)securityImageFrameForFrame:(NSRect)cellFrame; // Returns the portion of the cell to use for displaying the Page Action icon // at the given index. May be NSZeroRect if the index's action is not visible. +// This does a linear walk over all page actions, so do not call this in a loop +// to get the position of all page actions. Use |-layedOutIcons:| instead in that +// case. - (NSRect)pageActionFrameForIndex:(size_t)index inFrame:(NSRect)cellFrame; -// Returns the string to be shown on hover for the Page Action icon at the -// given index. -- (NSString*)pageActionToolTipForIndex:(size_t)index; - -// Returns a pointer to the ExtensionAction object that the view at the -// specified index represents. -- (ExtensionAction*)pageActionForIndex:(size_t)index; - -// Called when the Page Action at the given index, whose icon is drawn in the -// iconFrame, is visible and clicked. Passed through to the list of views to -// handle the click. -- (void)onPageActionMousePressedIn:(NSRect)iconFrame forIndex:(size_t)index; @end @@ -96,4 +104,11 @@ class ExtensionAction; @property(readonly) NSAttributedString* hintString; @property(readonly) NSAttributedString* hintIconLabel; +// Returns the total number of installed Page Actions, visible or not. +- (size_t)pageActionCount; + +// Returns the portion of the cell to use for displaying the security (SSL lock) +// icon, leaving space for its label if any. +- (NSRect)securityImageFrameForFrame:(NSRect)cellFrame; + @end diff --git a/chrome/browser/cocoa/autocomplete_text_field_cell.mm b/chrome/browser/cocoa/autocomplete_text_field_cell.mm index 8558b80..8772f5a 100644 --- a/chrome/browser/cocoa/autocomplete_text_field_cell.mm +++ b/chrome/browser/cocoa/autocomplete_text_field_cell.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -57,6 +57,22 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) { } // namespace +@implementation AutocompleteTextFieldIcon + +@synthesize rect = rect_; +@synthesize view = view_; + ++ (AutocompleteTextFieldIcon*) + iconWithRect:(NSRect)rect + view:(LocationBarViewMac::LocationBarImageView*)view { + AutocompleteTextFieldIcon* result = [[AutocompleteTextFieldIcon alloc] init]; + [result setRect:rect]; + [result setView:view]; + return [result autorelease]; +} + +@end + @implementation AutocompleteTextFieldCell // @synthesize doesn't seem to compile for this transition. @@ -202,12 +218,9 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) { security_image_view_ = view; } -- (void)onSecurityIconMousePressed { - security_image_view_->OnMousePressed(); -} - -- (void)onPageActionMousePressedIn:(NSRect)iconFrame forIndex:(size_t)index { - page_action_views_->OnMousePressed(iconFrame, index); +- (void)setContentBlockedViewList: + (LocationBarViewMac::ContentBlockedViews*)views { + content_blocked_views_ = views; } // Overriden to account for the hint strings and hint icons. @@ -235,32 +248,15 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) { textFrame.size.width = NSMaxX(cellFrame) - NSMinX(textFrame); } } else { - // Account for the lock icon, if any, and any visible Page Action icons. + // Leave room for images on the right (lock icon etc). + NSArray* iconFrames = [self layedOutIcons:cellFrame]; CGFloat width = 0; - const size_t iconCount = [self pageActionCount]; - for (size_t i = 0; i < iconCount; ++i) { - LocationBarViewMac::PageActionImageView* view = - page_action_views_->ViewAt(i); - NSImage* image = view->GetImage(); - if (image && view->IsVisible()) { - width += [image size].width + kIconHorizontalPad; - } - } - - if (security_image_view_ && security_image_view_->IsVisible()) { - width += [security_image_view_->GetImage() size].width + - kIconHorizontalPad; - NSAttributedString* label = security_image_view_->GetLabel(); - if (label) { - width += ceil([label size].width) + kHintXOffset; - } - } + if ([iconFrames count] > 0) + width = NSMaxX(cellFrame) - NSMinX([[iconFrames lastObject] rect]); if (width > 0) width += kIconHorizontalPad; - - if (width < NSWidth(cellFrame)) { + if (width < NSWidth(cellFrame)) textFrame.size.width -= width; - } } return textFrame; @@ -308,53 +304,21 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) { - (NSRect)pageActionFrameForIndex:(size_t)index inFrame:(NSRect)cellFrame { LocationBarViewMac::PageActionImageView* view = page_action_views_->ViewAt(index); - const NSImage* icon = view->GetImage(); // If we are calculating space for a preview page action, the icon is still // loading. We use this function only to get the correct x value for the // extension installed bubble arrow. if (!view->preview_enabled() && - (!icon || !view->IsVisible())) { + (!view->GetImage() || !view->IsVisible())) { return NSZeroRect; } - // Compute the amount of space used by this icon plus any other icons to its - // right. It's terribly inefficient to do this anew every time, but easy to - // understand. It should be fine for 5 or 10 installed Page Actions, perhaps - // too slow for 100. - // TODO(pamg): Refactor to avoid this if performance is a problem. - const NSRect securityIconRect = [self securityImageFrameForFrame:cellFrame]; - CGFloat widthUsed = 0.0; - if (NSWidth(securityIconRect) > 0) { - widthUsed += NSMaxX(cellFrame) - NSMinX(securityIconRect); + for (AutocompleteTextFieldIcon* icon in [self layedOutIcons:cellFrame]) { + if (view == [icon view]) + return [icon rect]; } - for (size_t i = 0; i <= index; ++i) { - view = page_action_views_->ViewAt(i); - if (view->IsVisible()) { - NSImage* image = view->GetImage(); - if (image) { - // Page Action icons don't have labels. Don't compute space for them. - widthUsed += [image size].width + kIconHorizontalPad; - } - } - } - widthUsed += kIconHorizontalPad; - - // If we are calculating frame space for a preview, the icon is still - // loading -- use maximum size as a placeholder. - NSSize iconSize = view->GetImageSize(); - - return [self rightJustifyImage:iconSize - inRect:cellFrame - withMargin:widthUsed]; -} - -- (NSString*)pageActionToolTipForIndex:(size_t)index { - return page_action_views_->ViewAt(index)->GetToolTip(); -} - -- (ExtensionAction*)pageActionForIndex:(size_t)index { - return page_action_views_->ViewAt(index)->page_action(); + NOTREACHED(); + return NSZeroRect; } - (void)drawHintWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { @@ -430,25 +394,65 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) { } else if (keywordString_) { [self drawKeywordWithFrame:cellFrame inView:controlView]; } else { - if (security_image_view_ && security_image_view_->IsVisible()) { - [self drawImageView:security_image_view_ - inFrame:[self securityImageFrameForFrame:cellFrame] + for (AutocompleteTextFieldIcon* icon in [self layedOutIcons:cellFrame]) { + [self drawImageView:[icon view] + inFrame:[icon rect] inView:controlView]; } + } - const size_t pageActionCount = [self pageActionCount]; - for (size_t i = 0; i < pageActionCount; ++i) { - LocationBarViewMac::PageActionImageView* view = - page_action_views_->ViewAt(i); - if (view && view->IsVisible()) { - [self drawImageView:view - inFrame:[self pageActionFrameForIndex:i inFrame:cellFrame] - inView:controlView]; - } + [super drawInteriorWithFrame:cellFrame inView:controlView]; +} + +- (NSArray*)layedOutIcons:(NSRect)cellFrame { + NSMutableArray* result = [NSMutableArray arrayWithCapacity:0]; + NSRect iconFrame = cellFrame; + if (security_image_view_ && security_image_view_->IsVisible()) { + NSRect securityImageFrame = [self securityImageFrameForFrame:iconFrame]; + [result addObject: + [AutocompleteTextFieldIcon iconWithRect:securityImageFrame + view:security_image_view_]]; + iconFrame.size.width -= NSMaxX(iconFrame) - NSMinX(securityImageFrame); + } + + const size_t pageActionCount = [self pageActionCount]; + for (size_t i = 0; i < pageActionCount; ++i) { + LocationBarViewMac::PageActionImageView* view = + page_action_views_->ViewAt(i); + if (view->preview_enabled() || (view->GetImage() && view->IsVisible())) { + NSSize iconSize = view->GetImageSize(); + NSRect pageActionFrame = + [self rightJustifyImage:iconSize + inRect:iconFrame + withMargin:kIconHorizontalPad + iconSize.width]; + [result addObject: + [AutocompleteTextFieldIcon iconWithRect:pageActionFrame view:view]]; + iconFrame.size.width -= NSMaxX(iconFrame) - NSMinX(pageActionFrame); } } - [super drawInteriorWithFrame:cellFrame inView:controlView]; + if (content_blocked_views_) { + // We use a reverse_iterator here because we're laying out the views from + // right to left but in the vector they're ordered left to right. + for (LocationBarViewMac::ContentBlockedViews::const_reverse_iterator + it(content_blocked_views_->rbegin()); + it != const_cast<const LocationBarViewMac::ContentBlockedViews*>( + content_blocked_views_)->rend(); + ++it) { + if ((*it)->IsVisible()) { + NSImage* image = (*it)->GetImage(); + NSRect blockedContentFrame = + [self rightJustifyImage:[image size] + inRect:iconFrame + withMargin:[image size].width + kIconHorizontalPad]; + [result addObject: + [AutocompleteTextFieldIcon iconWithRect:blockedContentFrame + view:*it]]; + iconFrame.size.width -= NSMaxX(iconFrame) - NSMinX(blockedContentFrame); + } + } + } + return result; } @end diff --git a/chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm b/chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm index a83cdab..9023d4b 100644 --- a/chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm +++ b/chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm @@ -284,14 +284,12 @@ TEST_F(AutocompleteTextFieldCellTest, SecurityImageFrame) { LocationBarViewMac::SecurityImageView::LOCK); security_image_view_.SetVisible(false); - NSRect iconRect = [cell securityImageFrameForFrame:bounds]; - EXPECT_TRUE(NSIsEmptyRect(iconRect)); - - // Save the starting frame for after clear. - const NSRect originalIconRect(iconRect); + EXPECT_EQ(0u, [[cell layedOutIcons:bounds] count]); security_image_view_.SetVisible(true); - iconRect = [cell securityImageFrameForFrame:bounds]; + NSArray* icons = [cell layedOutIcons:bounds]; + ASSERT_EQ(1u, [icons count]); + NSRect iconRect = [[icons objectAtIndex:0] rect]; EXPECT_FALSE(NSIsEmptyRect(iconRect)); EXPECT_TRUE(NSContainsRect(bounds, iconRect)); @@ -308,7 +306,9 @@ TEST_F(AutocompleteTextFieldCellTest, SecurityImageFrame) { NSFont* font = [NSFont controlContentFontOfSize:12.0]; NSColor* color = [NSColor blackColor]; security_image_view_.SetLabel(@"Label", font, color); - iconRect = [cell securityImageFrameForFrame:bounds]; + icons = [cell layedOutIcons:bounds]; + ASSERT_EQ(1u, [icons count]); + iconRect = [[icons objectAtIndex:0] rect]; EXPECT_FALSE(NSIsEmptyRect(iconRect)); EXPECT_TRUE(NSContainsRect(bounds, iconRect)); @@ -323,9 +323,7 @@ TEST_F(AutocompleteTextFieldCellTest, SecurityImageFrame) { // Make sure we clear correctly. security_image_view_.SetVisible(false); - iconRect = [cell securityImageFrameForFrame:bounds]; - EXPECT_TRUE(NSEqualRects(iconRect, originalIconRect)); - EXPECT_TRUE(NSIsEmptyRect(iconRect)); + EXPECT_EQ(0u, [[cell layedOutIcons:bounds] count]); } // Test Page Action counts. @@ -382,6 +380,7 @@ TEST_F(AutocompleteTextFieldCellTest, PageActionImageFrame) { EXPECT_TRUE(NSIsEmptyRect([cell pageActionFrameForIndex:2 inFrame:bounds])); preview_view.set_preview_enabled(true); EXPECT_FALSE(NSIsEmptyRect([cell pageActionFrameForIndex:2 inFrame:bounds])); + preview_view.set_preview_enabled(false); // One page action, no security icon. page_action_view.SetVisible(true); @@ -401,9 +400,14 @@ TEST_F(AutocompleteTextFieldCellTest, PageActionImageFrame) { // Two page actions plus a security icon. page_action_view2.SetVisible(true); security_image_view_.SetVisible(true); + NSArray* icons = [cell layedOutIcons:bounds]; + EXPECT_EQ(3u, [icons count]); iconRect0 = [cell pageActionFrameForIndex:0 inFrame:bounds]; NSRect iconRect1 = [cell pageActionFrameForIndex:1 inFrame:bounds]; - NSRect lockRect = [cell securityImageFrameForFrame:bounds]; + NSRect lockRect = [[icons objectAtIndex:0] rect]; + + EXPECT_TRUE(NSEqualRects(iconRect0, [[icons objectAtIndex:1] rect])); + EXPECT_TRUE(NSEqualRects(iconRect1, [[icons objectAtIndex:2] rect])); // Make sure they're all in the expected order, and right of the |drawingRect| // and |textFrame|. diff --git a/chrome/browser/cocoa/autocomplete_text_field_editor.mm b/chrome/browser/cocoa/autocomplete_text_field_editor.mm index b4e0a5e..7eb8b93 100644 --- a/chrome/browser/cocoa/autocomplete_text_field_editor.mm +++ b/chrome/browser/cocoa/autocomplete_text_field_editor.mm @@ -13,7 +13,6 @@ #import "chrome/browser/cocoa/autocomplete_text_field.h" #import "chrome/browser/cocoa/autocomplete_text_field_cell.h" #import "chrome/browser/cocoa/browser_window_controller.h" -#import "chrome/browser/cocoa/extensions/extension_action_context_menu.h" #import "chrome/browser/cocoa/toolbar_controller.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/common/extensions/extension_action.h" @@ -96,25 +95,13 @@ class Extension; AutocompleteTextField* field = (AutocompleteTextField*)[self delegate]; NSRect bounds([field bounds]); AutocompleteTextFieldCell* cell = [field autocompleteTextFieldCell]; - const size_t pageActionCount = [cell pageActionCount]; BOOL flipped = [self isFlipped]; - if (!profile_) - return [self defaultMenuForEvent:event]; - - ExtensionsService* service = profile_->GetExtensionsService(); - if (!service) - return [self defaultMenuForEvent:event]; - - for (size_t i = 0; i < pageActionCount; ++i) { - NSRect pageActionFrame = [cell pageActionFrameForIndex:i inFrame:bounds]; - if (NSMouseInRect(location, pageActionFrame, flipped)) { - Extension* extension = service->GetExtensionById( - [cell pageActionForIndex:i]->extension_id(), false); - DCHECK(extension); - if (!extension) - break; - return [[[ExtensionActionContextMenu alloc] - initWithExtension:extension profile:profile_] autorelease]; + + for (AutocompleteTextFieldIcon* icon in [cell layedOutIcons:bounds]) { + if (NSMouseInRect(location, [icon rect], flipped)) { + NSMenu* menu = [icon view]->GetMenu(); + if (menu) + return menu; } } diff --git a/chrome/browser/cocoa/autocomplete_text_field_editor_unittest.mm b/chrome/browser/cocoa/autocomplete_text_field_editor_unittest.mm index 40a1838..29d87ec 100644 --- a/chrome/browser/cocoa/autocomplete_text_field_editor_unittest.mm +++ b/chrome/browser/cocoa/autocomplete_text_field_editor_unittest.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. diff --git a/chrome/browser/cocoa/autocomplete_text_field_unittest.mm b/chrome/browser/cocoa/autocomplete_text_field_unittest.mm index 4adfa6a..b2f1f2d 100644 --- a/chrome/browser/cocoa/autocomplete_text_field_unittest.mm +++ b/chrome/browser/cocoa/autocomplete_text_field_unittest.mm @@ -27,7 +27,12 @@ class MockSecurityImageView : public LocationBarViewMac::SecurityImageView { ToolbarModel* model) : LocationBarViewMac::SecurityImageView(owner, profile, model) {} - MOCK_METHOD0(OnMousePressed, bool()); + // We can't use gmock's MOCK_METHOD macro, because it doesn't like the + // NSRect argument to OnMousePressed. + virtual void OnMousePressed(NSRect bounds) { + mouse_was_pressed_ = true; + } + bool mouse_was_pressed_; }; class MockPageActionImageView : public LocationBarViewMac::PageActionImageView { @@ -37,9 +42,8 @@ class MockPageActionImageView : public LocationBarViewMac::PageActionImageView { // We can't use gmock's MOCK_METHOD macro, because it doesn't like the // NSRect argument to OnMousePressed. - virtual bool OnMousePressed(NSRect bounds) { + virtual void OnMousePressed(NSRect bounds) { mouse_was_pressed_ = true; - return true; } bool MouseWasPressed() { return mouse_was_pressed_; } @@ -585,8 +589,8 @@ TEST_F(AutocompleteTextFieldObserverTest, SecurityIconMouseDown) { NSPoint location(NSMakePoint(NSMidX(iconFrame), NSMidY(iconFrame))); NSEvent* event(Event(field_, location, NSLeftMouseDown, 1)); - EXPECT_CALL(security_image_view, OnMousePressed()); [field_ mouseDown:event]; + EXPECT_TRUE(security_image_view.mouse_was_pressed_); } // Clicking a Page Action icon should call its OnMousePressed. @@ -657,8 +661,8 @@ TEST_F(AutocompleteTextFieldObserverTest, PageActionMouseDown) { location = NSMakePoint(NSMidX(iconFrame), NSMidY(iconFrame)); event = Event(field_, location, NSLeftMouseDown, 1); - EXPECT_CALL(security_image_view, OnMousePressed()); [field_ mouseDown:event]; + EXPECT_TRUE(security_image_view.mouse_was_pressed_); } // Verify that -setAttributedStringValue: works as expected when diff --git a/chrome/browser/cocoa/extension_installed_bubble_controller.mm b/chrome/browser/cocoa/extension_installed_bubble_controller.mm index f1d4761..677e55c 100644 --- a/chrome/browser/cocoa/extension_installed_bubble_controller.mm +++ b/chrome/browser/cocoa/extension_installed_bubble_controller.mm @@ -200,9 +200,7 @@ class ExtensionLoadedNotificationObserver : public NotificationObserver { pageActionFrameForIndex:index inFrame:[field frame]]; NSRect boundsrect = [browserContentWindow convertRect:iconRect fromView:[field superview]]; - arrowPoint = - NSMakePoint(NSMinX(boundsrect) - NSWidth(boundsrect) / 2 - 1, - NSMinY(boundsrect)); + arrowPoint = NSMakePoint(NSMidX(boundsrect) + 1, NSMinY(boundsrect)); break; } default: { diff --git a/chrome/browser/cocoa/location_bar_view_mac.h b/chrome/browser/cocoa/location_bar_view_mac.h index 19d88d1..75241f8 100644 --- a/chrome/browser/cocoa/location_bar_view_mac.h +++ b/chrome/browser/cocoa/location_bar_view_mac.h @@ -13,11 +13,13 @@ #include "base/scoped_nsobject.h" #include "base/scoped_ptr.h" +#include "base/scoped_vector.h" #include "chrome/browser/autocomplete/autocomplete_edit.h" #include "chrome/browser/autocomplete/autocomplete_edit_view_mac.h" #include "chrome/browser/extensions/image_loading_tracker.h" #include "chrome/browser/location_bar.h" #include "chrome/browser/toolbar_model.h" +#include "chrome/common/content_settings_types.h" #include "third_party/skia/include/core/SkBitmap.h" @class AutocompleteTextField; @@ -150,6 +152,15 @@ class LocationBarViewMac : public AutocompleteEditController, const NSAttributedString* GetLabel() const { return label_; } bool IsVisible() const { return visible_; } + // Returns the tooltip for this image view or |nil| if there is none. + virtual const NSString* GetToolTip() { return nil; } + + // Called on mouse down. + virtual void OnMousePressed(NSRect bounds) {} + + // Called to get the icon's context menu. Return |nil| for no menu. + virtual NSMenu* GetMenu() { return nil; } + private: scoped_nsobject<NSImage> image_; @@ -178,8 +189,8 @@ class LocationBarViewMac : public AutocompleteEditController, // Sets the image to the appropriate icon. void SetImageShown(Image image); - // Shows the page info dialog. Virtual so it can be overridden for testing. - virtual bool OnMousePressed(); + // Shows the page info dialog. + virtual void OnMousePressed(NSRect bounds); private: // The lock icon shown when using HTTPS. Loaded lazily, the first time it's @@ -223,8 +234,7 @@ class LocationBarViewMac : public AutocompleteEditController, virtual NSSize GetImageSize(); // Either notify listeners or show a popup depending on the Page Action. - // Virtual so it can be overridden for testing. - virtual bool OnMousePressed(NSRect bounds); + virtual void OnMousePressed(NSRect bounds); // Overridden from ImageLoadingTracker. virtual void OnImageLoaded(SkBitmap* image, size_t index); @@ -239,7 +249,10 @@ class LocationBarViewMac : public AutocompleteEditController, void SetToolTip(std::string tooltip); // Returns the tooltip for this Page Action image or |nil| if there is none. - const NSString* GetToolTip(); + virtual const NSString* GetToolTip(); + + // Overridden to return a menu. + virtual NSMenu* GetMenu(); protected: // For unit testing only. @@ -293,6 +306,38 @@ class LocationBarViewMac : public AutocompleteEditController, DISALLOW_COPY_AND_ASSIGN(PageActionImageView); }; + // ContentBlockedImageView is used to display the content settings images + // when types of contents are blocked on the current page. + class ContentBlockedImageView : public LocationBarImageView { + public: + ContentBlockedImageView(ContentSettingsType settings_type, + LocationBarViewMac* owner, + Profile* profile); + virtual ~ContentBlockedImageView(); + + // Shows a content settings bubble. + void OnMousePressed(NSRect bounds); + + // Returns the settings type this shows up for. + ContentSettingsType settings_type() { return settings_type_; } + + // Returns the tooltip for this Page Action image or |nil| if there is none. + virtual const NSString* GetToolTip(); + + private: + void SetToolTip(NSString* tooltip); + + // The type of content handled by this view. + ContentSettingsType settings_type_; + + LocationBarViewMac* owner_; + Profile* profile_; + scoped_nsobject<NSString> tooltip_; + + DISALLOW_COPY_AND_ASSIGN(ContentBlockedImageView); + }; + typedef ScopedVector<ContentBlockedImageView> ContentBlockedViews; + class PageActionViewList { public: PageActionViewList(LocationBarViewMac* location_bar, @@ -341,6 +386,10 @@ class LocationBarViewMac : public AutocompleteEditController, // Posts |notification| to the default notification center. void PostNotification(const NSString* notification); + // Updates visibility of the content blocked icons based on the current + // tab contents state. + void RefreshContentBlockedViews(); + scoped_ptr<AutocompleteEditViewMac> edit_view_; CommandUpdater* command_updater_; // Weak, owned by Browser. @@ -361,6 +410,9 @@ class LocationBarViewMac : public AutocompleteEditController, // Any installed Page Actions. PageActionViewList page_action_views_; + // The content blocked views. + ContentBlockedViews content_blocked_views_; + Profile* profile_; Browser* browser_; diff --git a/chrome/browser/cocoa/location_bar_view_mac.mm b/chrome/browser/cocoa/location_bar_view_mac.mm index afcf1b0..88fcc89 100644 --- a/chrome/browser/cocoa/location_bar_view_mac.mm +++ b/chrome/browser/cocoa/location_bar_view_mac.mm @@ -6,6 +6,7 @@ #include "app/l10n_util_mac.h" #include "app/resource_bundle.h" +#include "base/nsimage_cache_mac.h" #include "base/stl_util-inl.h" #include "base/string_util.h" #include "base/sys_string_conversions.h" @@ -17,6 +18,7 @@ #import "chrome/browser/cocoa/autocomplete_text_field.h" #import "chrome/browser/cocoa/autocomplete_text_field_cell.h" #include "chrome/browser/cocoa/event_utils.h" +#import "chrome/browser/cocoa/extensions/extension_action_context_menu.h" #import "chrome/browser/cocoa/extensions/extension_popup_controller.h" #include "chrome/browser/command_updater.h" #include "chrome/browser/extensions/extension_browser_event_router.h" @@ -99,9 +101,18 @@ LocationBarViewMac::LocationBarViewMac( browser_(browser), toolbar_model_(toolbar_model), transition_(PageTransition::TYPED) { + for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { + ContentBlockedImageView* content_blocked_view = + new ContentBlockedImageView(static_cast<ContentSettingsType>(i), this, + profile_); + content_blocked_views_.push_back(content_blocked_view); + content_blocked_view->SetVisible(false); + } + AutocompleteTextFieldCell* cell = [field_ autocompleteTextFieldCell]; [cell setSecurityImageView:&security_image_view_]; [cell setPageActionViewList:&page_action_views_]; + [cell setContentBlockedViewList:&content_blocked_views_]; registrar_.Add(this, NotificationType::EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED, @@ -123,6 +134,7 @@ WindowOpenDisposition LocationBarViewMac::GetWindowOpenDisposition() const { return disposition_; } +// TODO(thakis): Ping shess to verify what he wants to verify. // TODO(shess): Verify that this TODO is TODONE. // TODO(rohitrao): Fix this to return different types once autocomplete and // the onmibar are implemented. For now, any URL that comes from the @@ -152,7 +164,9 @@ void LocationBarViewMac::FocusSearch() { } void LocationBarViewMac::UpdateContentBlockedIcons() { - // TODO(pkasting): Implement. + RefreshContentBlockedViews(); + [field_ updateCursorAndToolTipRects]; + [field_ setNeedsDisplay:YES]; } void LocationBarViewMac::UpdatePageActions() { @@ -187,6 +201,7 @@ void LocationBarViewMac::Update(const TabContents* contents, bool should_restore_state) { SetSecurityIcon(toolbar_model_->GetIcon()); page_action_views_.RefreshViews(); + RefreshContentBlockedViews(); // AutocompleteEditView restores state if the tab is non-NULL. edit_view_->Update(should_restore_state ? contents : NULL); } @@ -497,6 +512,16 @@ void LocationBarViewMac::PostNotification(const NSString* notification) { object:[NSValue valueWithPointer:this]]; } +void LocationBarViewMac::RefreshContentBlockedViews() { + const TabContents* tab_contents = browser_->GetSelectedTabContents(); + for (ContentBlockedViews::iterator it(content_blocked_views_.begin()); + it != content_blocked_views_.end(); + ++it) { + (*it)->SetVisible((!toolbar_model_->input_in_progress() && tab_contents) ? + tab_contents->IsContentBlocked((*it)->settings_type()) : false); + } +} + // LocationBarImageView--------------------------------------------------------- void LocationBarViewMac::LocationBarImageView::SetImage(NSImage* image) { @@ -568,15 +593,14 @@ void LocationBarViewMac::SecurityImageView::SetImageShown(Image image) { } } -bool LocationBarViewMac::SecurityImageView::OnMousePressed() { +void LocationBarViewMac::SecurityImageView::OnMousePressed(NSRect bounds) { TabContents* tab = owner_->GetTabContents(); NavigationEntry* nav_entry = tab->controller().GetActiveEntry(); if (!nav_entry) { NOTREACHED(); - return true; + return; } tab->ShowPageInfo(nav_entry->url(), nav_entry->ssl(), true); - return true; } // PageActionImageView---------------------------------------------------------- @@ -632,12 +656,12 @@ NSSize LocationBarViewMac::PageActionImageView::GetImageSize() { // Overridden from LocationBarImageView. Either notify listeners or show a // popup depending on the Page Action. -bool LocationBarViewMac::PageActionImageView::OnMousePressed(NSRect bounds) { +void LocationBarViewMac::PageActionImageView::OnMousePressed(NSRect bounds) { if (current_tab_id_ < 0) { NOTREACHED() << "No current tab."; // We don't want other code to try and handle this click. Returning true // prevents this by indicating that we handled it. - return true; + return; } if (page_action_->HasPopup(current_tab_id_)) { @@ -662,7 +686,6 @@ bool LocationBarViewMac::PageActionImageView::OnMousePressed(NSRect bounds) { current_tab_id_, current_url_.spec(), 1); } - return true; } void LocationBarViewMac::PageActionImageView::OnImageLoaded(SkBitmap* image, @@ -763,6 +786,21 @@ const NSString* LocationBarViewMac::PageActionImageView::GetToolTip() { return tooltip_.get(); } +NSMenu* LocationBarViewMac::PageActionImageView::GetMenu() { + if (!profile_) + return nil; + ExtensionsService* service = profile_->GetExtensionsService(); + if (!service) + return nil; + Extension* extension = service->GetExtensionById( + page_action_->extension_id(), false); + DCHECK(extension); + if (!extension) + return nil; + return [[[ExtensionActionContextMenu alloc] + initWithExtension:extension profile:profile_] autorelease]; +} + void LocationBarViewMac::PageActionImageView::Observe( NotificationType type, const NotificationSource& source, @@ -781,6 +819,58 @@ void LocationBarViewMac::PageActionImageView::Observe( } } +// ContentSettingsImageView----------------------------------------------------- + +LocationBarViewMac::ContentBlockedImageView::ContentBlockedImageView( + ContentSettingsType settings_type, + LocationBarViewMac* owner, + Profile* profile) + : settings_type_(settings_type), + owner_(owner), + profile_(profile) { + // TODO(thakis): We should use pdfs for these icons on OSX. + // http://crbug.com/35847 + static const int kIconIDs[] = { + IDR_BLOCKED_COOKIES, + IDR_BLOCKED_IMAGES, + IDR_BLOCKED_JAVASCRIPT, + IDR_BLOCKED_PLUGINS, + IDR_BLOCKED_POPUPS, + }; + DCHECK_EQ(arraysize(kIconIDs), + static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES)); + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + SetImage(rb.GetNSImageNamed(kIconIDs[settings_type])); + + static const int kTooltipIDs[] = { + IDS_BLOCKED_COOKIES_TITLE, + IDS_BLOCKED_IMAGES_TITLE, + IDS_BLOCKED_JAVASCRIPT_TITLE, + IDS_BLOCKED_PLUGINS_TITLE, + IDS_BLOCKED_POPUPS_TOOLTIP, + }; + DCHECK_EQ(arraysize(kTooltipIDs), + static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES)); + SetToolTip(l10n_util::GetNSStringWithFixup(kTooltipIDs[settings_type])); +} + +LocationBarViewMac::ContentBlockedImageView::~ContentBlockedImageView() {} + +void LocationBarViewMac::ContentBlockedImageView::OnMousePressed(NSRect bounds) + { + // TODO(thakis): Implement. + NOTIMPLEMENTED(); +} + +const NSString* LocationBarViewMac::ContentBlockedImageView::GetToolTip() { + return tooltip_.get(); +} + +void LocationBarViewMac::ContentBlockedImageView::SetToolTip(NSString* tooltip) + { + tooltip_.reset([tooltip retain]); +} + // PageActionViewList----------------------------------------------------------- void LocationBarViewMac::PageActionViewList::DeleteAll() { |