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:NSZeroRect pullsDown:NO]) { |
| 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) { |
| 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 because it |
| 117 // will fit to the largest element in the menu, not just the selected item. |
| 118 // TODO(leng): This was copied from PermissionSelectorButton. Move to a |
| 119 // shared location, so that the code is not duplicated. |
| 120 NSDictionary* textAttributes = |
| 121 [[self attributedTitle] attributesAtIndex:0 effectiveRange:NULL]; |
| 122 NSSize titleSize = [[self title] sizeWithAttributes:textAttributes]; |
| 123 NSRect frame = [self frame]; |
| 124 NSRect titleRect = [[self cell] titleRectForBounds:frame]; |
| 125 CGFloat width = titleSize.width + NSWidth(frame) - NSWidth(titleRect); |
| 126 [self setFrameSize:NSMakeSize(width + kPermissionButtonTitleRightPadding, |
| 127 NSHeight(frame))]; |
| 128 } |
| 129 return self; |
| 130 } |
| 131 |
| 132 @end |
| 133 |
73 @interface PermissionBubbleController () | 134 @interface PermissionBubbleController () |
74 | 135 |
75 // Returns an autoreleased NSView displaying the icon and label for |request|. | 136 // Returns an autoreleased NSView displaying the icon and label for |request|. |
76 - (NSView*)labelForRequest:(PermissionBubbleRequest*)request; | 137 - (NSView*)labelForRequest:(PermissionBubbleRequest*)request; |
77 | 138 |
78 // Returns an autoreleased NSView displaying the title for the bubble | 139 // Returns an autoreleased NSView displaying the title for the bubble |
79 // requesting settings for |host|. | 140 // requesting settings for |host|. |
80 - (NSView*)titleWithHostname:(const std::string&)host; | 141 - (NSView*)titleWithHostname:(const std::string&)host; |
81 | 142 |
82 // Returns an autoreleased NSView displaying a checkbox for |request|. The | 143 // Returns an autoreleased NSView displaying a menu for |request|. The |
83 // checkbox will be initialized as checked if |checked| is YES. | 144 // menu will be initialized as 'allow' if |allow| is YES. |
84 - (NSView*)checkboxForRequest:(PermissionBubbleRequest*)request | 145 - (NSView*)menuForRequest:(PermissionBubbleRequest*)request |
85 checked:(BOOL)checked; | 146 atIndex:(int)index |
| 147 allow:(BOOL)allow; |
86 | 148 |
87 // Returns an autoreleased NSView of a button with |title| and |action|. | 149 // Returns an autoreleased NSView of a button with |title| and |action|. |
88 - (NSView*)buttonWithTitle:(NSString*)title | 150 - (NSView*)buttonWithTitle:(NSString*)title |
89 action:(SEL)action; | 151 action:(SEL)action; |
90 | 152 |
91 // Returns an autoreleased NSView displaying a block button. | 153 // Returns an autoreleased NSView displaying a block button. |
92 - (NSView*)blockButton; | 154 - (NSView*)blockButton; |
93 | 155 |
94 // Returns an autoreleased NSView with a block button and a drop-down menu | 156 // 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. | 157 // with one item, which will change the UI to allow customizing the permissions. |
96 - (NSView*)blockButtonWithCustomizeMenu; | 158 - (NSView*)blockButtonWithCustomizeMenu; |
97 | 159 |
98 // Returns an autoreleased NSView displaying the close 'x' button. | 160 // Returns an autoreleased NSView displaying the close 'x' button. |
99 - (NSView*)closeButton; | 161 - (NSView*)closeButton; |
100 | 162 |
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. | 163 // Called when the 'ok' button is pressed. |
106 - (void)ok:(id)sender; | 164 - (void)ok:(id)sender; |
107 | 165 |
108 // Called when the 'allow' button is pressed. | 166 // Called when the 'allow' button is pressed. |
109 - (void)onAllow:(id)sender; | 167 - (void)onAllow:(id)sender; |
110 | 168 |
111 // Called when the 'block' button is pressed. | 169 // Called when the 'block' button is pressed. |
112 - (void)onBlock:(id)sender; | 170 - (void)onBlock:(id)sender; |
113 | 171 |
114 // Called when the 'close' button is pressed. | 172 // Called when the 'close' button is pressed. |
115 - (void)onClose:(id)sender; | 173 - (void)onClose:(id)sender; |
116 | 174 |
117 // Called when the 'customize' button is pressed. | 175 // Called when the 'customize' button is pressed. |
118 - (void)onCustomize:(id)sender; | 176 - (void)onCustomize:(id)sender; |
119 | 177 |
120 // Called when a checkbox changes from checked to unchecked, or vice versa. | 178 // Sets the width of both |viewA| and |viewB| to be the larger of the |
121 - (void)onCheckboxChanged:(id)sender; | 179 // two views' widths. Does not change either view's origin or height. |
| 180 + (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB; |
| 181 |
| 182 // Sets the offset of |viewA| so that its vertical center is aligned with the |
| 183 // vertical center of |viewB|. |
| 184 + (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB; |
122 | 185 |
123 @end | 186 @end |
124 | 187 |
125 @implementation PermissionBubbleController | 188 @implementation PermissionBubbleController |
126 | 189 |
127 - (id)initWithParentWindow:(NSWindow*)parentWindow | 190 - (id)initWithParentWindow:(NSWindow*)parentWindow |
128 bridge:(PermissionBubbleCocoa*)bridge { | 191 bridge:(PermissionBubbleCocoa*)bridge { |
129 DCHECK(parentWindow); | 192 DCHECK(parentWindow); |
130 DCHECK(bridge); | 193 DCHECK(bridge); |
131 base::scoped_nsobject<InfoBubbleWindow> window([[InfoBubbleWindow alloc] | 194 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 | 232 allowOrOkButton.reset([[self buttonWithTitle:okTitle |
170 action:@selector(ok:)] retain]); | 233 action:@selector(ok:)] retain]); |
171 } else { | 234 } else { |
172 NSString* allowTitle = l10n_util::GetNSString(IDS_PERMISSION_ALLOW); | 235 NSString* allowTitle = l10n_util::GetNSString(IDS_PERMISSION_ALLOW); |
173 allowOrOkButton.reset([[self buttonWithTitle:allowTitle | 236 allowOrOkButton.reset([[self buttonWithTitle:allowTitle |
174 action:@selector(onAllow:)] retain]); | 237 action:@selector(onAllow:)] retain]); |
175 } | 238 } |
176 CGFloat yOffset = 2 * kVerticalPadding + NSMaxY([allowOrOkButton frame]); | 239 CGFloat yOffset = 2 * kVerticalPadding + NSMaxY([allowOrOkButton frame]); |
177 BOOL singlePermission = requests.size() == 1; | 240 BOOL singlePermission = requests.size() == 1; |
178 | 241 |
179 checkboxes_.reset(customizationMode ? [[NSMutableArray alloc] init] : nil); | 242 base::scoped_nsobject<NSMutableArray> permissionMenus; |
| 243 if (customizationMode) |
| 244 permissionMenus.reset([[NSMutableArray alloc] init]); |
| 245 |
180 for (auto it = requests.begin(); it != requests.end(); it++) { | 246 for (auto it = requests.begin(); it != requests.end(); it++) { |
181 base::scoped_nsobject<NSView> permissionView; | 247 base::scoped_nsobject<NSView> permissionView( |
182 if (customizationMode) { | 248 [[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; | 249 NSPoint origin = [permissionView frame].origin; |
193 origin.x += kHorizontalPadding; | 250 origin.x += kHorizontalPadding; |
194 origin.y += yOffset; | 251 origin.y += yOffset; |
195 [permissionView setFrameOrigin:origin]; | 252 [permissionView setFrameOrigin:origin]; |
196 [contentView addSubview:permissionView]; | 253 [contentView addSubview:permissionView]; |
197 | 254 |
| 255 if (customizationMode) { |
| 256 int index = it - requests.begin(); |
| 257 base::scoped_nsobject<NSView> menu( |
| 258 [[self menuForRequest:(*it) |
| 259 atIndex:index |
| 260 allow:acceptStates[index] ? YES : NO] retain]); |
| 261 // Align vertically. Horizontal alignment will be adjusted once the |
| 262 // widest permission is know. |
| 263 [PermissionBubbleController alignCenterOf:menu |
| 264 verticallyToCenterOf:permissionView]; |
| 265 [permissionMenus addObject:menu]; |
| 266 [contentView addSubview:menu]; |
| 267 } |
198 yOffset += NSHeight([permissionView frame]); | 268 yOffset += NSHeight([permissionView frame]); |
199 } | 269 } |
200 | 270 |
201 // The maximum width of the above permissions will dictate the width of the | 271 // 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 | 272 // bubble. It is calculated here so that it can be used for the positioning |
203 // of the buttons. | 273 // of the buttons. |
204 NSRect bubbleFrame = NSZeroRect; | 274 NSRect bubbleFrame = NSZeroRect; |
205 for (NSView* view in [contentView subviews]) { | 275 for (NSView* view in [contentView subviews]) { |
206 bubbleFrame = NSUnionRect( | 276 bubbleFrame = NSUnionRect( |
207 bubbleFrame, NSInsetRect([view frame], -kHorizontalPadding, 0)); | 277 bubbleFrame, NSInsetRect([view frame], -kHorizontalPadding, 0)); |
208 } | 278 } |
209 | 279 |
| 280 if (customizationMode) { |
| 281 // Adjust the horizontal origin for each menu. |
| 282 CGFloat xOffset = NSWidth(bubbleFrame) - kHorizontalPadding; |
| 283 CGFloat maxMenuWidth = 0; |
| 284 for (NSView* view in permissionMenus.get()) { |
| 285 [view setFrameOrigin:NSMakePoint(xOffset, NSMinY([view frame]))]; |
| 286 maxMenuWidth = std::max(maxMenuWidth, NSWidth([view frame])); |
| 287 } |
| 288 // And add the menu width to the bubble's width. |
| 289 bubbleFrame.size.width += maxMenuWidth; |
| 290 } |
| 291 |
210 base::scoped_nsobject<NSView> titleView( | 292 base::scoped_nsobject<NSView> titleView( |
211 [[self titleWithHostname:requests[0]->GetRequestingHostname().host()] | 293 [[self titleWithHostname:requests[0]->GetRequestingHostname().host()] |
212 retain]); | 294 retain]); |
213 [contentView addSubview:titleView]; | 295 [contentView addSubview:titleView]; |
214 [titleView setFrameOrigin:NSMakePoint(kHorizontalPadding, | 296 [titleView setFrameOrigin:NSMakePoint(kHorizontalPadding, |
215 kVerticalPadding + yOffset)]; | 297 kVerticalPadding + yOffset)]; |
216 yOffset += NSHeight([titleView frame]) + kVerticalPadding; | 298 yOffset += NSHeight([titleView frame]) + kVerticalPadding; |
217 | 299 |
218 // The title must fit within the bubble. | 300 // The title must fit within the bubble. |
219 bubbleFrame.size.width = std::max(NSWidth(bubbleFrame), | 301 bubbleFrame.size.width = std::max(NSWidth(bubbleFrame), |
(...skipping 15 matching lines...) Expand all Loading... |
235 kHorizontalPadding; | 317 kHorizontalPadding; |
236 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; | 318 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; |
237 [contentView addSubview:allowOrOkButton]; | 319 [contentView addSubview:allowOrOkButton]; |
238 | 320 |
239 if (!customizationMode) { | 321 if (!customizationMode) { |
240 base::scoped_nsobject<NSView> blockButton; | 322 base::scoped_nsobject<NSView> blockButton; |
241 if (singlePermission) | 323 if (singlePermission) |
242 blockButton.reset([[self blockButton] retain]); | 324 blockButton.reset([[self blockButton] retain]); |
243 else | 325 else |
244 blockButton.reset([[self blockButtonWithCustomizeMenu] retain]); | 326 blockButton.reset([[self blockButtonWithCustomizeMenu] retain]); |
245 CGFloat width = [self matchWidthsOf:blockButton andOf:allowOrOkButton]; | 327 CGFloat width = [PermissionBubbleController matchWidthsOf:blockButton |
| 328 andOf:allowOrOkButton]; |
246 // Ensure the allow/ok button is still in the correct position. | 329 // Ensure the allow/ok button is still in the correct position. |
247 xOrigin = NSWidth(bubbleFrame) - width - kHorizontalPadding; | 330 xOrigin = NSWidth(bubbleFrame) - width - kHorizontalPadding; |
248 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; | 331 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; |
249 // Line up the block button. | 332 // Line up the block button. |
250 xOrigin = NSMinX([allowOrOkButton frame]) - width - kButtonPadding; | 333 xOrigin = NSMinX([allowOrOkButton frame]) - width - kButtonPadding; |
251 [blockButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; | 334 [blockButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; |
252 [contentView addSubview:blockButton]; | 335 [contentView addSubview:blockButton]; |
253 } | 336 } |
254 | 337 |
255 bubbleFrame.size.height = yOffset + kVerticalPadding; | 338 bubbleFrame.size.height = yOffset + kVerticalPadding; |
(...skipping 27 matching lines...) Expand all Loading... |
283 [permissionIcon setFrameSize:[[permissionIcon image] size]]; | 366 [permissionIcon setFrameSize:[[permissionIcon image] size]]; |
284 [permissionView addSubview:permissionIcon]; | 367 [permissionView addSubview:permissionIcon]; |
285 | 368 |
286 base::scoped_nsobject<NSTextField> permissionLabel( | 369 base::scoped_nsobject<NSTextField> permissionLabel( |
287 [[NSTextField alloc] initWithFrame:NSZeroRect]); | 370 [[NSTextField alloc] initWithFrame:NSZeroRect]); |
288 base::string16 label = request->GetMessageTextFragment(); | 371 base::string16 label = request->GetMessageTextFragment(); |
289 [permissionLabel setDrawsBackground:NO]; | 372 [permissionLabel setDrawsBackground:NO]; |
290 [permissionLabel setBezeled:NO]; | 373 [permissionLabel setBezeled:NO]; |
291 [permissionLabel setEditable:NO]; | 374 [permissionLabel setEditable:NO]; |
292 [permissionLabel setSelectable:NO]; | 375 [permissionLabel setSelectable:NO]; |
| 376 [permissionLabel setFont:[NSFont systemFontOfSize:kPermissionFontSize]]; |
293 [permissionLabel setStringValue:base::SysUTF16ToNSString(label)]; | 377 [permissionLabel setStringValue:base::SysUTF16ToNSString(label)]; |
294 [permissionLabel sizeToFit]; | 378 [permissionLabel sizeToFit]; |
295 [permissionLabel setFrameOrigin: | 379 [permissionLabel setFrameOrigin: |
296 NSMakePoint(NSWidth([permissionIcon frame]), 0)]; | 380 NSMakePoint(NSWidth([permissionIcon frame]), 0)]; |
297 [permissionView addSubview:permissionLabel]; | 381 [permissionView addSubview:permissionLabel]; |
298 | 382 |
299 // Match the horizontal centers of the two subviews. Note that the label's | 383 // 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 | 384 // 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 | 385 // way - with the text's center slightly lower than the icon's center - if the |
302 // height delta is not evenly split. | 386 // height delta is not evenly split. |
(...skipping 16 matching lines...) Expand all Loading... |
319 - (NSView*)titleWithHostname:(const std::string&)host { | 403 - (NSView*)titleWithHostname:(const std::string&)host { |
320 base::scoped_nsobject<NSTextField> titleView( | 404 base::scoped_nsobject<NSTextField> titleView( |
321 [[NSTextField alloc] initWithFrame:NSZeroRect]); | 405 [[NSTextField alloc] initWithFrame:NSZeroRect]); |
322 [titleView setDrawsBackground:NO]; | 406 [titleView setDrawsBackground:NO]; |
323 [titleView setBezeled:NO]; | 407 [titleView setBezeled:NO]; |
324 [titleView setEditable:NO]; | 408 [titleView setEditable:NO]; |
325 [titleView setSelectable:NO]; | 409 [titleView setSelectable:NO]; |
326 [titleView setStringValue: | 410 [titleView setStringValue: |
327 l10n_util::GetNSStringF(IDS_PERMISSIONS_BUBBLE_PROMPT, | 411 l10n_util::GetNSStringF(IDS_PERMISSIONS_BUBBLE_PROMPT, |
328 base::UTF8ToUTF16(host))]; | 412 base::UTF8ToUTF16(host))]; |
329 [titleView setFont:[NSFont systemFontOfSize:kFontSize]]; | 413 [titleView setFont:[NSFont systemFontOfSize:kTitleFontSize]]; |
330 [titleView sizeToFit]; | 414 [titleView sizeToFit]; |
331 NSRect titleFrame = [titleView frame]; | 415 NSRect titleFrame = [titleView frame]; |
332 [titleView setFrameSize:NSMakeSize(NSWidth(titleFrame) + kTitlePaddingX, | 416 [titleView setFrameSize:NSMakeSize(NSWidth(titleFrame) + kTitlePaddingX, |
333 NSHeight(titleFrame))]; | 417 NSHeight(titleFrame))]; |
334 return titleView.autorelease(); | 418 return titleView.autorelease(); |
335 } | 419 } |
336 | 420 |
337 - (NSView*)checkboxForRequest:(PermissionBubbleRequest*)request | 421 - (NSView*)menuForRequest:(PermissionBubbleRequest*)request |
338 checked:(BOOL)checked { | 422 atIndex:(int)index |
| 423 allow:(BOOL)allow { |
339 DCHECK(request); | 424 DCHECK(request); |
340 base::scoped_nsobject<NSButton> checkbox( | 425 DCHECK(delegate_); |
341 [[NSButton alloc] initWithFrame:NSZeroRect]); | 426 base::scoped_nsobject<AllowBlockMenuButton> button( |
342 [checkbox setButtonType:NSSwitchButton]; | 427 [[AllowBlockMenuButton alloc] initForURL:request->GetRequestingHostname() |
343 base::string16 permission = request->GetMessageTextFragment(); | 428 allowed:allow |
344 [checkbox setTitle:base::SysUTF16ToNSString(permission)]; | 429 index:index |
345 [checkbox setState:(checked ? NSOnState : NSOffState)]; | 430 delegate:delegate_]); |
346 [checkbox setTarget:self]; | 431 return button.autorelease(); |
347 [checkbox setAction:@selector(onCheckboxChanged:)]; | |
348 [checkbox sizeToFit]; | |
349 [checkbox setFrameOrigin:NSMakePoint(0, kCheckboxYAdjustment)]; | |
350 return checkbox.autorelease(); | |
351 } | 432 } |
352 | 433 |
353 - (NSView*)buttonWithTitle:(NSString*)title | 434 - (NSView*)buttonWithTitle:(NSString*)title |
354 action:(SEL)action { | 435 action:(SEL)action { |
355 base::scoped_nsobject<NSButton> button( | 436 base::scoped_nsobject<NSButton> button( |
356 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]); | 437 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]); |
357 [button setButtonType:NSMomentaryPushInButton]; | 438 [button setButtonType:NSMomentaryPushInButton]; |
358 [button setTitle:title]; | 439 [button setTitle:title]; |
359 [button setTarget:self]; | 440 [button setTarget:self]; |
360 [button setAction:action]; | 441 [button setAction:action]; |
(...skipping 21 matching lines...) Expand all Loading... |
382 - (NSView*)closeButton { | 463 - (NSView*)closeButton { |
383 int dimension = chrome_style::GetCloseButtonSize(); | 464 int dimension = chrome_style::GetCloseButtonSize(); |
384 NSRect frame = NSMakeRect(0, 0, dimension, dimension); | 465 NSRect frame = NSMakeRect(0, 0, dimension, dimension); |
385 base::scoped_nsobject<NSButton> button( | 466 base::scoped_nsobject<NSButton> button( |
386 [[WebUIHoverCloseButton alloc] initWithFrame:frame]); | 467 [[WebUIHoverCloseButton alloc] initWithFrame:frame]); |
387 [button setAction:@selector(onClose:)]; | 468 [button setAction:@selector(onClose:)]; |
388 [button setTarget:self]; | 469 [button setTarget:self]; |
389 return button.autorelease(); | 470 return button.autorelease(); |
390 } | 471 } |
391 | 472 |
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 { | 473 - (void)ok:(id)sender { |
402 DCHECK(delegate_); | 474 DCHECK(delegate_); |
403 delegate_->Closing(); | 475 delegate_->Closing(); |
404 } | 476 } |
405 | 477 |
406 - (void)onAllow:(id)sender { | 478 - (void)onAllow:(id)sender { |
407 DCHECK(delegate_); | 479 DCHECK(delegate_); |
408 delegate_->Accept(); | 480 delegate_->Accept(); |
409 } | 481 } |
410 | 482 |
411 - (void)onBlock:(id)sender { | 483 - (void)onBlock:(id)sender { |
412 DCHECK(delegate_); | 484 DCHECK(delegate_); |
413 delegate_->Deny(); | 485 delegate_->Deny(); |
414 } | 486 } |
415 | 487 |
416 - (void)onClose:(id)sender { | 488 - (void)onClose:(id)sender { |
417 DCHECK(delegate_); | 489 DCHECK(delegate_); |
418 delegate_->Closing(); | 490 delegate_->Closing(); |
419 } | 491 } |
420 | 492 |
421 - (void)onCustomize:(id)sender { | 493 - (void)onCustomize:(id)sender { |
422 DCHECK(delegate_); | 494 DCHECK(delegate_); |
423 delegate_->SetCustomizationMode(); | 495 delegate_->SetCustomizationMode(); |
424 } | 496 } |
425 | 497 |
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 { | 498 - (void)onMenuItemClicked:(int)commandId { |
433 DCHECK(commandId == 0); | 499 DCHECK(commandId == 0); |
434 [self onCustomize:nil]; | 500 [self onCustomize:nil]; |
435 } | 501 } |
436 | 502 |
| 503 + (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB { |
| 504 NSRect frameA = [viewA frame]; |
| 505 NSRect frameB = [viewB frame]; |
| 506 CGFloat width = std::max(NSWidth(frameA), NSWidth(frameB)); |
| 507 [viewA setFrameSize:NSMakeSize(width, NSHeight(frameA))]; |
| 508 [viewB setFrameSize:NSMakeSize(width, NSHeight(frameB))]; |
| 509 return width; |
| 510 } |
| 511 |
| 512 + (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB { |
| 513 NSRect frameA = [viewA frame]; |
| 514 NSRect frameB = [viewB frame]; |
| 515 frameA.origin.y = |
| 516 NSMinY(frameB) + std::floor((NSHeight(frameB) - NSHeight(frameA)) / 2); |
| 517 [viewA setFrameOrigin:frameA.origin]; |
| 518 } |
| 519 |
437 @end // implementation PermissionBubbleController | 520 @end // implementation PermissionBubbleController |
OLD | NEW |