Upstream version 10.38.208.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / browser_window_controller_private.mm
index af920e6..0bf99da 100644 (file)
@@ -7,18 +7,17 @@
 #include <cmath>
 
 #include "base/command_line.h"
+#include "base/mac/mac_util.h"
 #import "base/mac/scoped_nsobject.h"
 #include "base/prefs/pref_service.h"
 #include "base/prefs/scoped_user_pref_update.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/fullscreen.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_info_util.h"
+#include "chrome/browser/profiles/profile_avatar_icon_util.h"
 #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window_state.h"
-#import "chrome/browser/ui/cocoa/browser/avatar_button_controller.h"
-#import "chrome/browser/ui/cocoa/browser/avatar_icon_controller.h"
 #import "chrome/browser/ui/cocoa/dev_tools_controller.h"
 #import "chrome/browser/ui/cocoa/fast_resize_view.h"
 #import "chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h"
 #include "chrome/browser/ui/cocoa/last_active_browser_cocoa.h"
 #import "chrome/browser/ui/cocoa/nsview_additions.h"
 #import "chrome/browser/ui/cocoa/presentation_mode_controller.h"
+#import "chrome/browser/ui/cocoa/profiles/avatar_button_controller.h"
+#import "chrome/browser/ui/cocoa/profiles/avatar_icon_controller.h"
 #import "chrome/browser/ui/cocoa/status_bubble_mac.h"
 #import "chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller.h"
-#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
+#import "chrome/browser/ui/cocoa/version_independent_window.h"
+#import "chrome/browser/ui/cocoa/website_settings/permission_bubble_cocoa.h"
 #include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_view.h"
 #import "ui/base/cocoa/focus_tracker.h"
 #include "ui/base/ui_base_types.h"
 
@@ -59,7 +60,7 @@ const CGFloat kAvatarTabStripShrink = 18;
 
 // Width of the full screen icon. Used to position the AvatarButton to the
 // left of the icon.
-const CGFloat kFullscreenIconWidth = 30;
+const CGFloat kFullscreenIconWidth = 32;
 
 // Insets for the location bar, used when the full toolbar is hidden.
 // TODO(viettrungluu): We can argue about the "correct" insetting; I like the
@@ -313,32 +314,43 @@ willPositionSheet:(NSWindow*)sheet
   maxY -= tabStripHeight;
   [tabStripView setFrame:NSMakeRect(0, maxY, width, tabStripHeight)];
 
+  // In Yosemite fullscreen, manually add the fullscreen controls to the tab
+  // strip.
+  BOOL isInAppKitFullscreen =
+      [self isInSystemFullscreen] || enteringSystemFullscreen_;
+  BOOL addControlsInFullscreen =
+      isInAppKitFullscreen && base::mac::IsOSYosemiteOrLater();
+
   // Set left indentation based on fullscreen mode status.
-  [tabStripController_ setLeftIndentForControls:(fullscreen ? 0 :
-      [[tabStripController_ class] defaultLeftIndentForControls])];
+  CGFloat leftIndent = 0;
+  if (!fullscreen || addControlsInFullscreen)
+    leftIndent = [[tabStripController_ class] defaultLeftIndentForControls];
+  [tabStripController_ setLeftIndentForControls:leftIndent];
+
+  if (addControlsInFullscreen)
+    [tabStripController_ addWindowControls];
+  else
+    [tabStripController_ removeWindowControls];
 
   // Lay out the icognito/avatar badge because calculating the indentation on
   // the right depends on it.
