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

Side by Side Diff: chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm

Issue 885373004: Use customization mode by default in permission bubbles (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Test fixes etc. Created 5 years, 10 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 unified diff | Download patch
OLDNEW
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/bind_objc_block.h"
10 #include "base/strings/sys_string_conversions.h" 10 #include "base/strings/sys_string_conversions.h"
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 class MenuDelegate : public ui::SimpleMenuModel::Delegate { 50 class MenuDelegate : public ui::SimpleMenuModel::Delegate {
51 public: 51 public:
52 explicit MenuDelegate(PermissionBubbleController* bubble) 52 explicit MenuDelegate(PermissionBubbleController* bubble)
53 : bubble_controller_(bubble) {} 53 : bubble_controller_(bubble) {}
54 bool IsCommandIdChecked(int command_id) const override { return false; } 54 bool IsCommandIdChecked(int command_id) const override { return false; }
55 bool IsCommandIdEnabled(int command_id) const override { return true; } 55 bool IsCommandIdEnabled(int command_id) const override { return true; }
56 bool GetAcceleratorForCommandId(int command_id, 56 bool GetAcceleratorForCommandId(int command_id,
57 ui::Accelerator* accelerator) override { 57 ui::Accelerator* accelerator) override {
58 return false; 58 return false;
59 } 59 }
60 void ExecuteCommand(int command_id, int event_flags) override {
61 [bubble_controller_ onMenuItemClicked:command_id];
62 }
63 private: 60 private:
64 PermissionBubbleController* bubble_controller_; // Weak, owns us. 61 PermissionBubbleController* bubble_controller_; // Weak, owns us.
65 DISALLOW_COPY_AND_ASSIGN(MenuDelegate); 62 DISALLOW_COPY_AND_ASSIGN(MenuDelegate);
66 }; 63 };
67 64
68 } // namespace 65 } // namespace
69 66
70 // NSPopUpButton with a menu containing two items: allow and block. 67 // NSPopUpButton with a menu containing two items: allow and block.
71 // One AllowBlockMenuButton is used for each requested permission, but only when 68 // One AllowBlockMenuButton is used for each requested permission when there are
72 // the permission bubble is in 'customize' mode. 69 // multiple permissions in the bubble.
73 @interface AllowBlockMenuButton : NSPopUpButton { 70 @interface AllowBlockMenuButton : NSPopUpButton {
74 @private 71 @private
75 scoped_ptr<PermissionMenuModel> menuModel_; 72 scoped_ptr<PermissionMenuModel> menuModel_;
76 base::scoped_nsobject<MenuController> menuController_; 73 base::scoped_nsobject<MenuController> menuController_;
77 } 74 }
78 75
79 - (id)initForURL:(const GURL&)url 76 - (id)initForURL:(const GURL&)url
80 allowed:(BOOL)allow 77 allowed:(BOOL)allow
81 index:(int)index 78 index:(int)index
82 delegate:(PermissionBubbleView::Delegate*)delegate; 79 delegate:(PermissionBubbleView::Delegate*)delegate;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 atIndex:(int)index 173 atIndex:(int)index
177 allow:(BOOL)allow; 174 allow:(BOOL)allow;
178 175
179 // Returns an autoreleased NSView of a button with |title| and |action|. 176 // Returns an autoreleased NSView of a button with |title| and |action|.
180 - (NSView*)buttonWithTitle:(NSString*)title 177 - (NSView*)buttonWithTitle:(NSString*)title
181 action:(SEL)action; 178 action:(SEL)action;
182 179
183 // Returns an autoreleased NSView displaying a block button. 180 // Returns an autoreleased NSView displaying a block button.
184 - (NSView*)blockButton; 181 - (NSView*)blockButton;
185 182
186 // Returns an autoreleased NSView with a block button and a drop-down menu
187 // with one item, which will change the UI to allow customizing the permissions.
188 - (NSView*)blockButtonWithCustomizeMenu;
189
190 // Returns an autoreleased NSView displaying the close 'x' button. 183 // Returns an autoreleased NSView displaying the close 'x' button.
191 - (NSView*)closeButton; 184 - (NSView*)closeButton;
192 185
193 // Called when the 'ok' button is pressed. 186 // Called when the 'ok' button is pressed.
194 - (void)ok:(id)sender; 187 - (void)ok:(id)sender;
195 188
196 // Called when the 'allow' button is pressed. 189 // Called when the 'allow' button is pressed.
197 - (void)onAllow:(id)sender; 190 - (void)onAllow:(id)sender;
198 191
199 // Called when the 'block' button is pressed. 192 // Called when the 'block' button is pressed.
200 - (void)onBlock:(id)sender; 193 - (void)onBlock:(id)sender;
201 194
202 // Called when the 'close' button is pressed. 195 // Called when the 'close' button is pressed.
203 - (void)onClose:(id)sender; 196 - (void)onClose:(id)sender;
204 197
205 // Called when the 'customize' button is pressed.
206 - (void)onCustomize:(id)sender;
207
208 // Sets the width of both |viewA| and |viewB| to be the larger of the 198 // Sets the width of both |viewA| and |viewB| to be the larger of the
209 // two views' widths. Does not change either view's origin or height. 199 // two views' widths. Does not change either view's origin or height.
210 + (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB; 200 + (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB;
211 201
212 // Sets the offset of |viewA| so that its vertical center is aligned with the 202 // Sets the offset of |viewA| so that its vertical center is aligned with the
213 // vertical center of |viewB|. 203 // vertical center of |viewB|.
214 + (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB; 204 + (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB;
215 205
216 @end 206 @end
217 207
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 } 250 }
261 251
262 - (void)parentWindowDidMove:(NSNotification*)notification { 252 - (void)parentWindowDidMove:(NSNotification*)notification {
263 DCHECK(bridge_); 253 DCHECK(bridge_);
264 [self setAnchorPoint:bridge_->GetAnchorPoint()]; 254 [self setAnchorPoint:bridge_->GetAnchorPoint()];
265 } 255 }
266 256
267 - (void)showAtAnchor:(NSPoint)anchorPoint 257 - (void)showAtAnchor:(NSPoint)anchorPoint
268 withDelegate:(PermissionBubbleView::Delegate*)delegate 258 withDelegate:(PermissionBubbleView::Delegate*)delegate
269 forRequests:(const std::vector<PermissionBubbleRequest*>&)requests 259 forRequests:(const std::vector<PermissionBubbleRequest*>&)requests
270 acceptStates:(const std::vector<bool>&)acceptStates 260 acceptStates:(const std::vector<bool>&)acceptStates {
271 customizationMode:(BOOL)customizationMode {
272 DCHECK(!requests.empty()); 261 DCHECK(!requests.empty());
273 DCHECK(delegate); 262 DCHECK(delegate);
274 DCHECK(!customizationMode || (requests.size() == acceptStates.size()));
275 delegate_ = delegate; 263 delegate_ = delegate;
276 264
277 NSView* contentView = [[self window] contentView]; 265 NSView* contentView = [[self window] contentView];
278 [contentView setSubviews:@[]]; 266 [contentView setSubviews:@[]];
279 267
268 BOOL singlePermission = requests.size() == 1;
269
280 // Create one button to use as a guide for the permissions' y-offsets. 270 // Create one button to use as a guide for the permissions' y-offsets.
281 base::scoped_nsobject<NSView> allowOrOkButton; 271 base::scoped_nsobject<NSView> allowOrOkButton;
282 if (customizationMode) { 272 if (singlePermission) {
273 NSString* allowTitle = l10n_util::GetNSString(IDS_PERMISSION_ALLOW);
274 allowOrOkButton.reset([[self buttonWithTitle:allowTitle
275 action:@selector(onAllow:)] retain]);
276 } else {
283 NSString* okTitle = l10n_util::GetNSString(IDS_OK); 277 NSString* okTitle = l10n_util::GetNSString(IDS_OK);
284 allowOrOkButton.reset([[self buttonWithTitle:okTitle 278 allowOrOkButton.reset([[self buttonWithTitle:okTitle
285 action:@selector(ok:)] retain]); 279 action:@selector(ok:)] retain]);
286 } else {
287 NSString* allowTitle = l10n_util::GetNSString(IDS_PERMISSION_ALLOW);
288 allowOrOkButton.reset([[self buttonWithTitle:allowTitle
289 action:@selector(onAllow:)] retain]);
290 } 280 }
291 CGFloat yOffset = 2 * kVerticalPadding + NSMaxY([allowOrOkButton frame]); 281 CGFloat yOffset = 2 * kVerticalPadding + NSMaxY([allowOrOkButton frame]);
292 BOOL singlePermission = requests.size() == 1;
293 282
294 base::scoped_nsobject<NSMutableArray> permissionMenus; 283 base::scoped_nsobject<NSMutableArray> permissionMenus;
295 if (customizationMode) 284 if (!singlePermission)
296 permissionMenus.reset([[NSMutableArray alloc] init]); 285 permissionMenus.reset([[NSMutableArray alloc] init]);
297 286
298 CGFloat maxPermissionLineWidth = 0; 287 CGFloat maxPermissionLineWidth = 0;
299 for (auto it = requests.begin(); it != requests.end(); it++) { 288 for (auto it = requests.begin(); it != requests.end(); it++) {
300 base::scoped_nsobject<NSView> permissionView( 289 base::scoped_nsobject<NSView> permissionView(
301 [[self labelForRequest:(*it)] retain]); 290 [[self labelForRequest:(*it)] retain]);
302 NSPoint origin = [permissionView frame].origin; 291 NSPoint origin = [permissionView frame].origin;
303 origin.x += kHorizontalPadding; 292 origin.x += kHorizontalPadding;
304 origin.y += yOffset; 293 origin.y += yOffset;
305 [permissionView setFrameOrigin:origin]; 294 [permissionView setFrameOrigin:origin];
306 [contentView addSubview:permissionView]; 295 [contentView addSubview:permissionView];
307 296
308 if (customizationMode) { 297 if (!singlePermission) {
309 int index = it - requests.begin(); 298 int index = it - requests.begin();
310 base::scoped_nsobject<NSView> menu( 299 base::scoped_nsobject<NSView> menu(
311 [[self menuForRequest:(*it) 300 [[self menuForRequest:(*it)
312 atIndex:index 301 atIndex:index
313 allow:acceptStates[index] ? YES : NO] retain]); 302 allow:acceptStates[index] ? YES : NO] retain]);
314 // Align vertically. Horizontal alignment will be adjusted once the 303 // Align vertically. Horizontal alignment will be adjusted once the
315 // widest permission is know. 304 // widest permission is know.
316 [PermissionBubbleController alignCenterOf:menu 305 [PermissionBubbleController alignCenterOf:menu
317 verticallyToCenterOf:permissionView]; 306 verticallyToCenterOf:permissionView];
318 [permissionMenus addObject:menu]; 307 [permissionMenus addObject:menu];
(...skipping 16 matching lines...) Expand all
335 324
336 // Determine the dimensions of the bubble. 325 // Determine the dimensions of the bubble.
337 // Once the height and width are set, the buttons and permission menus can 326 // Once the height and width are set, the buttons and permission menus can
338 // be laid out correctly. 327 // be laid out correctly.
339 NSRect bubbleFrame = NSMakeRect(0, 0, kBubbleMinWidth, 0); 328 NSRect bubbleFrame = NSMakeRect(0, 0, kBubbleMinWidth, 0);
340 329
341 // Fix the height of the bubble relative to the title. 330 // Fix the height of the bubble relative to the title.
342 bubbleFrame.size.height = NSMaxY([titleView frame]) + kVerticalPadding + 331 bubbleFrame.size.height = NSMaxY([titleView frame]) + kVerticalPadding +
343 info_bubble::kBubbleArrowHeight; 332 info_bubble::kBubbleArrowHeight;
344 333
345 if (customizationMode) { 334 if (!singlePermission) {
346 // Add the maximum menu width to the bubble width. 335 // Add the maximum menu width to the bubble width.
347 CGFloat maxMenuWidth = 0; 336 CGFloat maxMenuWidth = 0;
348 for (AllowBlockMenuButton* button in permissionMenus.get()) { 337 for (AllowBlockMenuButton* button in permissionMenus.get()) {
349 maxMenuWidth = std::max(maxMenuWidth, [button maximumTitleWidth]); 338 maxMenuWidth = std::max(maxMenuWidth, [button maximumTitleWidth]);
350 } 339 }
351 maxPermissionLineWidth += maxMenuWidth; 340 maxPermissionLineWidth += maxMenuWidth;
352 } 341 }
353 342
354 // The title and 'x' button row must fit within the bubble. 343 // The title and 'x' button row must fit within the bubble.
355 CGFloat titleRowWidth = NSMaxX([titleView frame]) + 344 CGFloat titleRowWidth = NSMaxX([titleView frame]) +
(...skipping 17 matching lines...) Expand all
373 362
374 [closeButton setFrameOrigin:closeButtonOrigin]; 363 [closeButton setFrameOrigin:closeButtonOrigin];
375 [contentView addSubview:closeButton]; 364 [contentView addSubview:closeButton];
376 365
377 // Position the allow/ok button. 366 // Position the allow/ok button.
378 CGFloat xOrigin = NSWidth(bubbleFrame) - NSWidth([allowOrOkButton frame]) - 367 CGFloat xOrigin = NSWidth(bubbleFrame) - NSWidth([allowOrOkButton frame]) -
379 kButtonRightEdgePadding; 368 kButtonRightEdgePadding;
380 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; 369 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)];
381 [contentView addSubview:allowOrOkButton]; 370 [contentView addSubview:allowOrOkButton];
382 371
383 if (customizationMode) { 372 if (singlePermission) {
384 // Adjust the horizontal origin for each menu so that its right edge
385 // lines up with the right edge of the ok button.
386 CGFloat rightEdge = NSMaxX([allowOrOkButton frame]);
387 for (NSView* view in permissionMenus.get()) {
388 [view setFrameOrigin:NSMakePoint(rightEdge - NSWidth([view frame]),
389 NSMinY([view frame]))];
390 }
391 } else {
392 base::scoped_nsobject<NSView> blockButton; 373 base::scoped_nsobject<NSView> blockButton;
393 if (singlePermission) 374 blockButton.reset([[self blockButton] retain]);
394 blockButton.reset([[self blockButton] retain]);
395 else
396 blockButton.reset([[self blockButtonWithCustomizeMenu] retain]);
397 CGFloat width = [PermissionBubbleController matchWidthsOf:blockButton 375 CGFloat width = [PermissionBubbleController matchWidthsOf:blockButton
398 andOf:allowOrOkButton]; 376 andOf:allowOrOkButton];
399 // Ensure the allow/ok button is still in the correct position. 377 // Ensure the allow/ok button is still in the correct position.
400 xOrigin = NSWidth(bubbleFrame) - width - kHorizontalPadding; 378 xOrigin = NSWidth(bubbleFrame) - width - kHorizontalPadding;
401 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; 379 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)];
402 // Line up the block button. 380 // Line up the block button.
403 xOrigin = NSMinX([allowOrOkButton frame]) - width - kBetweenButtonsPadding; 381 xOrigin = NSMinX([allowOrOkButton frame]) - width - kBetweenButtonsPadding;
404 [blockButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)]; 382 [blockButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)];
405 [contentView addSubview:blockButton]; 383 [contentView addSubview:blockButton];
384 } else {
385 // Adjust the horizontal origin for each menu so that its right edge
386 // lines up with the right edge of the ok button.
387 CGFloat rightEdge = NSMaxX([allowOrOkButton frame]);
388 for (NSView* view in permissionMenus.get()) {
389 [view setFrameOrigin:NSMakePoint(rightEdge - NSWidth([view frame]),
390 NSMinY([view frame]))];
391 }
406 } 392 }
407 393
408 bubbleFrame = [[self window] frameRectForContentRect:bubbleFrame]; 394 bubbleFrame = [[self window] frameRectForContentRect:bubbleFrame];
409 if ([[self window] isVisible]) { 395 if ([[self window] isVisible]) {
410 // Unfortunately, calling -setFrame followed by -setFrameOrigin (called 396 // Unfortunately, calling -setFrame followed by -setFrameOrigin (called
411 // within -setAnchorPoint) causes flickering. Avoid the flickering by 397 // within -setAnchorPoint) causes flickering. Avoid the flickering by
412 // manually adjusting the new frame's origin so that the top left stays the 398 // manually adjusting the new frame's origin so that the top left stays the
413 // same, and only calling -setFrame. 399 // same, and only calling -setFrame.
414 NSRect currentWindowFrame = [[self window] frame]; 400 NSRect currentWindowFrame = [[self window] frame];
415 bubbleFrame.origin = currentWindowFrame.origin; 401 bubbleFrame.origin = currentWindowFrame.origin;
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 [button sizeToFit]; 497 [button sizeToFit];
512 return button.autorelease(); 498 return button.autorelease();
513 } 499 }
514 500
515 - (NSView*)blockButton { 501 - (NSView*)blockButton {
516 NSString* blockTitle = l10n_util::GetNSString(IDS_PERMISSION_DENY); 502 NSString* blockTitle = l10n_util::GetNSString(IDS_PERMISSION_DENY);
517 return [self buttonWithTitle:blockTitle 503 return [self buttonWithTitle:blockTitle
518 action:@selector(onBlock:)]; 504 action:@selector(onBlock:)];
519 } 505 }
520 506
521 - (NSView*)blockButtonWithCustomizeMenu {
522 menuDelegate_.reset(new MenuDelegate(self));
523 base::scoped_nsobject<SplitBlockButton> blockButton([[SplitBlockButton alloc]
524 initWithMenuDelegate:menuDelegate_.get()]);
525 [blockButton sizeToFit];
526 [blockButton setEnabled:YES];
527 [blockButton setAction:@selector(onBlock:)];
528 [blockButton setTarget:self];
529 return blockButton.autorelease();
530 }
531
532 - (NSView*)closeButton { 507 - (NSView*)closeButton {
533 int dimension = chrome_style::GetCloseButtonSize(); 508 int dimension = chrome_style::GetCloseButtonSize();
534 NSRect frame = NSMakeRect(0, 0, dimension, dimension); 509 NSRect frame = NSMakeRect(0, 0, dimension, dimension);
535 base::scoped_nsobject<NSButton> button( 510 base::scoped_nsobject<NSButton> button(
536 [[WebUIHoverCloseButton alloc] initWithFrame:frame]); 511 [[WebUIHoverCloseButton alloc] initWithFrame:frame]);
537 [button setAction:@selector(onClose:)]; 512 [button setAction:@selector(onClose:)];
538 [button setTarget:self]; 513 [button setTarget:self];
539 return button.autorelease(); 514 return button.autorelease();
540 } 515 }
541 516
(...skipping 10 matching lines...) Expand all
552 - (void)onBlock:(id)sender { 527 - (void)onBlock:(id)sender {
553 DCHECK(delegate_); 528 DCHECK(delegate_);
554 delegate_->Deny(); 529 delegate_->Deny();
555 } 530 }
556 531
557 - (void)onClose:(id)sender { 532 - (void)onClose:(id)sender {
558 DCHECK(delegate_); 533 DCHECK(delegate_);
559 delegate_->Closing(); 534 delegate_->Closing();
560 } 535 }
561 536
562 - (void)onCustomize:(id)sender {
563 DCHECK(delegate_);
564 delegate_->SetCustomizationMode();
565 }
566
567 - (void)onMenuItemClicked:(int)commandId {
568 DCHECK(commandId == 0);
569 [self onCustomize:nil];
570 }
571
572 - (void)activateTabWithContents:(content::WebContents*)newContents 537 - (void)activateTabWithContents:(content::WebContents*)newContents
573 previousContents:(content::WebContents*)oldContents 538 previousContents:(content::WebContents*)oldContents
574 atIndex:(NSInteger)index 539 atIndex:(NSInteger)index
575 reason:(int)reason { 540 reason:(int)reason {
576 // The show/hide of this bubble is handled by the PermissionBubbleManager. 541 // The show/hide of this bubble is handled by the PermissionBubbleManager.
577 // So bypass the base class, which would close the bubble here. 542 // So bypass the base class, which would close the bubble here.
578 } 543 }
579 544
580 + (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB { 545 + (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB {
581 NSRect frameA = [viewA frame]; 546 NSRect frameA = [viewA frame];
582 NSRect frameB = [viewB frame]; 547 NSRect frameB = [viewB frame];
583 CGFloat width = std::max(NSWidth(frameA), NSWidth(frameB)); 548 CGFloat width = std::max(NSWidth(frameA), NSWidth(frameB));
584 [viewA setFrameSize:NSMakeSize(width, NSHeight(frameA))]; 549 [viewA setFrameSize:NSMakeSize(width, NSHeight(frameA))];
585 [viewB setFrameSize:NSMakeSize(width, NSHeight(frameB))]; 550 [viewB setFrameSize:NSMakeSize(width, NSHeight(frameB))];
586 return width; 551 return width;
587 } 552 }
588 553
589 + (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB { 554 + (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB {
590 NSRect frameA = [viewA frame]; 555 NSRect frameA = [viewA frame];
591 NSRect frameB = [viewB frame]; 556 NSRect frameB = [viewB frame];
592 frameA.origin.y = 557 frameA.origin.y =
593 NSMinY(frameB) + std::floor((NSHeight(frameB) - NSHeight(frameA)) / 2); 558 NSMinY(frameB) + std::floor((NSHeight(frameB) - NSHeight(frameA)) / 2);
594 [viewA setFrameOrigin:frameA.origin]; 559 [viewA setFrameOrigin:frameA.origin];
595 } 560 }
596 561
597 @end // implementation PermissionBubbleController 562 @end // implementation PermissionBubbleController
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698