diff options
-rw-r--r-- | base/scoped_vector.h | 10 | ||||
-rw-r--r-- | chrome/browser/cocoa/autocomplete_text_field.mm | 40 | ||||
-rw-r--r-- | chrome/browser/cocoa/autocomplete_text_field_cell.h | 59 | ||||
-rw-r--r-- | chrome/browser/cocoa/autocomplete_text_field_cell.mm | 164 | ||||
-rw-r--r-- | chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm | 26 | ||||
-rw-r--r-- | chrome/browser/cocoa/autocomplete_text_field_editor.mm | 25 | ||||
-rw-r--r-- | chrome/browser/cocoa/autocomplete_text_field_editor_unittest.mm | 2 | ||||
-rw-r--r-- | chrome/browser/cocoa/autocomplete_text_field_unittest.mm | 14 | ||||
-rw-r--r-- | chrome/browser/cocoa/extension_installed_bubble_controller.mm | 4 | ||||
-rw-r--r-- | chrome/browser/cocoa/location_bar_view_mac.h | 62 | ||||
-rw-r--r-- | chrome/browser/cocoa/location_bar_view_mac.mm | 104 |
11 files changed, 328 insertions, 182 deletions
diff --git a/base/scoped_vector.h b/base/scoped_vector.h index 0c7449d..c007ce4 100644 --- a/base/scoped_vector.h +++ b/base/scoped_vector.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 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. @@ -17,6 +17,9 @@ class ScopedVector { public: typedef typename std::vector<T*>::iterator iterator; typedef typename std::vector<T*>::const_iterator const_iterator; + typedef typename std::vector<T*>::reverse_iterator reverse_iterator; + typedef typename std::vector<T*>::const_reverse_iterator + const_reverse_iterator; ScopedVector() {} ~ScopedVector() { reset(); } @@ -29,6 +32,11 @@ class ScopedVector { bool empty() const { return v.empty(); } size_t size() const { return v.size(); } + reverse_iterator rbegin() { return v.rbegin(); } + const_reverse_iterator rbegin() const { return v.rbegin(); } + reverse_iterator rend() { return v.rend(); } + const_reverse_iterator rend() const { return v.rend(); } + iterator begin() { return v.begin(); } const_iterator begin() const { return v.begin(); } iterator end() { return v.end(); } 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() { |