+  NSView* avatarButton = [avatarButtonController_ view];
   if ([self shouldShowAvatar]) {
-    NSView* avatarButton = [avatarButtonController_ view];
     CGFloat badgeXOffset = -kAvatarRightOffset;
     CGFloat badgeYOffset = 0;
-    CGFloat buttonHeight;
+    CGFloat buttonHeight = NSHeight([avatarButton frame]);
 
     if ([self shouldUseNewAvatarButton]) {
       // The fullscreen icon is displayed to the right of the avatar button.
       if (![self isFullscreen])
         badgeXOffset -= kFullscreenIconWidth;
-
       // Center the button vertically on the tabstrip.
-      buttonHeight = NSHeight([avatarButton frame]);
       badgeYOffset = (tabStripHeight - buttonHeight) / 2;
     } else {
-      buttonHeight = static_cast<CGFloat>(profiles::kAvatarIconHeight);
       // Actually place the badge *above* |maxY|, by +2 to miss the divider.
       badgeYOffset = 2 * [[avatarButton superview] cr_lineWidth];
-
     }
+
     [avatarButton setFrameSize:NSMakeSize(NSWidth([avatarButton frame]),
         std::min(buttonHeight, tabStripHeight))];
     NSPoint origin =
@@ -358,18 +370,20 @@ willPositionSheet:(NSWindow*)sheet
     FramedBrowserWindow* window =
         static_cast<FramedBrowserWindow*>([self window]);
     rightIndent += -[window fullScreenButtonOriginAdjustment].x;
-  } else if ([self shouldShowAvatar]) {
-    rightIndent += kAvatarTabStripShrink;
+
     if ([self shouldUseNewAvatarButton]) {
-      rightIndent += NSWidth([[avatarButtonController_ view] frame])
-        + kAvatarTabStripShrink;
-    } else {
-      NSButton* labelButton =
-          [static_cast<AvatarIconController*>(avatarButtonController_)
-              labelButtonView];
-      if (labelButton)
-        rightIndent += NSWidth([labelButton frame]) + kAvatarRightOffset;
+      // The new avatar is wider than the default indentation, so we need to
+      // account for its width.
+      rightIndent += NSWidth([avatarButton frame]) + kAvatarTabStripShrink;
+
+      // When the fullscreen icon is not displayed, return its width to the
+      // tabstrip.
+      if ([self isFullscreen])
+        rightIndent -= kFullscreenIconWidth;
     }
+  } else if ([self shouldShowAvatar]) {
+    rightIndent += kAvatarTabStripShrink +
+        NSWidth([avatarButton frame]) + kAvatarRightOffset;
   }
   [tabStripController_ setRightIndentForControls:rightIndent];
 
@@ -514,6 +528,10 @@ willPositionSheet:(NSWindow*)sheet
   }
 }
 
