Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(305)

Unified Diff: chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm

Issue 242443005: Changes cocoa implementation of permission bubble to better match mocks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm
diff --git a/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm b/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm
index 0b6f6f03f8b6c240922da6e39e02ff2e961e8f46..13b88a8db343881c23af2ef06174d6afb04c3f1d 100644
--- a/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm
@@ -6,6 +6,7 @@
#include <algorithm>
+#include "base/mac/bind_objc_block.h"
#include "base/mac/foundation_util.h"
#include "base/mac/mac_util.h"
#include "base/strings/sys_string_conversions.h"
@@ -20,12 +21,15 @@
#import "chrome/browser/ui/cocoa/info_bubble_view.h"
#import "chrome/browser/ui/cocoa/info_bubble_window.h"
#include "chrome/browser/ui/cocoa/website_settings/permission_bubble_cocoa.h"
+#include "chrome/browser/ui/cocoa/website_settings/permission_selector_button.h"
#include "chrome/browser/ui/cocoa/website_settings/split_block_button.h"
#include "chrome/browser/ui/website_settings/permission_bubble_request.h"
#include "chrome/browser/ui/website_settings/permission_bubble_view.h"
+#include "chrome/browser/ui/website_settings/permission_menu_model.h"
#include "content/public/browser/user_metrics.h"
#include "grit/generated_resources.h"
#include "skia/ext/skia_utils_mac.h"
+#import "ui/base/cocoa/menu_controller.h"
#include "ui/base/cocoa/window_size_constants.h"
#import "ui/base/cocoa/menu_controller.h"
#include "ui/base/l10n/l10n_util_mac.h"
@@ -39,9 +43,9 @@ const CGFloat kHorizontalPadding = 20.0f;
const CGFloat kVerticalPadding = 20.0f;
const CGFloat kButtonPadding = 10.0f;
const CGFloat kTitlePaddingX = 50.0f;
-const CGFloat kCheckboxYAdjustment = 2.0f;
+const CGFloat kTitleFontSize = 15.0f;
+const CGFloat kPermissionFontSize = 12.0f;
-const CGFloat kFontSize = 15.0f;
class MenuDelegate : public ui::SimpleMenuModel::Delegate {
public:
explicit MenuDelegate(PermissionBubbleController* bubble)
@@ -50,10 +54,7 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
return false;
}
virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE {
- // TODO(leng): Change this to true once setting the bubble to be
- // customizable works properly. Ideally, the bubble will alter its
- // contents, rather than reshowing completely.
- return false;
+ return true;
}
virtual bool GetAcceleratorForCommandId(
int command_id,
@@ -70,6 +71,61 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
} // namespace
+// NSPopUpButton with a menu containing two items: allow and block.
+// One AllowBlockMenuButton is used for each requested permission, but only when
+// the permission bubble is in 'customize' mode.
+@interface AllowBlockMenuButton : NSPopUpButton {
+ @private
+ int index_;
+ scoped_ptr<PermissionMenuModel> menuModel_;
+ base::scoped_nsobject<MenuController> menuController_;
+}
+
+- (id)initWithIndex:(int)index
+ forURL:(const GURL&)url
+ allowed:(BOOL)allow
+ withCallback:(void (^)(int, bool))callback;
+@end
+
+@implementation AllowBlockMenuButton
+
+- (id)initWithIndex:(int)index
+ forURL:(const GURL&)url
+ allowed:(BOOL)allow
+ withCallback:(void (^)(int, bool))callback {
+ if (self = [super initWithFrame:NSMakeRect(0, 0, 1, 1) pullsDown:NO]) {
+ index_ = index;
+ ContentSetting setting =
+ allow ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
+ [self setFont:[NSFont systemFontOfSize:kPermissionFontSize]];
+ [self setBordered:NO];
+
+ PermissionMenuModel::ChangeCallback changeCallback =
+ base::BindBlock(^(const WebsiteSettingsUI::PermissionInfo& permission) {
+ callback(index_, permission.setting == CONTENT_SETTING_ALLOW);
+ });
+
+ menuModel_.reset(new PermissionMenuModel(url, setting, changeCallback));
+ menuController_.reset([[MenuController alloc] initWithModel:menuModel_.get()
+ useWithPopUpButtonCell:NO]);
+ [self setMenu:[menuController_ menu]];
+ [[self cell] selectItemAtIndex:menuModel_->GetIndexOfCommandId(setting)];
groby-ooo-7-16 2014/04/18 18:18:18 I don't think you need the cell for selectItemAtIn
leng 2014/04/18 22:48:46 The first time I tried, it didn't work. Must've h
+ [self sizeToFit];
+ // Adjust the size to fit the current title. Using only -sizeToFit leaves
+ // an ugly amount of whitespace between the title and the arrows.
+ [self setFrameSize:[PermissionSelectorButton sizeForTitle:[self title]
groby-ooo-7-16 2014/04/18 18:18:18 I'm not happy with the tight coupling between the
leng 2014/04/18 22:48:46 As per our conversation offline, I'll make a follo
+ forButton:self]];
+ }
+ return self;
+}
+
+// Getter for testing
+- (int)index {
+ return index_;
+}
+
+@end
+
@interface PermissionBubbleController ()
// Returns an autoreleased NSView displaying the icon and label for |request|.
@@ -79,10 +135,11 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
// requesting settings for |host|.
- (NSView*)titleWithHostname:(const std::string&)host;
-// Returns an autoreleased NSView displaying a checkbox for |request|. The
-// checkbox will be initialized as checked if |checked| is YES.
-- (NSView*)checkboxForRequest:(PermissionBubbleRequest*)request
- checked:(BOOL)checked;
+// Returns an autoreleased NSView displaying a menu for |request|. The
+// menu will be initialized as 'allow' if |allow| is YES.
+- (NSView*)menuForRequest:(PermissionBubbleRequest*)request
groby-ooo-7-16 2014/04/18 18:18:18 menuViewForRequest?
leng 2014/04/18 22:48:46 Would you like me to change the other names, as we
+ atIndex:(int)index
+ allow:(BOOL)allow;
// Returns an autoreleased NSView of a button with |title| and |action|.
- (NSView*)buttonWithTitle:(NSString*)title
@@ -102,6 +159,10 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
// two views' widths. Does not change either view's origin or height.
- (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB;
+// Sets the offset of |viewA| so that its vertical center is aligned with the
+// vertical center of |viewB|.
+- (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB;
groby-ooo-7-16 2014/04/18 18:18:18 I'd probably do that as a standalone function, bec
leng 2014/04/18 22:48:46 Done.
+
// Called when the 'ok' button is pressed.
- (void)ok:(id)sender;
@@ -117,9 +178,6 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
// Called when the 'customize' button is pressed.
- (void)onCustomize:(id)sender;
-// Called when a checkbox changes from checked to unchecked, or vice versa.
-- (void)onCheckboxChanged:(id)sender;
-
@end
@implementation PermissionBubbleController
@@ -176,25 +234,31 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
CGFloat yOffset = 2 * kVerticalPadding + NSMaxY([allowOrOkButton frame]);
BOOL singlePermission = requests.size() == 1;
- checkboxes_.reset(customizationMode ? [[NSMutableArray alloc] init] : nil);
+ base::scoped_nsobject<NSMutableArray> permissionMenus;
+ if (customizationMode)
+ permissionMenus.reset([[NSMutableArray alloc] init]);
+
for (auto it = requests.begin(); it != requests.end(); it++) {
- base::scoped_nsobject<NSView> permissionView;
- if (customizationMode) {
- int index = it - requests.begin();
- permissionView.reset(
- [[self checkboxForRequest:(*it)
- checked:acceptStates[index] ? YES : NO] retain]);
- [base::mac::ObjCCastStrict<NSButton>(permissionView) setTag:index];
- [checkboxes_ addObject:permissionView];
- } else {
- permissionView.reset([[self labelForRequest:(*it)] retain]);
- }
+ base::scoped_nsobject<NSView> permissionView(
+ [[self labelForRequest:(*it)] retain]);
NSPoint origin = [permissionView frame].origin;
origin.x += kHorizontalPadding;
origin.y += yOffset;
[permissionView setFrameOrigin:origin];
[contentView addSubview:permissionView];
+ if (customizationMode) {
+ int index = it - requests.begin();
+ base::scoped_nsobject<NSView> menu(
+ [[self menuForRequest:(*it)
+ atIndex:index
+ allow:acceptStates[index] ? YES : NO] retain]);
+ // Align vertically. Horizontal alignment will be adjusted once the
+ // widest permission is know.
+ [self alignCenterOf:menu verticallyToCenterOf:permissionView];
+ [permissionMenus addObject:menu];
+ [contentView addSubview:menu];
+ }
yOffset += NSHeight([permissionView frame]);
}
@@ -207,6 +271,17 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
bubbleFrame, NSInsetRect([view frame], -kHorizontalPadding, 0));
}
+ if (customizationMode) {
+ // Adjust the horizontal origin for each menu.
+ CGFloat xOffset = NSWidth(bubbleFrame) - kHorizontalPadding;
+ for (NSView* view in permissionMenus.get()) {
+ [view setFrameOrigin:NSMakePoint(xOffset, NSMinY([view frame]))];
+ }
+ // And add the menu width to the bubble's width.
+ NSView* menu = base::mac::ObjCCast<NSView>(permissionMenus[0]);
groby-ooo-7-16 2014/04/18 18:18:18 Menu 0 is OK? We don't have varying sizes? Also:
leng 2014/04/18 22:48:46 Changed to use a max width. The NSUnionRect, above
+ bubbleFrame.size.width += NSWidth([menu frame]);
+ }
+
base::scoped_nsobject<NSView> titleView(
[[self titleWithHostname:requests[0]->GetRequestingHostname().host()]
retain]);
@@ -290,6 +365,7 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
[permissionLabel setBezeled:NO];
[permissionLabel setEditable:NO];
[permissionLabel setSelectable:NO];
+ [permissionLabel setFont:[NSFont systemFontOfSize:kPermissionFontSize]];
[permissionLabel setStringValue:base::SysUTF16ToNSString(label)];
[permissionLabel sizeToFit];
[permissionLabel setFrameOrigin:
@@ -326,7 +402,7 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
[titleView setStringValue:
l10n_util::GetNSStringF(IDS_PERMISSIONS_BUBBLE_PROMPT,
base::UTF8ToUTF16(host))];
- [titleView setFont:[NSFont systemFontOfSize:kFontSize]];
+ [titleView setFont:[NSFont systemFontOfSize:kTitleFontSize]];
[titleView sizeToFit];
NSRect titleFrame = [titleView frame];
[titleView setFrameSize:NSMakeSize(NSWidth(titleFrame) + kTitlePaddingX,
@@ -334,20 +410,21 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
return titleView.autorelease();
}
-- (NSView*)checkboxForRequest:(PermissionBubbleRequest*)request
- checked:(BOOL)checked {
+- (NSView*)menuForRequest:(PermissionBubbleRequest*)request
+ atIndex:(int)index
+ allow:(BOOL)allow {
DCHECK(request);
- base::scoped_nsobject<NSButton> checkbox(
- [[NSButton alloc] initWithFrame:NSZeroRect]);
- [checkbox setButtonType:NSSwitchButton];
- base::string16 permission = request->GetMessageTextFragment();
- [checkbox setTitle:base::SysUTF16ToNSString(permission)];
- [checkbox setState:(checked ? NSOnState : NSOffState)];
- [checkbox setTarget:self];
- [checkbox setAction:@selector(onCheckboxChanged:)];
- [checkbox sizeToFit];
- [checkbox setFrameOrigin:NSMakePoint(0, kCheckboxYAdjustment)];
- return checkbox.autorelease();
+ DCHECK(delegate_);
+ PermissionBubbleView::Delegate* blockDelegate = delegate_;
+ base::scoped_nsobject<AllowBlockMenuButton> button(
+ [[AllowBlockMenuButton alloc]
+ initWithIndex:index
+ forURL:request->GetRequestingHostname()
+ allowed:allow
+ withCallback:^(int index, bool allow) {
groby-ooo-7-16 2014/04/18 18:18:18 Why not just pass down the blockDelegate and save
leng 2014/04/18 22:48:46 Good idea. Done. I did the simplest version, whi
+ blockDelegate->ToggleAccept(index, allow);
+ }]);
+ return button.autorelease();
}
- (NSView*)buttonWithTitle:(NSString*)title
@@ -398,6 +475,14 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
return width;
}
+- (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB {
groby-ooo-7-16 2014/04/18 18:18:18 Grumble. I wish we had helper functions for this.
leng 2014/04/18 22:48:46 Me, too.
+ NSRect frameA = [viewA frame];
+ NSRect frameB = [viewB frame];
+ frameA.origin.y =
+ NSMinY(frameB) + std::floor((NSHeight(frameB) - NSHeight(frameA)) / 2);
+ [viewA setFrameOrigin:frameA.origin];
+}
+
- (void)ok:(id)sender {
DCHECK(delegate_);
delegate_->Closing();
@@ -423,12 +508,6 @@ class MenuDelegate : public ui::SimpleMenuModel::Delegate {
delegate_->SetCustomizationMode();
}
-- (void)onCheckboxChanged:(id)sender {
- DCHECK(delegate_);
- NSButton* checkbox = base::mac::ObjCCastStrict<NSButton>(sender);
- delegate_->ToggleAccept([checkbox tag], [checkbox state] == NSOnState);
-}
-
- (void)onMenuItemClicked:(int)commandId {
DCHECK(commandId == 0);
[self onCustomize:nil];

Powered by Google App Engine
This is Rietveld 408576698