Index: chrome/browser/cocoa/blocked_popup_container_controller.mm |
=================================================================== |
--- chrome/browser/cocoa/blocked_popup_container_controller.mm (revision 19942) |
+++ chrome/browser/cocoa/blocked_popup_container_controller.mm (working copy) |
@@ -50,6 +50,7 @@ |
- (void)dealloc { |
[view_ removeFromSuperview]; |
+ [[NSNotificationCenter defaultCenter] removeObserver:self]; |
[super dealloc]; |
} |
@@ -77,14 +78,30 @@ |
0, |
startFrame.size.width - kCloseBoxSize, |
startFrame.size.height); |
- label_ = [[[NSTextField alloc] initWithFrame:labelFrame] autorelease]; |
- [label_ setSelectable:NO]; |
- [label_ setAutoresizingMask:NSViewWidthSizable]; |
- [label_ setBordered:NO]; |
- [label_ setBezeled:NO]; |
- [label_ setDrawsBackground:NO]; |
- [view_ addSubview:label_]; |
+ popupButton_ = [[[NSPopUpButton alloc] initWithFrame:labelFrame] autorelease]; |
+ [popupButton_ setAutoresizingMask:NSViewWidthSizable]; |
+ [popupButton_ setBordered:NO]; |
+ [popupButton_ setBezelStyle:NSTexturedRoundedBezelStyle]; |
+ [popupButton_ setPullsDown:YES]; |
+ // TODO(pinkerton): this doesn't work, not sure why. |
+ [popupButton_ setPreferredEdge:NSMaxYEdge]; |
+ // TODO(pinkerton): no matter what, the arrows always draw in the middle |
+ // of the button. We can turn off the arrows entirely, but then will the |
+ // user ever know to click it? Leave them on for now. |
+ //[[popupButton_ cell] setArrowPosition:NSPopUpNoArrow]; |
+ [[popupButton_ cell] setAltersStateOfSelectedItem:NO]; |
+ // If we don't add this, no title will ever display. |
+ [popupButton_ addItemWithTitle:@"placeholder"]; |
+ [view_ addSubview:popupButton_]; |
+ // Register for notifications that the menu is about to display so we can |
+ // fill it in lazily |
+ [[NSNotificationCenter defaultCenter] |
+ addObserver:self |
+ selector:@selector(showMenu:) |
+ name:NSPopUpButtonCellWillPopUpNotification |
+ object:nil]; |
+ |
// Create the close box and position at the left of the view. |
NSRect closeFrame = NSMakeRect(startFrame.size.width - kCloseBoxSize, |
kCloseBoxPaddingY, |
@@ -139,9 +156,14 @@ |
// Resize the view based on the new label contents. The autoresize mask will |
// take care of resizing everything else. |
- (void)resizeWithLabel:(NSString*)label { |
+// TODO(pinkerton): fix this so that it measures the text so that it can |
+// be localized. |
#if 0 |
-// TODO(pinkerton): fix this once the popup gets put in. |
- NSSize stringSize = [label sizeWithAttributes:nil]; |
+ NSDictionary* attributes = |
+ [NSDictionary dictionaryWithObjectsAndKeys: |
+ NSFontAttributeName, [NSFont systemFontOfSize:25], |
+ nil]; |
+ NSSize stringSize = [label sizeWithAttributes:attributes]; |
NSRect frame = [view_ frame]; |
float originalWidth = frame.size.width; |
frame.size.width = stringSize.width + 16 + 5; |
@@ -162,17 +184,118 @@ |
l10n_util::GetStringUTF16(IDS_POPUPS_UNBLOCKED)); |
} |
[self resizeWithLabel:label]; |
- [label_ setStringValue:label]; |
+ [popupButton_ setTitle:label]; |
} |
+// Called when the user selects an item from the popup menu. The tag, if below |
+// |kImpossibleNumberOfPopups| will be the index into the container's popup |
+// array. In that case, we should display the popup. If >= |
+// |kImpossibleNumberOfPopups|, it represents a host that we should whitelist. |
+// |sender| is the NSMenuItem that was chosen. |
+- (void)menuAction:(id)sender { |
+ size_t tag = static_cast<size_t>([sender tag]); |
+ if (tag < BlockedPopupContainer::kImpossibleNumberOfPopups) { |
+ container_->LaunchPopupAtIndex(tag); |
+ } else { |
+ size_t hostIndex = tag - BlockedPopupContainer::kImpossibleNumberOfPopups; |
+ container_->ToggleWhitelistingForHost(hostIndex); |
+ } |
+} |
+ |
+namespace { |
+void GetURLAndTitleForPopup( |
+ const BlockedPopupContainer* container, |
+ size_t index, |
+ string16* url, |
+ string16* title) { |
+ DCHECK(url); |
+ DCHECK(title); |
+ TabContents* tab_contents = container->GetTabContentsAt(index); |
+ const GURL& tab_contents_url = tab_contents->GetURL().GetOrigin(); |
+ *url = UTF8ToUTF16(tab_contents_url.possibly_invalid_spec()); |
+ *title = tab_contents->GetTitle(); |
+} |
+} // namespace |
+ |
+// Build a new popup menu from scratch. The menu contains the blocked popups |
+// (tags being the popup's index), followed by the list of hosts from which |
+// the popups were blocked (tags being |kImpossibleNumberOfPopups| + host |
+// index). The hosts are used to toggle whitelisting for a site. |
+- (NSMenu*)buildMenu { |
+ NSMenu* menu = [[[NSMenu alloc] init] autorelease]; |
+ |
+ // For pop-down menus, the first item is what is displayed while tracking the |
+ // menu and it remains there if nothing is selected. Set it to the |
+ // current title. |
+ NSString* currentTitle = [popupButton_ title]; |
+ scoped_nsobject<NSMenuItem> dummy( |
+ [[NSMenuItem alloc] initWithTitle:currentTitle |
+ action:nil |
+ keyEquivalent:@""]); |
+ [menu addItem:dummy.get()]; |
+ |
+ // Add the list of blocked popups titles to the menu. We set the array index |
+ // as the tag for use in the menu action rather than relying on the menu item |
+ // index. |
+ const size_t count = container_->GetBlockedPopupCount(); |
+ for (size_t i = 0; i < count; ++i) { |
+ string16 url, title; |
+ GetURLAndTitleForPopup(container_, i, &url, &title); |
+ NSString* titleStr = base::SysUTF16ToNSString( |
+ l10n_util::GetStringFUTF16(IDS_POPUP_TITLE_FORMAT, url, title)); |
+ scoped_nsobject<NSMenuItem> item( |
+ [[NSMenuItem alloc] initWithTitle:titleStr |
+ action:@selector(menuAction:) |
+ keyEquivalent:@""]); |
+ [item setTag:i]; |
+ [item setTarget:self]; |
+ [menu addItem:item.get()]; |
+ } |
+ |
+ // Add the list of hosts. We begin tagging these at |
+ // |kImpossibleNumberOfPopups|. If whitelisting has already been enabled |
+ // for a site, mark it with a checkmark. |
+ std::vector<std::string> hosts(container_->GetHosts()); |
+ if (!hosts.empty() && count) |
+ [menu addItem:[NSMenuItem separatorItem]]; |
+ for (size_t i = 0; i < hosts.size(); ++i) { |
+ NSString* titleStr = base::SysUTF8ToNSString( |
+ l10n_util::GetStringFUTF8(IDS_POPUP_HOST_FORMAT, |
+ UTF8ToUTF16(hosts[i]))); |
+ scoped_nsobject<NSMenuItem> item( |
+ [[NSMenuItem alloc] initWithTitle:titleStr |
+ action:@selector(menuAction:) |
+ keyEquivalent:@""]); |
+ if (container_->IsHostWhitelisted(i)) |
+ [item setState:NSOnState]; |
+ [item setTag:BlockedPopupContainer::kImpossibleNumberOfPopups + i]; |
+ [item setTarget:self]; |
+ [menu addItem:item.get()]; |
+ } |
+ |
+ return menu; |
+} |
+ |
+// Called when the popup button is about to display the menu, giving us a |
+// chance to fill in the contents. |
+- (void)showMenu:(NSNotification*)notify { |
+ NSMenu* menu = [self buildMenu]; |
+ [[notify object] setMenu:menu]; |
+} |
+ |
- (NSView*)view { |
return view_.get(); |
} |
-- (NSView*)label { |
- return label_; |
+- (NSPopUpButton*)popupButton { |
+ return popupButton_; |
} |
+// Only used for testing. |
+- (void)setContainer:(BlockedPopupContainer*)container { |
+ container_ = container; |
+} |
+ |
@end |
//--------------------------------------------------------------------------- |