+- (void)updateRoundedBottomCorners {
+  [[self tabContentArea] setRoundedBottomCorners:![self isFullscreen]];
+}
+
 - (void)adjustToolbarAndBookmarkBarForCompression:(CGFloat)compression {
   CGFloat newHeight =
       [toolbarController_ desiredHeightForCompression:compression];
@@ -533,16 +551,9 @@ willPositionSheet:(NSWindow*)sheet
 
 // Fullscreen and presentation mode methods
 
-- (BOOL)shouldShowPresentationModeToggle {
-  return chrome::mac::SupportsSystemFullscreen() && [self isFullscreen];
-}
-
-- (void)moveViewsForFullscreenForSnowLeopard:(BOOL)fullscreen
-    regularWindow:(NSWindow*)regularWindow
-    fullscreenWindow:(NSWindow*)fullscreenWindow {
-  // This method is only for systems without fullscreen support.
-  DCHECK(!chrome::mac::SupportsSystemFullscreen());
-
+- (void)moveViewsForImmersiveFullscreen:(BOOL)fullscreen
+                          regularWindow:(NSWindow*)regularWindow
+                       fullscreenWindow:(NSWindow*)fullscreenWindow {
   NSWindow* sourceWindow = fullscreen ? regularWindow : fullscreenWindow;
   NSWindow* destWindow = fullscreen ? fullscreenWindow : regularWindow;
 
@@ -592,13 +603,13 @@ willPositionSheet:(NSWindow*)sheet
 
     [avatarButtonView removeFromSuperview];
     [avatarButtonView setHidden:YES];  // Will be shown in layout.
-    [[[destWindow contentView] superview] addSubview: avatarButtonView];
+    [[destWindow cr_windowView] addSubview:avatarButtonView];
   }
 
   // Add the tab strip after setting the content view and moving the incognito
   // badge (if any), so that the tab strip will be on top (in the z-order).
   if ([self hasTabStrip])
-    [[[destWindow contentView] superview] addSubview:tabStripView];
+    [[destWindow cr_windowView] addSubview:tabStripView];
 
   [sourceWindow setWindowController:nil];
   [self setWindow:destWindow];
@@ -621,13 +632,31 @@ willPositionSheet:(NSWindow*)sheet
   [destWindow makeKeyAndOrderFront:self];
   [destWindow setCollectionBehavior:behavior];
 
-  [focusTracker restoreFocusInWindow:destWindow];
+  if (![focusTracker restoreFocusInWindow:destWindow]) {
+    // During certain types of fullscreen transitions, the view that had focus
+    // may have gone away (e.g., the one for a Flash FS widget).  In this case,
+    // FocusTracker will fail to restore focus to anything, so we set the focus
+    // to the tab contents as a reasonable fall-back.
+    [self focusTabContents];
+  }
   [sourceWindow orderOut:self];
 
   // We're done moving focus, so re-enable bar visibility changes.
   [self enableBarVisibilityUpdates];
 }
 
+- (void)permissionBubbleWindowWillClose:(NSNotification*)notification {
+  DCHECK(permissionBubbleCocoa_);
+
+  NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
+  [center removeObserver:self
+                    name:NSWindowWillCloseNotification
+                  object:[notification object]];
+  [self releaseBarVisibilityForOwner:[notification object]
+                       withAnimation:YES
+                               delay:YES];
+}
+
 - (void)setPresentationModeInternal:(BOOL)presentationMode
                       forceDropdown:(BOOL)forceDropdown {
   if (presentationMode == [self inPresentationMode])
@@ -635,15 +664,42 @@ willPositionSheet:(NSWindow*)sheet
 
   if (presentationMode) {
     BOOL fullscreen_for_tab =
-        browser_->fullscreen_controller()->IsFullscreenForTabOrPending();
+        browser_->fullscreen_controller()->IsWindowFullscreenForTabOrPending();
     BOOL kiosk_mode =
         CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode);
     BOOL showDropdown = !fullscreen_for_tab &&
         !kiosk_mode &&
         (forceDropdown || [self floatingBarHasFocus]);
-    NSView* contentView = [[self window] contentView];
     presentationModeController_.reset(
         [[PresentationModeController alloc] initWithBrowserController:self]);
+
+    if (permissionBubbleCocoa_ && permissionBubbleCocoa_->IsVisible()) {
+      DCHECK(permissionBubbleCocoa_->window());
+      // A visible permission bubble will force the dropdown to remain visible.
+      [self lockBarVisibilityForOwner:permissionBubbleCocoa_->window()
+                        withAnimation:NO
+                                delay:NO];
+      showDropdown = YES;
+      // Register to be notified when the permission bubble is closed, to
+      // allow fullscreen to hide the dropdown.
+      NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
+      [center addObserver:self
+                 selector:@selector(permissionBubbleWindowWillClose:)
+                     name:NSWindowWillCloseNotification
+                   object:permissionBubbleCocoa_->window()];
+    }
+    if (showDropdown) {
+      // Turn on layered mode for the window's root view for the entry
+      // animation.  Without this, the OS fullscreen animation for entering
+      // fullscreen mode does not correctly draw the tab strip.
+      // It will be turned off (set back to NO) when the animation finishes,
+      // in -windowDidEnterFullScreen:.
+      // Leaving wantsLayer on for the duration of presentation mode causes
+      // performance issues when the dropdown is animated in/out.  It also does
+      // not seem to be required for the exit animation.
+      [[[self window] cr_windowView] setWantsLayer:YES];
+    }
+    NSView* contentView = [[self window] contentView];
     [presentationModeController_ enterPresentationModeForContentView:contentView
                                  showDropdown:showDropdown];
   } else {
@@ -655,9 +711,10 @@ willPositionSheet:(NSWindow*)sheet
   [self layoutSubviews];
 }
 
-// TODO(rohitrao): This method is misnamed now, since there is a flag that
-// enables 10.6-style fullscreen on newer OSes.
-- (void)enterFullscreenForSnowLeopard {
+- (void)enterImmersiveFullscreen {
+  // |-isFullscreen:| will return YES from here onwards.
+  enteringFullscreen_ = YES;  // Set to NO by |-windowDidEnterFullScreen:|.
+
   // Fade to black.
   const CGDisplayReservationInterval kFadeDurationSeconds = 0.6;
   Boolean didFadeOut = NO;
@@ -669,15 +726,14 @@ willPositionSheet:(NSWindow*)sheet
         kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, /*synchronous=*/true);
   }
 
-  // Create the fullscreen window.  After this line, isFullscreen will return
-  // YES.
+  // Create the fullscreen window.
   fullscreenWindow_.reset([[self createFullscreenWindow] retain]);
   savedRegularWindow_ = [[self window] retain];
   savedRegularWindowFrame_ = [savedRegularWindow_ frame];
 
-  [self moveViewsForFullscreenForSnowLeopard:YES
-                               regularWindow:[self window]
-                            fullscreenWindow:fullscreenWindow_.get()];
+  [self moveViewsForImmersiveFullscreen:YES
+                          regularWindow:[self window]
+                       fullscreenWindow:fullscreenWindow_.get()];
 
   // When simplified fullscreen is enabled, do not enter presentation mode.
   const CommandLine* command_line = CommandLine::ForCurrentProcess();
@@ -700,11 +756,7 @@ willPositionSheet:(NSWindow*)sheet
   }
 }
 
