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

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

Issue 2748443005: Rename website_settings UI folders to permission_bubble. (Closed)
Patch Set: Rebase. Created 3 years, 9 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #import "chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.h "
6
7 #include <algorithm>
8
9 #include "base/mac/bind_objc_block.h"
10 #include "base/macros.h"
11 #include "base/strings/sys_string_conversions.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/permissions/permission_request.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_finder.h"
16 #include "chrome/browser/ui/browser_window.h"
17 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
18 #import "chrome/browser/ui/cocoa/browser_window_utils.h"
19 #import "chrome/browser/ui/cocoa/chrome_style.h"
20 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h"
21 #import "chrome/browser/ui/cocoa/hover_close_button.h"
22 #import "chrome/browser/ui/cocoa/info_bubble_view.h"
23 #import "chrome/browser/ui/cocoa/info_bubble_window.h"
24 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
25 #include "chrome/browser/ui/cocoa/page_info/permission_selector_button.h"
26 #include "chrome/browser/ui/cocoa/page_info/split_block_button.h"
27 #include "chrome/browser/ui/cocoa/page_info/website_settings_utils_cocoa.h"
28 #include "chrome/browser/ui/cocoa/website_settings/permission_bubble_cocoa.h"
29 #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h"
30 #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h"
31 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
32 #include "chrome/browser/ui/page_info/permission_menu_model.h"
33 #include "chrome/browser/ui/website_settings/permission_prompt.h"
34 #include "chrome/common/pref_names.h"
35 #include "chrome/grit/generated_resources.h"
36 #include "components/prefs/pref_service.h"
37 #include "components/strings/grit/components_strings.h"
38 #include "components/url_formatter/elide_url.h"
39 #include "content/public/browser/native_web_keyboard_event.h"
40 #include "content/public/browser/user_metrics.h"
41 #include "skia/ext/skia_utils_mac.h"
42 #include "ui/base/cocoa/cocoa_base_utils.h"
43 #import "ui/base/cocoa/controls/hyperlink_text_view.h"
44 #import "ui/base/cocoa/menu_controller.h"
45 #include "ui/base/cocoa/window_size_constants.h"
46 #include "ui/base/l10n/l10n_util_mac.h"
47 #include "ui/base/models/simple_menu_model.h"
48 #include "ui/gfx/color_palette.h"
49 #include "ui/gfx/image/image_skia_util_mac.h"
50 #include "ui/gfx/paint_vector_icon.h"
51 #include "url/gurl.h"
52
53 using base::UserMetricsAction;
54
55 namespace {
56
57 // Distance between permission icon and permission label.
58 const CGFloat kHorizontalIconPadding = 8.0f;
59
60 // Distance between two permission labels.
61 const CGFloat kVerticalPermissionPadding = 2.0f;
62
63 const CGFloat kHorizontalPadding = 13.0f;
64 const CGFloat kVerticalPadding = 15.0f;
65 const CGFloat kBetweenButtonsPadding = 10.0f;
66 const CGFloat kButtonRightEdgePadding = 17.0f;
67 const CGFloat kTitlePaddingX = 50.0f;
68 const CGFloat kBubbleMinWidth = 315.0f;
69 const NSSize kPermissionIconSize = {18, 18};
70
71 const NSInteger kFullscreenLeftOffset = 40;
72
73 } // namespace
74
75 // NSPopUpButton with a menu containing two items: allow and block.
76 // One AllowBlockMenuButton is used for each requested permission when there are
77 // multiple permissions in the bubble.
78 @interface AllowBlockMenuButton : NSPopUpButton {
79 @private
80 std::unique_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:(PermissionPrompt::Delegate*)delegate
88 profile:(Profile*)profile;
89
90 // Returns the maximum width of its possible titles.
91 - (CGFloat)maximumTitleWidth;
92 @end
93
94 @implementation AllowBlockMenuButton
95
96 - (id)initForURL:(const GURL&)url
97 allowed:(BOOL)allow
98 index:(int)index
99 delegate:(PermissionPrompt::Delegate*)delegate
100 profile:(Profile*)profile {
101 if (self = [super initWithFrame:NSZeroRect pullsDown:NO]) {
102 ContentSetting setting =
103 allow ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
104 [self setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
105 [self setBordered:NO];
106
107 __block PermissionPrompt::Delegate* blockDelegate = delegate;
108 __block AllowBlockMenuButton* blockSelf = self;
109 PermissionMenuModel::ChangeCallback changeCallback =
110 base::BindBlock(^(const WebsiteSettingsUI::PermissionInfo& permission) {
111 blockDelegate->ToggleAccept(
112 index, permission.setting == CONTENT_SETTING_ALLOW);
113 [blockSelf setFrameSize:
114 SizeForWebsiteSettingsButtonTitle(blockSelf,
115 [blockSelf title])];
116 });
117
118 menuModel_.reset(
119 new PermissionMenuModel(profile, url, setting, changeCallback));
120 menuController_.reset([[MenuController alloc] initWithModel:menuModel_.get()
121 useWithPopUpButtonCell:NO]);
122 [self setMenu:[menuController_ menu]];
123 [self selectItemAtIndex:menuModel_->GetIndexOfCommandId(setting)];
124 // Although the frame is reset, below, this sizes the cell properly.
125 [self sizeToFit];
126 // Adjust the size to fit the current title. Using only -sizeToFit leaves
127 // an ugly amount of whitespace between the title and the arrows because it
128 // will fit to the largest element in the menu, not just the selected item.
129 [self setFrameSize:SizeForWebsiteSettingsButtonTitle(self, [self title])];
130 }
131 return self;
132 }
133
134 - (CGFloat)maximumTitleWidth {
135 CGFloat maxTitleWidth = 0;
136 for (NSMenuItem* item in [self itemArray]) {
137 NSSize size = SizeForWebsiteSettingsButtonTitle(self, [item title]);
138 maxTitleWidth = std::max(maxTitleWidth, size.width);
139 }
140 return maxTitleWidth;
141 }
142
143 @end
144
145 @interface PermissionBubbleController ()
146
147 // Determines if the bubble has an anchor in a corner or no anchor at all.
148 - (info_bubble::BubbleArrowLocation)getExpectedArrowLocation;
149
150 // Returns the expected parent for this bubble.
151 - (NSWindow*)getExpectedParentWindow;
152
153 // Returns an autoreleased NSView displaying the icon and label for |request|.
154 - (NSView*)labelForRequest:(PermissionRequest*)request;
155
156 // Returns an autoreleased NSView displaying the title for the bubble
157 // requesting settings for |host|.
158 - (NSView*)titleWithOrigin:(const GURL&)origin;
159
160 // Returns an autoreleased NSView displaying a menu for |request|. The
161 // menu will be initialized as 'allow' if |allow| is YES.
162 - (NSView*)menuForRequest:(PermissionRequest*)request
163 atIndex:(int)index
164 allow:(BOOL)allow;
165
166 // Returns an autoreleased NSView of a button with |title| and |action|.
167 - (NSView*)buttonWithTitle:(NSString*)title
168 action:(SEL)action;
169
170 // Returns an autoreleased NSView displaying a block button.
171 - (NSView*)blockButton;
172
173 // Returns an autoreleased NSView displaying the close 'x' button.
174 - (NSView*)closeButton;
175
176 // Called when the 'ok' button is pressed.
177 - (void)ok:(id)sender;
178
179 // Called when the 'allow' button is pressed.
180 - (void)onAllow:(id)sender;
181
182 // Called when the 'block' button is pressed.
183 - (void)onBlock:(id)sender;
184
185 // Called when the 'close' button is pressed.
186 - (void)onClose:(id)sender;
187
188 // Returns the constant offset from the left to use for fullscreen permission
189 // bubbles. Only used in tests.
190 + (NSInteger)getFullscreenLeftOffset;
191
192 // Sets the width of both |viewA| and |viewB| to be the larger of the
193 // two views' widths. Does not change either view's origin or height.
194 + (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB;
195
196 // Sets the offset of |viewA| so that its vertical center is aligned with the
197 // vertical center of |viewB|.
198 + (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB;
199
200 // BaseBubbleController override.
201 - (IBAction)cancel:(id)sender;
202
203 @end
204
205 @implementation PermissionBubbleController
206
207 - (id)initWithBrowser:(Browser*)browser bridge:(PermissionBubbleCocoa*)bridge {
208 DCHECK(browser);
209 DCHECK(bridge);
210 browser_ = browser;
211 base::scoped_nsobject<InfoBubbleWindow> window([[InfoBubbleWindow alloc]
212 initWithContentRect:ui::kWindowSizeDeterminedLater
213 styleMask:NSBorderlessWindowMask
214 backing:NSBackingStoreBuffered
215 defer:NO]);
216
217 [window setAllowedAnimations:info_bubble::kAnimateNone];
218 [window setReleasedWhenClosed:NO];
219 if ((self = [super initWithWindow:window
220 parentWindow:[self getExpectedParentWindow]
221 anchoredAt:NSZeroPoint])) {
222 [self setShouldCloseOnResignKey:NO];
223 [self setShouldOpenAsKeyWindow:YES];
224 [[self bubble] setArrowLocation:[self getExpectedArrowLocation]];
225 bridge_ = bridge;
226 NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
227 [center addObserver:self
228 selector:@selector(parentWindowDidMove:)
229 name:NSWindowDidMoveNotification
230 object:[self getExpectedParentWindow]];
231 }
232 return self;
233 }
234
235 - (LocationBarDecoration*)decorationForBubble {
236 if (![self hasVisibleLocationBar])
237 return nullptr;
238
239 LocationBarViewMac* location_bar =
240 [[self.parentWindow windowController] locationBarBridge];
241 return location_bar->GetPageInfoDecoration();
242 }
243
244 + (NSPoint)getAnchorPointForBrowser:(Browser*)browser {
245 NSPoint anchor;
246 NSWindow* parentWindow = browser->window()->GetNativeWindow();
247 if ([PermissionBubbleController hasVisibleLocationBarForBrowser:browser]) {
248 LocationBarViewMac* location_bar =
249 [[parentWindow windowController] locationBarBridge];
250 anchor = location_bar->GetPageInfoBubblePoint();
251 } else {
252 // Position the bubble on the left of the screen if there is no page info
253 // button to point at.
254 NSRect contentFrame = [[parentWindow contentView] frame];
255 anchor = NSMakePoint(NSMinX(contentFrame) + kFullscreenLeftOffset,
256 NSMaxY(contentFrame));
257 }
258
259 return ui::ConvertPointFromWindowToScreen(parentWindow, anchor);
260 }
261
262 + (bool)hasVisibleLocationBarForBrowser:(Browser*)browser {
263 if (!browser->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR))
264 return false;
265
266 if (!browser->exclusive_access_manager()->context()->IsFullscreen())
267 return true;
268
269 // If the browser is in browser-initiated full screen, a preference can cause
270 // the toolbar to be hidden.
271 if (browser->exclusive_access_manager()
272 ->fullscreen_controller()
273 ->IsFullscreenForBrowser()) {
274 PrefService* prefs = browser->profile()->GetPrefs();
275 bool show_toolbar = prefs->GetBoolean(prefs::kShowFullscreenToolbar);
276 return show_toolbar;
277 }
278
279 // Otherwise this is fullscreen without a toolbar, so there is no visible
280 // location bar.
281 return false;
282 }
283
284 - (void)windowWillClose:(NSNotification*)notification {
285 [[NSNotificationCenter defaultCenter]
286 removeObserver:self
287 name:NSWindowDidMoveNotification
288 object:nil];
289 bridge_->OnBubbleClosing();
290 [super windowWillClose:notification];
291 }
292
293 - (void)parentWindowWillToggleFullScreen:(NSNotification*)notification {
294 // Override the base class implementation, which would have closed the bubble.
295 }
296
297 - (void)parentWindowDidResize:(NSNotification*)notification {
298 // Override the base class implementation, which sets the anchor point. But
299 // it's not necessary since BrowserWindowController will notify the
300 // PermissionRequestManager to update the anchor position on a resize.
301 }
302
303 - (void)parentWindowDidMove:(NSNotification*)notification {
304 DCHECK(bridge_);
305 [self setAnchorPoint:[self getExpectedAnchorPoint]];
306 }
307
308 - (void)showWithDelegate:(PermissionPrompt::Delegate*)delegate
309 forRequests:(const std::vector<PermissionRequest*>&)requests
310 acceptStates:(const std::vector<bool>&)acceptStates {
311 DCHECK(!requests.empty());
312 DCHECK(delegate);
313 delegate_ = delegate;
314
315 NSView* contentView = [[self window] contentView];
316 [contentView setSubviews:@[]];
317
318 BOOL singlePermission = requests.size() == 1;
319
320 // Create one button to use as a guide for the permissions' y-offsets.
321 base::scoped_nsobject<NSView> allowOrOkButton;
322 if (singlePermission) {
323 NSString* allowTitle = l10n_util::GetNSString(IDS_PERMISSION_ALLOW);
324 allowOrOkButton.reset([[self buttonWithTitle:allowTitle
325 action:@selector(onAllow:)] retain]);
326 } else {
327 NSString* okTitle = l10n_util::GetNSString(IDS_OK);
328 allowOrOkButton.reset([[self buttonWithTitle:okTitle
329 action:@selector(ok:)] retain]);
330 }
331 CGFloat yOffset = 2 * kVerticalPadding + NSMaxY([allowOrOkButton frame]);
332
333 base::scoped_nsobject<NSMutableArray> permissionMenus;
334 if (!singlePermission)
335 permissionMenus.reset([[NSMutableArray alloc] init]);
336
337 CGFloat maxPermissionLineWidth = 0;
338 CGFloat verticalPadding = 0.0f;
339 for (auto it = requests.begin(); it != requests.end(); it++) {
340 base::scoped_nsobject<NSView> permissionView(
341 [[self labelForRequest:(*it)] retain]);
342 NSPoint origin = [permissionView frame].origin;
343 origin.x += kHorizontalPadding;
344 origin.y += yOffset + verticalPadding;
345 [permissionView setFrameOrigin:origin];
346 [contentView addSubview:permissionView];
347
348 if (!singlePermission) {
349 int index = it - requests.begin();
350 base::scoped_nsobject<NSView> menu(
351 [[self menuForRequest:(*it)
352 atIndex:index
353 allow:acceptStates[index] ? YES : NO] retain]);
354 // Align vertically. Horizontal alignment will be adjusted once the
355 // widest permission is know.
356 [PermissionBubbleController alignCenterOf:menu
357 verticallyToCenterOf:permissionView];
358 [permissionMenus addObject:menu];
359 [contentView addSubview:menu];
360 }
361 maxPermissionLineWidth = std::max(
362 maxPermissionLineWidth, NSMaxX([permissionView frame]));
363 yOffset += NSHeight([permissionView frame]);
364
365 // Add extra padding for all but first permission.
366 verticalPadding = kVerticalPermissionPadding;
367 }
368
369 base::scoped_nsobject<NSView> titleView(
370 [[self titleWithOrigin:requests[0]->GetOrigin()] retain]);
371 [contentView addSubview:titleView];
372 [titleView setFrameOrigin:NSMakePoint(kHorizontalPadding,
373 kVerticalPadding + yOffset)];
374
375 // 'x' button in the upper-right-hand corner.
376 base::scoped_nsobject<NSView> closeButton([[self closeButton] retain]);
377
378 // Determine the dimensions of the bubble.
379 // Once the height and width are set, the buttons and permission menus can
380 // be laid out correctly.
381 NSRect bubbleFrame = NSMakeRect(0, 0, kBubbleMinWidth, 0);
382
383 // Fix the height of the bubble relative to the title.
384 bubbleFrame.size.height = NSMaxY([titleView frame]) + kVerticalPadding +
385 info_bubble::kBubbleArrowHeight;
386
387 if (!singlePermission) {
388 // Add the maximum menu width to the bubble width.
389 CGFloat maxMenuWidth = 0;
390 for (AllowBlockMenuButton* button in permissionMenus.get()) {
391 maxMenuWidth = std::max(maxMenuWidth, [button maximumTitleWidth]);
392 }
393 maxPermissionLineWidth += maxMenuWidth;
394 }
395
396 // The title and 'x' button row must fit within the bubble.
397 CGFloat titleRowWidth = NSMaxX([titleView frame]) +
398 NSWidth([closeButton frame]) +
399 chrome_style::kCloseButtonPadding;
400
401 bubbleFrame.size.width = std::max(
402 NSWidth(bubbleFrame), std::max(titleRowWidth, maxPermissionLineWidth));
403
404 // Now that the bubble's dimensions have been set, lay out the buttons and
405 // menus.
406
407 // Place the close button at the upper-right-hand corner of the bubble.
408 NSPoint closeButtonOrigin =
409 NSMakePoint(NSWidth(bubbleFrame) - NSWidth([closeButton frame]) -
410 chrome_style::kCloseButtonPadding,
411 NSHeight(bubbleFrame) - NSWidth([closeButton frame]) -
412 chrome_style::kCloseButtonPadding);
413 // Account for the bubble's arrow.
414 closeButtonOrigin.y -= info_bubble::kBubbleArrowHeight;
415
416 [closeButton setFrameOrigin:closeButtonOrigin];
417 [contentView addSubview:closeButton];
418
419 // Position the allow/ok button.
420 CGFloat xOrigin = NSWidth(bubbleFrame) - NSWidth([allowOrOkButton frame]) -
421 kButtonRightEdgePadding;
422 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)];
423 [contentView addSubview:allowOrOkButton];
424
425 if (singlePermission) {
426 base::scoped_nsobject<NSView> blockButton;
427 blockButton.reset([[self blockButton] retain]);
428 CGFloat width = [PermissionBubbleController matchWidthsOf:blockButton
429 andOf:allowOrOkButton];
430 // Ensure the allow/ok button is still in the correct position.
431 xOrigin = NSWidth(bubbleFrame) - width - kHorizontalPadding;
432 [allowOrOkButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)];
433 // Line up the block button.
434 xOrigin = NSMinX([allowOrOkButton frame]) - width - kBetweenButtonsPadding;
435 [blockButton setFrameOrigin:NSMakePoint(xOrigin, kVerticalPadding)];
436 [contentView addSubview:blockButton];
437 } else {
438 // Adjust the horizontal origin for each menu so that its right edge
439 // lines up with the right edge of the ok button.
440 CGFloat rightEdge = NSMaxX([allowOrOkButton frame]);
441 for (NSView* view in permissionMenus.get()) {
442 [view setFrameOrigin:NSMakePoint(rightEdge - NSWidth([view frame]),
443 NSMinY([view frame]))];
444 }
445 }
446
447 bubbleFrame = [[self window] frameRectForContentRect:bubbleFrame];
448 if ([[self window] isVisible]) {
449 // Unfortunately, calling -setFrame followed by -setFrameOrigin (called
450 // within -setAnchorPoint) causes flickering. Avoid the flickering by
451 // manually adjusting the new frame's origin so that the top left stays the
452 // same, and only calling -setFrame.
453 NSRect currentWindowFrame = [[self window] frame];
454 bubbleFrame.origin = currentWindowFrame.origin;
455 bubbleFrame.origin.y = bubbleFrame.origin.y +
456 currentWindowFrame.size.height - bubbleFrame.size.height;
457 [[self window] setFrame:bubbleFrame display:YES];
458 } else {
459 [[self window] setFrame:bubbleFrame display:NO];
460 [self setAnchorPoint:[self getExpectedAnchorPoint]];
461 [self showWindow:nil];
462 [[self window] makeFirstResponder:nil];
463 [[self window] setInitialFirstResponder:allowOrOkButton.get()];
464 }
465 }
466
467 - (void)updateAnchorPosition {
468 [self setParentWindow:[self getExpectedParentWindow]];
469 [self setAnchorPoint:[self getExpectedAnchorPoint]];
470 [[self bubble] setArrowLocation:[self getExpectedArrowLocation]];
471 }
472
473 - (NSPoint)getExpectedAnchorPoint {
474 return [PermissionBubbleController getAnchorPointForBrowser:browser_];
475 }
476
477 - (bool)hasVisibleLocationBar {
478 return [PermissionBubbleController hasVisibleLocationBarForBrowser:browser_];
479 }
480
481 - (info_bubble::BubbleArrowLocation)getExpectedArrowLocation {
482 return info_bubble::kTopLeading;
483 }
484
485 - (NSWindow*)getExpectedParentWindow {
486 DCHECK(browser_->window());
487 return browser_->window()->GetNativeWindow();
488 }
489
490 - (NSView*)labelForRequest:(PermissionRequest*)request {
491 DCHECK(request);
492 base::scoped_nsobject<NSView> permissionView(
493 [[NSView alloc] initWithFrame:NSZeroRect]);
494 base::scoped_nsobject<NSImageView> permissionIcon(
495 [[NSImageView alloc] initWithFrame:NSZeroRect]);
496 [permissionIcon
497 setImage:NSImageFromImageSkia(gfx::CreateVectorIcon(
498 request->GetIconId(), 18, gfx::kChromeIconGrey))];
499 [permissionIcon setFrameSize:kPermissionIconSize];
500 [permissionView addSubview:permissionIcon];
501
502 base::scoped_nsobject<NSTextField> permissionLabel(
503 [[NSTextField alloc] initWithFrame:NSZeroRect]);
504 base::string16 label = request->GetMessageTextFragment();
505 [permissionLabel setDrawsBackground:NO];
506 [permissionLabel setBezeled:NO];
507 [permissionLabel setEditable:NO];
508 [permissionLabel setSelectable:NO];
509 [permissionLabel
510 setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
511 [permissionLabel setStringValue:base::SysUTF16ToNSString(label)];
512 [permissionLabel sizeToFit];
513 [permissionLabel setFrameOrigin:
514 NSMakePoint(NSWidth([permissionIcon frame]) + kHorizontalIconPadding, 0)];
515 [permissionView addSubview:permissionLabel];
516
517 // Match the horizontal centers of the two subviews. Note that the label's
518 // center is rounded down, and the icon's center, up. It looks better that
519 // way - with the text's center slightly lower than the icon's center - if the
520 // height delta is not evenly split.
521 NSRect iconFrame = [permissionIcon frame];
522 NSRect labelFrame = [permissionLabel frame];
523 NSRect unionFrame = NSUnionRect(iconFrame, labelFrame);
524
525 iconFrame.origin.y =
526 std::ceil((NSHeight(unionFrame) - NSHeight(iconFrame)) / 2);
527 labelFrame.origin.y =
528 std::floor((NSHeight(unionFrame) - NSHeight(labelFrame)) / 2);
529
530 [permissionLabel setFrame:labelFrame];
531 [permissionIcon setFrame:iconFrame];
532 [permissionView setFrame:unionFrame];
533
534 return permissionView.autorelease();
535 }
536
537 - (NSView*)titleWithOrigin:(const GURL&)origin {
538 base::scoped_nsobject<NSTextField> titleView(
539 [[NSTextField alloc] initWithFrame:NSZeroRect]);
540 [titleView setDrawsBackground:NO];
541 [titleView setBezeled:NO];
542 [titleView setEditable:NO];
543 [titleView setSelectable:NO];
544 [titleView setStringValue:l10n_util::GetNSStringF(
545 IDS_PERMISSIONS_BUBBLE_PROMPT,
546 url_formatter::FormatUrlForSecurityDisplay(
547 origin, url_formatter::SchemeDisplay::
548 OMIT_CRYPTOGRAPHIC))];
549 [titleView setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
550 [titleView sizeToFit];
551 NSRect titleFrame = [titleView frame];
552 [titleView setFrameSize:NSMakeSize(NSWidth(titleFrame) + kTitlePaddingX,
553 NSHeight(titleFrame))];
554 return titleView.autorelease();
555 }
556
557 - (NSView*)menuForRequest:(PermissionRequest*)request
558 atIndex:(int)index
559 allow:(BOOL)allow {
560 DCHECK(request);
561 DCHECK(delegate_);
562 base::scoped_nsobject<AllowBlockMenuButton> button(
563 [[AllowBlockMenuButton alloc] initForURL:request->GetOrigin()
564 allowed:allow
565 index:index
566 delegate:delegate_
567 profile:browser_->profile()]);
568 return button.autorelease();
569 }
570
571 - (NSView*)buttonWithTitle:(NSString*)title
572 action:(SEL)action {
573 base::scoped_nsobject<NSButton> button(
574 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]);
575 [button setButtonType:NSMomentaryPushInButton];
576 [button setTitle:title];
577 [button setTarget:self];
578 [button setAction:action];
579 [button sizeToFit];
580 return button.autorelease();
581 }
582
583 - (NSView*)blockButton {
584 NSString* blockTitle = l10n_util::GetNSString(IDS_PERMISSION_DENY);
585 return [self buttonWithTitle:blockTitle
586 action:@selector(onBlock:)];
587 }
588
589 - (NSView*)closeButton {
590 int dimension = chrome_style::GetCloseButtonSize();
591 NSRect frame = NSMakeRect(0, 0, dimension, dimension);
592 base::scoped_nsobject<NSButton> button(
593 [[WebUIHoverCloseButton alloc] initWithFrame:frame]);
594 [button setAction:@selector(onClose:)];
595 [button setTarget:self];
596 return button.autorelease();
597 }
598
599 - (void)ok:(id)sender {
600 if (delegate_)
601 delegate_->Accept();
602 }
603
604 - (void)onAllow:(id)sender {
605 if (delegate_)
606 delegate_->Accept();
607 }
608
609 - (void)onBlock:(id)sender {
610 if (delegate_)
611 delegate_->Deny();
612 }
613
614 - (void)onClose:(id)sender {
615 if (delegate_)
616 delegate_->Closing();
617 }
618
619 + (NSInteger)getFullscreenLeftOffset {
620 return kFullscreenLeftOffset;
621 }
622
623 - (void)activateTabWithContents:(content::WebContents*)newContents
624 previousContents:(content::WebContents*)oldContents
625 atIndex:(NSInteger)index
626 reason:(int)reason {
627 // The show/hide of this bubble is handled by the PermissionRequestManager.
628 // So bypass the base class, which would close the bubble here.
629 }
630
631 + (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB {
632 NSRect frameA = [viewA frame];
633 NSRect frameB = [viewB frame];
634 CGFloat width = std::max(NSWidth(frameA), NSWidth(frameB));
635 [viewA setFrameSize:NSMakeSize(width, NSHeight(frameA))];
636 [viewB setFrameSize:NSMakeSize(width, NSHeight(frameB))];
637 return width;
638 }
639
640 + (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB {
641 NSRect frameA = [viewA frame];
642 NSRect frameB = [viewB frame];
643 frameA.origin.y =
644 NSMinY(frameB) + std::floor((NSHeight(frameB) - NSHeight(frameA)) / 2);
645 [viewA setFrameOrigin:frameA.origin];
646 }
647
648 - (IBAction)cancel:(id)sender {
649 // This is triggered by ESC when the bubble has focus.
650 if (delegate_)
651 delegate_->Closing();
652 [super cancel:sender];
653 }
654
655 @end // implementation PermissionBubbleController
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698