Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.h " | 5 #import "chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.h " |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/mac/bind_objc_block.h" | |
| 9 #include "base/mac/foundation_util.h" | 10 #include "base/mac/foundation_util.h" |
| 10 #include "base/mac/mac_util.h" | 11 #include "base/mac/mac_util.h" |
| 11 #include "base/strings/sys_string_conversions.h" | 12 #include "base/strings/sys_string_conversions.h" |
| 12 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
| 13 #include "chrome/browser/ui/browser.h" | 14 #include "chrome/browser/ui/browser.h" |
| 14 #include "chrome/browser/ui/browser_finder.h" | 15 #include "chrome/browser/ui/browser_finder.h" |
| 15 #import "chrome/browser/ui/chrome_style.h" | 16 #import "chrome/browser/ui/chrome_style.h" |
| 16 #import "chrome/browser/ui/cocoa/browser_window_controller.h" | 17 #import "chrome/browser/ui/cocoa/browser_window_controller.h" |
| 17 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h" | 18 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h" |
| 18 #import "chrome/browser/ui/cocoa/hover_close_button.h" | 19 #import "chrome/browser/ui/cocoa/hover_close_button.h" |
| 19 #import "chrome/browser/ui/cocoa/hyperlink_text_view.h" | 20 #import "chrome/browser/ui/cocoa/hyperlink_text_view.h" |
| 20 #import "chrome/browser/ui/cocoa/info_bubble_view.h" | 21 #import "chrome/browser/ui/cocoa/info_bubble_view.h" |
| 21 #import "chrome/browser/ui/cocoa/info_bubble_window.h" | 22 #import "chrome/browser/ui/cocoa/info_bubble_window.h" |
| 22 #include "chrome/browser/ui/cocoa/website_settings/permission_bubble_cocoa.h" | 23 #include "chrome/browser/ui/cocoa/website_settings/permission_bubble_cocoa.h" |
| 24 #include "chrome/browser/ui/cocoa/website_settings/permission_selector_button.h" | |
| 23 #include "chrome/browser/ui/cocoa/website_settings/split_block_button.h" | 25 #include "chrome/browser/ui/cocoa/website_settings/split_block_button.h" |
| 24 #include "chrome/browser/ui/website_settings/permission_bubble_request.h" | 26 #include "chrome/browser/ui/website_settings/permission_bubble_request.h" |
| 25 #include "chrome/browser/ui/website_settings/permission_bubble_view.h" | 27 #include "chrome/browser/ui/website_settings/permission_bubble_view.h" |
| 28 #include "chrome/browser/ui/website_settings/permission_menu_model.h" | |
| 26 #include "content/public/browser/user_metrics.h" | 29 #include "content/public/browser/user_metrics.h" |
| 27 #include "grit/generated_resources.h" | 30 #include "grit/generated_resources.h" |
| 28 #include "skia/ext/skia_utils_mac.h" | 31 #include "skia/ext/skia_utils_mac.h" |
| 32 #import "ui/base/cocoa/menu_controller.h" | |
| 29 #include "ui/base/cocoa/window_size_constants.h" | 33 #include "ui/base/cocoa/window_size_constants.h" |
| 30 #import "ui/base/cocoa/menu_controller.h" | 34 #import "ui/base/cocoa/menu_controller.h" |
| 31 #include "ui/base/l10n/l10n_util_mac.h" | 35 #include "ui/base/l10n/l10n_util_mac.h" |
| 32 #include "ui/base/models/simple_menu_model.h" | 36 #include "ui/base/models/simple_menu_model.h" |
| 33 | 37 |
| 34 using base::UserMetricsAction; | 38 using base::UserMetricsAction; |
| 35 | 39 |
| 36 namespace { | 40 namespace { |
| 37 | 41 |
| 38 const CGFloat kHorizontalPadding = 20.0f; | 42 const CGFloat kHorizontalPadding = 20.0f; |
| 39 const CGFloat kVerticalPadding = 20.0f; | 43 const CGFloat kVerticalPadding = 20.0f; |
| 40 const CGFloat kButtonPadding = 10.0f; | 44 const CGFloat kButtonPadding = 10.0f; |
| 41 const CGFloat kTitlePaddingX = 50.0f; | 45 const CGFloat kTitlePaddingX = 50.0f; |
| 42 const CGFloat kCheckboxYAdjustment = 2.0f; | 46 const CGFloat kTitleFontSize = 15.0f; |
| 47 const CGFloat kPermissionFontSize = 12.0f; | |
| 48 const CGFloat kPermissionButtonTitleRightPadding = 4.0f; | |
| 43 | 49 |
| 44 const CGFloat kFontSize = 15.0f; | |
| 45 class MenuDelegate : public ui::SimpleMenuModel::Delegate { | 50 class MenuDelegate : public ui::SimpleMenuModel::Delegate { |
| 46 public: | 51 public: |
| 47 explicit MenuDelegate(PermissionBubbleController* bubble) | 52 explicit MenuDelegate(PermissionBubbleController* bubble) |
| 48 : bubble_controller_(bubble) {} | 53 : bubble_controller_(bubble) {} |
| 49 virtual bool IsCommandIdChecked(int command_id) const OVERRIDE { | 54 virtual bool IsCommandIdChecked(int command_id) const OVERRIDE { |
| 50 return false; | 55 return false; |
| 51 } | 56 } |
| 52 virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE { | 57 virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE { |
| 53 // TODO(leng): Change this to true once setting the bubble to be | 58 return true; |
| 54 // customizable works properly. Ideally, the bubble will alter its | |
| 55 // contents, rather than reshowing completely. | |
| 56 return false; | |
| 57 } | 59 } |
| 58 virtual bool GetAcceleratorForCommandId( | 60 virtual bool GetAcceleratorForCommandId( |
| 59 int command_id, | 61 int command_id, |
| 60 ui::Accelerator* accelerator) OVERRIDE { | 62 ui::Accelerator* accelerator) OVERRIDE { |
| 61 return false; | 63 return false; |
| 62 } | 64 } |
| 63 virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE { | 65 virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE { |
| 64 [bubble_controller_ onMenuItemClicked:command_id]; | 66 [bubble_controller_ onMenuItemClicked:command_id]; |
| 65 } | 67 } |
| 66 private: | 68 private: |
| 67 PermissionBubbleController* bubble_controller_; // Weak, owns us. | 69 PermissionBubbleController* bubble_controller_; // Weak, owns us. |
| 68 DISALLOW_COPY_AND_ASSIGN(MenuDelegate); | 70 DISALLOW_COPY_AND_ASSIGN(MenuDelegate); |
| 69 }; | 71 }; |
| 70 | 72 |
| 71 } // namespace | 73 } // namespace |
| 72 | 74 |
| 75 // NSPopUpButton with a menu containing two items: allow and block. | |
| 76 // One AllowBlockMenuButton is used for each requested permission, but only when | |
| 77 // the permission bubble is in 'customize' mode. | |
| 78 @interface AllowBlockMenuButton : NSPopUpButton { | |
| 79 @private | |
| 80 scoped_ptr<PermissionMenuModel> menuModel_; | |
| 81 base::scoped_nsobject<MenuController> menuController_; | |
| 82 } | |
| 83 | |
| 84 - (id)initForURL:(const GURL&)url | |
| 85 allowed:(BOOL)allow | |
| 86 index:(int)index | |
| 87 delegate:(PermissionBubbleView::Delegate*)delegate; | |
| 88 @end | |
| 89 | |
| 90 @implementation AllowBlockMenuButton | |
| 91 | |
| 92 - (id)initForURL:(const GURL&)url | |
| 93 allowed:(BOOL)allow | |
| 94 index:(int)index | |
| 95 delegate:(PermissionBubbleView::Delegate*)delegate { | |
| 96 if (self = [super initWithFrame:NSMakeRect(0, 0, 1, 1) pullsDown:NO]) { | |
|
groby-ooo-7-16
2014/04/25 19:25:28
Why not NSZeroRect?
leng
2014/04/25 22:18:56
Done.
| |
| 97 ContentSetting setting = | |
| 98 allow ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; | |
| 99 [self setFont:[NSFont systemFontOfSize:kPermissionFontSize]]; | |
| 100 [self setBordered:NO]; | |
| 101 | |
| 102 __block PermissionBubbleView::Delegate* blockDelegate = delegate; | |
| 103 PermissionMenuModel::ChangeCallback changeCallback = | |
| 104 base::BindBlock(^(const WebsiteSettingsUI::PermissionInfo& permission) { | |
|
groby-ooo-7-16
2014/04/25 19:25:28
I just realized we created an ObjC block for the O
leng
2014/04/25 22:18:56
On 2014/04/25 19:25:28, groby wrote:
> I just real
| |
| 105 blockDelegate->ToggleAccept( | |
| 106 index, permission.setting == CONTENT_SETTING_ALLOW); | |
| 107 }); | |
| 108 | |
| 109 menuModel_.reset(new PermissionMenuModel(url, setting, changeCallback)); | |
| 110 menuController_.reset([[MenuController alloc] initWithModel:menuModel_.get() | |
| 111 useWithPopUpButtonCell:NO]); | |
| 112 [self setMenu:[menuController_ menu]]; | |
| 113 [self selectItemAtIndex:menuModel_->GetIndexOfCommandId(setting)]; | |
| 114 [self sizeToFit]; | |
| 115 // Adjust the size to fit the current title. Using only -sizeToFit leaves | |
| 116 // an ugly amount of whitespace between the title and the arrows. | |
|
groby-ooo-7-16
2014/04/25 19:25:28
Ah. That's because NSPopUpButton's sizeToFit fits
leng
2014/04/25 22:18:56
Done.
| |
| 117 // TODO(leng): This was copied from PermissionSelectorButton. Move to a | |
| 118 // shared location, so that the code is not duplicated. | |
| 119 NSDictionary* textAttributes = @{NSFontAttributeName : [self font]}; | |
|
groby-ooo-7-16
2014/04/25 19:25:28
You could call
[[self attributedTitle] attribut
leng
2014/04/25 22:18:56
Done.
| |
| 120 NSSize titleSize = [[self title] sizeWithAttributes:textAttributes]; | |
| 121 NSRect frame = [self frame]; | |
| 122 NSRect titleRect = [[self cell] titleRectForBounds:frame]; | |
| 123 CGFloat width = titleSize.width + NSWidth(frame) - NSWidth(titleRect); | |
| 124 [self setFrameSize:NSMakeSize(width + kPermissionButtonTitleRightPadding, | |
| 125 NSHeight(frame))]; | |
| 126 } | |
| 127 return self; | |
| 128 } | |
| 129 | |
| 130 @end | |
| 131 | |
| 73 @interface PermissionBubbleController () | 132 @interface PermissionBubbleController () |
| 74 | 133 |
| 75 // Returns an autoreleased NSView displaying the icon and label for |request|. | 134 // Returns an autoreleased NSView displaying the icon and label for |request|. |
| 76 - (NSView*)labelForRequest:(PermissionBubbleRequest*)request; | 135 - (NSView*)labelForRequest:(PermissionBubbleRequest*)request; |
| 77 | 136 |
| 78 // Returns an autoreleased NSView displaying the title for the bubble | 137 // Returns an autoreleased NSView displaying the title for the bubble |
| 79 // requesting settings for |host|. | 138 // requesting settings for |host|. |
| 80 - (NSView*)titleWithHostname:(const std::string&)host; | 139 - (NSView*)titleWithHostname:(const std::string&)host; |
| 81 | 140 |
| 82 // Returns an autoreleased NSView displaying a checkbox for |request|. The | 141 // Returns an autoreleased NSView displaying a menu for |request|. The |
| 83 // checkbox will be initialized as checked if |checked| is YES. | 142 // menu will be initialized as 'allow' if |allow| is YES. |
| 84 - (NSView*)checkboxForRequest:(PermissionBubbleRequest*)request | 143 - (NSView*)menuForRequest:(PermissionBubbleRequest*)request |
| 85 checked:(BOOL)checked; | 144 atIndex:(int)index |
| 145 allow:(BOOL)allow; | |
| 86 | 146 |
| 87 // Returns an autoreleased NSView of a button with |title| and |action|. | 147 // Returns an autoreleased NSView of a button with |title| and |action|. |
| 88 - (NSView*)buttonWithTitle:(NSString*)title | 148 - (NSView*)buttonWithTitle:(NSString*)title |
| 89 action:(SEL)action; | 149 action:(SEL)action; |
| 90 | 150 |
| 91 // Returns an autoreleased NSView displaying a block button. | 151 // Returns an autoreleased NSView displaying a block button. |
| 92 - (NSView*)blockButton; | 152 - (NSView*)blockButton; |
| 93 | 153 |
| 94 // Returns an autoreleased NSView with a block button and a drop-down menu | 154 // Returns an autoreleased NSView with a block button and a drop-down menu |
| 95 // with one item, which will change the UI to allow customizing the permissions. | 155 // with one item, which will change the UI to allow customizing the permissions. |
| 96 - (NSView*)blockButtonWithCustomizeMenu; | 156 - (NSView*)blockButtonWithCustomizeMenu; |
| 97 | 157 |
| 98 // Returns an autoreleased NSView displaying the close 'x' button. | 158 // Returns an autoreleased NSView displaying the close 'x' button. |
| 99 - (NSView*)closeButton; | 159 - (NSView*)closeButton; |
| 100 | 160 |
| 101 // Sets the width of both |viewA| and |viewB| to be the larger of the | |
| 102 // two views' widths. Does not change either view's origin or height. | |
| 103 - (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB; | |
| 104 | |
| 105 // Called when the 'ok' button is pressed. | 161 // Called when the 'ok' button is pressed. |
| 106 - (void)ok:(id)sender; | 162 - (void)ok:(id)sender; |
| 107 | 163 |
| 108 // Called when the 'allow' button is pressed. | 164 // Called when the 'allow' button is pressed. |
| 109 - (void)onAllow:(id)sender; | 165 - (void)onAllow:(id)sender; |
| 110 | 166 |
| 111 // Called when the 'block' button is pressed. | 167 // Called when the 'block' button is pressed. |
| 112 - (void)onBlock:(id)sender; | 168 - (void)onBlock:(id)sender; |
| 113 | 169 |
| 114 // Called when the 'close' button is pressed. | 170 // Called when the 'close' button is pressed. |
| 115 - (void)onClose:(id)sender; | 171 - (void)onClose:(id)sender; |
| 116 | 172 |
| 117 // Called when the 'customize' button is pressed. | 173 // Called when the 'customize' button is pressed. |
| 118 - (void)onCustomize:(id)sender; | 174 - (void)onCustomize:(id)sender; |
| 119 | 175 |
| 120 // Called when a checkbox changes from checked to unchecked, or vice versa. | 176 // Sets the width of both |viewA| and |viewB| to be the larger of the |
| 121 - (void)onCheckboxChanged:(id)sender; | 177 // two views' widths. Does not change either view's origin or height. |
| 178 + (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB; | |
| 179 | |
| 180 // Sets the offset of |viewA| so that its vertical center is aligned with the | |
| 181 // vertical center of |viewB|. | |
| 182 + (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB; | |
| 122 | 183 |
| 123 @end | 184 @end |
| 124 | 185 |
| 125 @implementation PermissionBubbleController | 186 @implementation PermissionBubbleController |
| 126 | 187 |
| 127 - (id)initWithParentWindow:(NSWindow*)parentWindow | 188 - (id)initWithParentWindow:(NSWindow*)parentWindow |
| 128 bridge:(PermissionBubbleCocoa*)bridge { | 189 bridge:(PermissionBubbleCocoa*)bridge { |
| 129 DCHECK(parentWindow); | 190 DCHECK(parentWindow); |
| 130 DCHECK(bridge); | 191 DCHECK(bridge); |
| 131 base::scoped_nsobject<InfoBubbleWindow> window([[InfoBubbleWindow alloc] | 192 base::scoped_nsobject<InfoBubbleWindow> window([[InfoBubbleWindow alloc] |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 allowOrOkButton.reset([[self buttonWithTitle:okTitle | 230 allowOrOkButton.reset([[self buttonWithTitle:okTitle |
| 170 action:@selector(ok:)] retain]); | 231 action:@selector(ok:)] retain]); |
| 171 } else { | 232 } else { |
| 172 NSString* allowTitle = l10n_util::GetNSString(IDS_PERMISSION_ALLOW); | 233 NSString* allowTitle = l10n_util::GetNSString(IDS_PERMISSION_ALLOW); |
| 173 allowOrOkButton.reset([[self buttonWithTitle:allowTitle | 234 allowOrOkButton.reset([[self buttonWithTitle:allowTitle |
| 174 action:@selector(onAllow:)] retain]); | 235 action:@selector(onAllow:)] retain]); |
| 175 } | 236 } |
| 176 CGFloat yOffset = 2 * kVerticalPadding + NSMaxY([allowOrOkButton frame]); | 237 CGFloat yOffset = 2 * kVerticalPadding + NSMaxY([allowOrOkButton frame]); |
| 177 BOOL singlePermission = requests.size() == 1; | 238 BOOL singlePermission = requests.size() == 1; |
| 178 | 239 |
| 179 checkboxes_.reset(customizationMode ? [[NSMutableArray alloc] init] : nil); | 240 base::scoped_nsobject<NSMutableArray> permissionMenus; |
| 241 if (customizationMode) | |
| 242 permissionMenus.reset([[NSMutableArray alloc] init]); | |
| 243 | |
| 180 for (auto it = requests.begin(); it != requests.end(); it++) { | 244 for (auto it = requests.begin(); it != requests.end(); it++) { |
| 181 base::scoped_nsobject<NSView> permissionView; | 245 base::scoped_nsobject<NSView> permissionView( |
| 182 if (customizationMode) { | 246 [[self labelForRequest:(*it)] retain]); |
| 183 int index = it - requests.begin(); | |
| 184 permissionView.reset( | |
| 185 [[self checkboxForRequest:(*it) | |
| 186 checked:acceptStates[index] ? YES : NO] retain]); | |
| 187 [base::mac::ObjCCastStrict<NSButton>(permissionView) setTag:index]; | |
| 188 [checkboxes_ addObject:permissionView]; | |
| 189 } else { | |
| 190 permissionView.reset([[self labelForRequest:(*it)] retain]); | |
| 191 } | |
| 192 NSPoint origin = [permissionView frame].origin; | 247 NSPoint origin = [permissionView frame].origin; |
| 193 origin.x += kHorizontalPadding; | 248 origin.x += kHorizontalPadding; |
| 194 origin.y += yOffset; | 249 origin.y += yOffset; |
| 195 [permissionView setFrameOrigin:origin]; | 250 [permissionView setFrameOrigin:origin]; |
| 196 [contentView addSubview:permissionView]; | 251 [contentView addSubview:permissionView]; |
| 197 | 252 |
| 253 if (customizationMode) { | |
| 254 int index = it - requests.begin(); | |
| 255 base::scoped_nsobject<NSView> menu( | |
| 256 [[self menuForRequest:(*it) | |
| 257 atIndex:index | |
| 258 allow:acceptStates[index] ? YES : NO] retain]); | |
| 259 // Align vertically. Horizontal alignment will be adjusted once the | |
| 260 // widest permission is know. | |
| 261 [PermissionBubbleController alignCenterOf:menu | |
| 262 verticallyToCenterOf:permissionView]; | |
| 263 [permissionMenus addObject:menu]; | |
| 264 [contentView addSubview:menu]; | |
| 265 } | |
| 198 yOffset += NSHeight([permissionView frame]); | 266 yOffset += NSHeight([permissionView frame]); |
| 199 } | 267 } |
| 200 | 268 |
| 201 // The maximum width of the above permissions will dictate the width of the | 269 // The maximum width of the above permissions will dictate the width of the |
| 202 // bubble. It is calculated here so that it can be used for the positioning | 270 // bubble. It is calculated here so that it can be used for the positioning |
| 203 // of the buttons. | 271 // of the buttons. |
| 204 NSRect bubbleFrame = NSZeroRect; | 272 NSRect bubbleFrame = NSZeroRect; |
| 205 for (NSView* view in [contentView subviews]) { | 273 for (NSView* view in [contentView subviews]) { |
| 206 bubbleFrame = NSUnionRect( | 274 bubbleFrame = NSUnionRect( |
| 207 bubbleFrame, NSInsetRect([view frame], -kHorizontalPadding, 0)); | 275 bubbleFrame, NSInsetRect([view frame], -kHorizontalPadding, 0)); |
| 208 } | 276 } |
| 209 | 277 |
| 278 if (customizationMode) { | |
| 279 // Adjust the horizontal origin for each menu. | |
| 280 CGFloat xOffset = NSWidth(bubbleFrame) - kHorizontalPadding; | |
| 281 CGFloat maxMenuWidth = 0; | |
| 282 for (NSView* view in permissionMenus.get()) { | |
| 283 [view setFrameOrigin:NSMakePoint(xOffset, NSMinY([view frame]))]; | |
| 284 maxMenuWidth = std::max(maxMenuWidth, NSWidth([view frame])); | |
| 285 } | |
| 286 // And add the menu width to the bubble's width. | |
| 287 bubbleFrame.size.width += maxMenuWidth; | |
| 288 } | |
| 289 | |
| 210 base::scoped_nsobject<NSView> titleView( | 290 base::scoped_nsobject<NSView> titleView( |
| 211 [[self titleWithHostname:requests[0]->GetRequestingHostname().host()] | 291 [[self titleWithHostname:requests[0]->GetRequestingHostname().host()] |
| 212 retain]); | 292 retain]); |
| 213 [contentView addSubview:titleView]; | 293 [contentView addSubview:titleView]; |
| 214 [titleView setFrameOrigin:NSMakePoint(kHorizontalPadding, | 294 [titleView setFrameOrigin:NSMakePoint(kHorizontalPadding, |
| 215 kVerticalPadding + yOffset)]; | 295 kVerticalPadding + yOffset)]; |
| 216 yOffset += NSHeight([titleView frame]) + kVerticalPadding; | 296 yOffset += NSHeight([titleView frame]) + kVerticalPadding; |
| 217 | 297 |
| 218 // The title must fit within the bubble. | 298 // The title must fit within the bubble. |
| 219 bubbleFrame.size.width = std::max(NSWidth(bubbleFrame), | 299 bubbleFrame.size.width = std::max(NSWidth(bubbleFrame), |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 235 kHorizontalPadding; | 315 kHorizontalPadding; |
| 236 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; | 316 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; |
| 237 [contentView addSubview:allowOrOkButton]; | 317 [contentView addSubview:allowOrOkButton]; |
| 238 | 318 |
| 239 if (!customizationMode) { | 319 if (!customizationMode) { |
| 240 base::scoped_nsobject<NSView> blockButton; | 320 base::scoped_nsobject<NSView> blockButton; |
| 241 if (singlePermission) | 321 if (singlePermission) |
| 242 blockButton.reset([[self blockButton] retain]); | 322 blockButton.reset([[self blockButton] retain]); |
| 243 else | 323 else |
| 244 blockButton.reset([[self blockButtonWithCustomizeMenu] retain]); | 324 blockButton.reset([[self blockButtonWithCustomizeMenu] retain]); |
| 245 CGFloat width = [self matchWidthsOf:blockButton andOf:allowOrOkButton]; | 325 CGFloat width = [PermissionBubbleController matchWidthsOf:blockButton |
| 326 andOf:allowOrOkButton]; | |
| 246 // Ensure the allow/ok button is still in the correct position. | 327 // Ensure the allow/ok button is still in the correct position. |
| 247 xOrigin = NSWidth(bubbleFrame) - width - kHorizontalPadding; | 328 xOrigin = NSWidth(bubbleFrame) - width - kHorizontalPadding; |
| 248 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; | 329 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; |
| 249 // Line up the block button. | 330 // Line up the block button. |
| 250 xOrigin = NSMinX([allowOrOkButton frame]) - width - kButtonPadding; | 331 xOrigin = NSMinX([allowOrOkButton frame]) - width - kButtonPadding; |
| 251 [blockButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; | 332 [blockButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; |
| 252 [contentView addSubview:blockButton]; | 333 [contentView addSubview:blockButton]; |
| 253 } | 334 } |
| 254 | 335 |
| 255 bubbleFrame.size.height = yOffset + kVerticalPadding; | 336 bubbleFrame.size.height = yOffset + kVerticalPadding; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 283 [permissionIcon setFrameSize:[[permissionIcon image] size]]; | 364 [permissionIcon setFrameSize:[[permissionIcon image] size]]; |
| 284 [permissionView addSubview:permissionIcon]; | 365 [permissionView addSubview:permissionIcon]; |
| 285 | 366 |
| 286 base::scoped_nsobject<NSTextField> permissionLabel( | 367 base::scoped_nsobject<NSTextField> permissionLabel( |
| 287 [[NSTextField alloc] initWithFrame:NSZeroRect]); | 368 [[NSTextField alloc] initWithFrame:NSZeroRect]); |
| 288 base::string16 label = request->GetMessageTextFragment(); | 369 base::string16 label = request->GetMessageTextFragment(); |
| 289 [permissionLabel setDrawsBackground:NO]; | 370 [permissionLabel setDrawsBackground:NO]; |
| 290 [permissionLabel setBezeled:NO]; | 371 [permissionLabel setBezeled:NO]; |
| 291 [permissionLabel setEditable:NO]; | 372 [permissionLabel setEditable:NO]; |
| 292 [permissionLabel setSelectable:NO]; | 373 [permissionLabel setSelectable:NO]; |
| 374 [permissionLabel setFont:[NSFont systemFontOfSize:kPermissionFontSize]]; | |
| 293 [permissionLabel setStringValue:base::SysUTF16ToNSString(label)]; | 375 [permissionLabel setStringValue:base::SysUTF16ToNSString(label)]; |
| 294 [permissionLabel sizeToFit]; | 376 [permissionLabel sizeToFit]; |
| 295 [permissionLabel setFrameOrigin: | 377 [permissionLabel setFrameOrigin: |
| 296 NSMakePoint(NSWidth([permissionIcon frame]), 0)]; | 378 NSMakePoint(NSWidth([permissionIcon frame]), 0)]; |
| 297 [permissionView addSubview:permissionLabel]; | 379 [permissionView addSubview:permissionLabel]; |
| 298 | 380 |
| 299 // Match the horizontal centers of the two subviews. Note that the label's | 381 // Match the horizontal centers of the two subviews. Note that the label's |
| 300 // center is rounded down, and the icon's center, up. It looks better that | 382 // center is rounded down, and the icon's center, up. It looks better that |
| 301 // way - with the text's center slightly lower than the icon's center - if the | 383 // way - with the text's center slightly lower than the icon's center - if the |
| 302 // height delta is not evenly split. | 384 // height delta is not evenly split. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 319 - (NSView*)titleWithHostname:(const std::string&)host { | 401 - (NSView*)titleWithHostname:(const std::string&)host { |
| 320 base::scoped_nsobject<NSTextField> titleView( | 402 base::scoped_nsobject<NSTextField> titleView( |
| 321 [[NSTextField alloc] initWithFrame:NSZeroRect]); | 403 [[NSTextField alloc] initWithFrame:NSZeroRect]); |
| 322 [titleView setDrawsBackground:NO]; | 404 [titleView setDrawsBackground:NO]; |
| 323 [titleView setBezeled:NO]; | 405 [titleView setBezeled:NO]; |
| 324 [titleView setEditable:NO]; | 406 [titleView setEditable:NO]; |
| 325 [titleView setSelectable:NO]; | 407 [titleView setSelectable:NO]; |
| 326 [titleView setStringValue: | 408 [titleView setStringValue: |
| 327 l10n_util::GetNSStringF(IDS_PERMISSIONS_BUBBLE_PROMPT, | 409 l10n_util::GetNSStringF(IDS_PERMISSIONS_BUBBLE_PROMPT, |
| 328 base::UTF8ToUTF16(host))]; | 410 base::UTF8ToUTF16(host))]; |
| 329 [titleView setFont:[NSFont systemFontOfSize:kFontSize]]; | 411 [titleView setFont:[NSFont systemFontOfSize:kTitleFontSize]]; |
| 330 [titleView sizeToFit]; | 412 [titleView sizeToFit]; |
| 331 NSRect titleFrame = [titleView frame]; | 413 NSRect titleFrame = [titleView frame]; |
| 332 [titleView setFrameSize:NSMakeSize(NSWidth(titleFrame) + kTitlePaddingX, | 414 [titleView setFrameSize:NSMakeSize(NSWidth(titleFrame) + kTitlePaddingX, |
| 333 NSHeight(titleFrame))]; | 415 NSHeight(titleFrame))]; |
| 334 return titleView.autorelease(); | 416 return titleView.autorelease(); |
| 335 } | 417 } |
| 336 | 418 |
| 337 - (NSView*)checkboxForRequest:(PermissionBubbleRequest*)request | 419 - (NSView*)menuForRequest:(PermissionBubbleRequest*)request |
| 338 checked:(BOOL)checked { | 420 atIndex:(int)index |
| 421 allow:(BOOL)allow { | |
| 339 DCHECK(request); | 422 DCHECK(request); |
| 340 base::scoped_nsobject<NSButton> checkbox( | 423 DCHECK(delegate_); |
| 341 [[NSButton alloc] initWithFrame:NSZeroRect]); | 424 base::scoped_nsobject<AllowBlockMenuButton> button( |
| 342 [checkbox setButtonType:NSSwitchButton]; | 425 [[AllowBlockMenuButton alloc] initForURL:request->GetRequestingHostname() |
| 343 base::string16 permission = request->GetMessageTextFragment(); | 426 allowed:allow |
| 344 [checkbox setTitle:base::SysUTF16ToNSString(permission)]; | 427 index:index |
| 345 [checkbox setState:(checked ? NSOnState : NSOffState)]; | 428 delegate:delegate_]); |
| 346 [checkbox setTarget:self]; | 429 return button.autorelease(); |
| 347 [checkbox setAction:@selector(onCheckboxChanged:)]; | |
| 348 [checkbox sizeToFit]; | |
| 349 [checkbox setFrameOrigin:NSMakePoint(0, kCheckboxYAdjustment)]; | |
| 350 return checkbox.autorelease(); | |
| 351 } | 430 } |
| 352 | 431 |
| 353 - (NSView*)buttonWithTitle:(NSString*)title | 432 - (NSView*)buttonWithTitle:(NSString*)title |
| 354 action:(SEL)action { | 433 action:(SEL)action { |
| 355 base::scoped_nsobject<NSButton> button( | 434 base::scoped_nsobject<NSButton> button( |
| 356 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]); | 435 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]); |
| 357 [button setButtonType:NSMomentaryPushInButton]; | 436 [button setButtonType:NSMomentaryPushInButton]; |
| 358 [button setTitle:title]; | 437 [button setTitle:title]; |
| 359 [button setTarget:self]; | 438 [button setTarget:self]; |
| 360 [button setAction:action]; | 439 [button setAction:action]; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 382 - (NSView*)closeButton { | 461 - (NSView*)closeButton { |
| 383 int dimension = chrome_style::GetCloseButtonSize(); | 462 int dimension = chrome_style::GetCloseButtonSize(); |
| 384 NSRect frame = NSMakeRect(0, 0, dimension, dimension); | 463 NSRect frame = NSMakeRect(0, 0, dimension, dimension); |
| 385 base::scoped_nsobject<NSButton> button( | 464 base::scoped_nsobject<NSButton> button( |
| 386 [[WebUIHoverCloseButton alloc] initWithFrame:frame]); | 465 [[WebUIHoverCloseButton alloc] initWithFrame:frame]); |
| 387 [button setAction:@selector(onClose:)]; | 466 [button setAction:@selector(onClose:)]; |
| 388 [button setTarget:self]; | 467 [button setTarget:self]; |
| 389 return button.autorelease(); | 468 return button.autorelease(); |
| 390 } | 469 } |
| 391 | 470 |
| 392 - (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB { | |
| 393 NSRect frameA = [viewA frame]; | |
| 394 NSRect frameB = [viewB frame]; | |
| 395 CGFloat width = std::max(NSWidth(frameA), NSWidth(frameB)); | |
| 396 [viewA setFrameSize:NSMakeSize(width, NSHeight(frameA))]; | |
| 397 [viewB setFrameSize:NSMakeSize(width, NSHeight(frameB))]; | |
| 398 return width; | |
| 399 } | |
| 400 | |
| 401 - (void)ok:(id)sender { | 471 - (void)ok:(id)sender { |
| 402 DCHECK(delegate_); | 472 DCHECK(delegate_); |
| 403 delegate_->Closing(); | 473 delegate_->Closing(); |
| 404 } | 474 } |
| 405 | 475 |
| 406 - (void)onAllow:(id)sender { | 476 - (void)onAllow:(id)sender { |
| 407 DCHECK(delegate_); | 477 DCHECK(delegate_); |
| 408 delegate_->Accept(); | 478 delegate_->Accept(); |
| 409 } | 479 } |
| 410 | 480 |
| 411 - (void)onBlock:(id)sender { | 481 - (void)onBlock:(id)sender { |
| 412 DCHECK(delegate_); | 482 DCHECK(delegate_); |
| 413 delegate_->Deny(); | 483 delegate_->Deny(); |
| 414 } | 484 } |
| 415 | 485 |
| 416 - (void)onClose:(id)sender { | 486 - (void)onClose:(id)sender { |
| 417 DCHECK(delegate_); | 487 DCHECK(delegate_); |
| 418 delegate_->Closing(); | 488 delegate_->Closing(); |
| 419 } | 489 } |
| 420 | 490 |
| 421 - (void)onCustomize:(id)sender { | 491 - (void)onCustomize:(id)sender { |
| 422 DCHECK(delegate_); | 492 DCHECK(delegate_); |
| 423 delegate_->SetCustomizationMode(); | 493 delegate_->SetCustomizationMode(); |
| 424 } | 494 } |
| 425 | 495 |
| 426 - (void)onCheckboxChanged:(id)sender { | |
| 427 DCHECK(delegate_); | |
| 428 NSButton* checkbox = base::mac::ObjCCastStrict<NSButton>(sender); | |
| 429 delegate_->ToggleAccept([checkbox tag], [checkbox state] == NSOnState); | |
| 430 } | |
| 431 | |
| 432 - (void)onMenuItemClicked:(int)commandId { | 496 - (void)onMenuItemClicked:(int)commandId { |
| 433 DCHECK(commandId == 0); | 497 DCHECK(commandId == 0); |
| 434 [self onCustomize:nil]; | 498 [self onCustomize:nil]; |
| 435 } | 499 } |
| 436 | 500 |
| 501 + (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB { | |
| 502 NSRect frameA = [viewA frame]; | |
| 503 NSRect frameB = [viewB frame]; | |
| 504 CGFloat width = std::max(NSWidth(frameA), NSWidth(frameB)); | |
| 505 [viewA setFrameSize:NSMakeSize(width, NSHeight(frameA))]; | |
| 506 [viewB setFrameSize:NSMakeSize(width, NSHeight(frameB))]; | |
| 507 return width; | |
| 508 } | |
| 509 | |
| 510 + (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB { | |
| 511 NSRect frameA = [viewA frame]; | |
| 512 NSRect frameB = [viewB frame]; | |
| 513 frameA.origin.y = | |
| 514 NSMinY(frameB) + std::floor((NSHeight(frameB) - NSHeight(frameA)) / 2); | |
| 515 [viewA setFrameOrigin:frameA.origin]; | |
| 516 } | |
| 517 | |
| 437 @end // implementation PermissionBubbleController | 518 @end // implementation PermissionBubbleController |
| OLD | NEW |