-- (void)exitFullscreenForSnowLeopard {
-  // TODO(rohitrao): This method is misnamed now, since there is a flag that
-  // enables 10.6-style fullscreen on newer OSes.
-  DCHECK(!chrome::mac::SupportsSystemFullscreen());
-
+- (void)exitImmersiveFullscreen {
   // Fade to black.
   const CGDisplayReservationInterval kFadeDurationSeconds = 0.6;
   Boolean didFadeOut = NO;
@@ -725,9 +777,9 @@ willPositionSheet:(NSWindow*)sheet
 
   [self windowWillExitFullScreen:nil];
 
-  [self moveViewsForFullscreenForSnowLeopard:NO
-                                        regularWindow:savedRegularWindow_
-                                     fullscreenWindow:fullscreenWindow_.get()];
+  [self moveViewsForImmersiveFullscreen:NO
+                          regularWindow:savedRegularWindow_
+                       fullscreenWindow:fullscreenWindow_.get()];
 
   // When exiting fullscreen mode, we need to call layoutSubviews manually.
   [savedRegularWindow_ autorelease];
@@ -766,14 +818,15 @@ willPositionSheet:(NSWindow*)sheet
 
 - (void)showFullscreenExitBubbleIfNecessary {
   // This method is called in response to
-  // |-updateFullscreenExitBubbleURL:bubbleType:|. If on Lion the system is
-  // transitioning, do not show the bubble because it will cause visual jank
-  // <http://crbug.com/130649>. This will be called again as part of
+  // |-updateFullscreenExitBubbleURL:bubbleType:|. If we're in the middle of the
+  // transition into fullscreen (i.e., using the System Fullscreen API), do not
+  // show the bubble because it will cause visual jank
+  // (http://crbug.com/130649). This will be called again as part of
   // |-windowDidEnterFullScreen:|, so arrange to do that work then instead.
   if (enteringFullscreen_)
     return;
 
-  [presentationModeController_ ensureOverlayHiddenWithAnimation:NO delay:NO];
+  [self hideOverlayIfPossibleWithAnimation:NO delay:NO];
 
   if (fullscreenBubbleType_ == FEB_TYPE_NONE ||
       fullscreenBubbleType_ == FEB_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION) {
@@ -828,20 +881,36 @@ willPositionSheet:(NSWindow*)sheet
 }
 
 - (void)windowWillEnterFullScreen:(NSNotification*)notification {
-  [self registerForContentViewResizeNotifications];
+  if (notification)  // For System Fullscreen when non-nil.
+    [self registerForContentViewResizeNotifications];
 
   NSWindow* window = [self window];
   savedRegularWindowFrame_ = [window frame];
   BOOL mode = enteringPresentationMode_ ||
-       browser_->fullscreen_controller()->IsFullscreenForTabOrPending();
+       browser_->fullscreen_controller()->IsWindowFullscreenForTabOrPending();
   enteringFullscreen_ = YES;
+  enteringSystemFullscreen_ = YES;
   [self setPresentationModeInternal:mode forceDropdown:NO];
 }
 
 - (void)windowDidEnterFullScreen:(NSNotification*)notification {
-  if (chrome::mac::SupportsSystemFullscreen())
+  // In Yosemite, some combination of the titlebar and toolbar always show in
+  // full-screen mode. We do not want either to show. Search for the window that
+  // contains the views, and hide it. There is no need to ever unhide the view.
+  // http://crbug.com/380235
+  if (base::mac::IsOSYosemiteOrLater()) {
+    for (NSWindow* window in [[NSApplication sharedApplication] windows]) {
+      if ([window
+              isKindOfClass:NSClassFromString(@"NSToolbarFullScreenWindow")]) {
+        [window.contentView setHidden:YES];
+      }
+    }
+  }
+
+  if (notification)  // For System Fullscreen when non-nil.
     [self deregisterForContentViewResizeNotifications];
   enteringFullscreen_ = NO;
+  enteringSystemFullscreen_ = NO;
   enteringPresentationMode_ = NO;
 
   const CommandLine* command_line = CommandLine::ForCurrentProcess();
@@ -853,10 +922,12 @@ willPositionSheet:(NSWindow*)sheet
 
   [self showFullscreenExitBubbleIfNecessary];
   browser_->WindowFullscreenStateChanged();
+  [[[self window] cr_windowView] setWantsLayer:NO];
+  [self updateRoundedBottomCorners];
 }
 
 - (void)windowWillExitFullScreen:(NSNotification*)notification {
-  if (chrome::mac::SupportsSystemFullscreen())
+  if (notification)  // For System Fullscreen when non-nil.
     [self registerForContentViewResizeNotifications];
   fullscreenModeController_.reset();
   [self destroyFullscreenExitBubbleIfNecessary];
@@ -864,14 +935,16 @@ willPositionSheet:(NSWindow*)sheet
 }
 
 - (void)windowDidExitFullScreen:(NSNotification*)notification {
-  if (chrome::mac::SupportsSystemFullscreen())
+  if (notification)  // For System Fullscreen when non-nil.
     [self deregisterForContentViewResizeNotifications];
   browser_->WindowFullscreenStateChanged();
+  [self updateRoundedBottomCorners];
 }
 
 - (void)windowDidFailToEnterFullScreen:(NSWindow*)window {
   [self deregisterForContentViewResizeNotifications];
   enteringFullscreen_ = NO;
+  enteringSystemFullscreen_ = NO;
   [self setPresentationModeInternal:NO forceDropdown:NO];
 
   // Force a relayout to try and get the window back into a reasonable state.
@@ -907,6 +980,13 @@ willPositionSheet:(NSWindow*)sheet
   [presentationModeController_ cancelAnimationAndTimers];
 }
 
+- (void)hideOverlayIfPossibleWithAnimation:(BOOL)animation delay:(BOOL)delay {
+  if (!barVisibilityUpdatesEnabled_ || [barVisibilityLocks_ count])
+    return;
+  [presentationModeController_ ensureOverlayHiddenWithAnimation:animation
+                                                          delay:delay];
+}
+
 - (CGFloat)toolbarDividerOpacity {
   return [bookmarkBarController_ toolbarDividerOpacity];
 }
@@ -1001,14 +1081,11 @@ willPositionSheet:(NSWindow*)sheet
   // transitioning between composited and non-composited mode.
   // http://crbug.com/279472
   allowOverlappingViews = YES;
-  contents->GetView()->SetAllowOverlappingViews(allowOverlappingViews);
+  contents->SetAllowOverlappingViews(allowOverlappingViews);
 
-  DevToolsWindow* devToolsWindow =
-      DevToolsWindow::GetDockedInstanceForInspectedTab(contents);
-  if (devToolsWindow) {
-    devToolsWindow->web_contents()->GetView()->
-        SetAllowOverlappingViews(allowOverlappingViews);
-  }
+  WebContents* devTools = DevToolsWindow::GetInTabWebContents(contents, NULL);
+  if (devTools)
+    devTools->SetAllowOverlappingViews(allowOverlappingViews);
 }
 
 - (void)updateInfoBarTipVisibility {