Upstream version 10.38.208.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / browser_window_controller_private.mm
index 01bb5e6..0bf99da 100644 (file)
@@ -7,17 +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/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"
 
@@ -56,6 +58,10 @@ const CGFloat kAvatarRightOffset = 4;
 // incognito badge is present.
 const CGFloat kAvatarTabStripShrink = 18;
 
+// Width of the full screen icon. Used to position the AvatarButton to the
+// left of the icon.
+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
 // following best, though arguably 0 inset is better/more correct.
@@ -123,7 +129,7 @@ const CGFloat kLocBarBottomInset = 1;
   DictionaryPrefUpdate update(
       prefs,
       chrome::GetWindowPlacementKey(browser_.get()).c_str());
-  DictionaryValue* windowPreferences = update.Get();
+  base::DictionaryValue* windowPreferences = update.Get();
   windowPreferences->SetInteger("left", bounds.x());
   windowPreferences->SetInteger("top", bounds.y());
   windowPreferences->SetInteger("right", bounds.right());
@@ -308,22 +314,45 @@ 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 buttonHeight = std::min(
-        static_cast<CGFloat>(profiles::kAvatarIconHeight), tabStripHeight);
-    [avatarButton setFrameSize:NSMakeSize(NSWidth([avatarButton frame]),
-                                          buttonHeight)];
-
-    // Actually place the badge *above* |maxY|, by +2 to miss the divider.
     CGFloat badgeXOffset = -kAvatarRightOffset;
-    CGFloat badgeYOffset = 2 * [[avatarButton superview] cr_lineWidth];
+    CGFloat badgeYOffset = 0;
+    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.
+      badgeYOffset = (tabStripHeight - buttonHeight) / 2;
+    } else {
+      // 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 =
         NSMakePoint(width - NSWidth([avatarButton frame]) + badgeXOffset,
                     maxY + badgeYOffset);
@@ -341,11 +370,20 @@ willPositionSheet:(NSWindow*)sheet
     FramedBrowserWindow* window =
         static_cast<FramedBrowserWindow*>([self window]);
     rightIndent += -[window fullScreenButtonOriginAdjustment].x;
+
+    if ([self shouldUseNewAvatarButton]) {
+      // 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;
-    NSButton* labelButton = [avatarButtonController_ labelButtonView];
-    if (labelButton)
-      rightIndent += NSWidth([labelButton frame]) + kAvatarRightOffset;
+    rightIndent += kAvatarTabStripShrink +
+        NSWidth([avatarButton frame]) + kAvatarRightOffset;
   }
   [tabStripController_ setRightIndentForControls:rightIndent];
 
@@ -490,6 +528,10 @@ willPositionSheet:(NSWindow*)sheet
   }
 }
 
+- (void)updateRoundedBottomCorners {
+  [[self tabContentArea] setRoundedBottomCorners:![self isFullscreen]];
+}
+
 - (void)adjustToolbarAndBookmarkBarForCompression:(CGFloat)compression {
   CGFloat newHeight =
       [toolbarController_ desiredHeightForCompression:compression];
@@ -509,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;
 
@@ -564,16 +599,17 @@ willPositionSheet:(NSWindow*)sheet
 
   // Move the incognito badge if present.
   if ([self shouldShowAvatar]) {
-    [[avatarButtonController_ view] removeFromSuperview];
-    [[avatarButtonController_ view] setHidden:YES];  // Will be shown in layout.
-    [[[destWindow contentView] superview] addSubview:
-        [avatarButtonController_ view]];
+    NSView* avatarButtonView = [avatarButtonController_ view];
+
+    [avatarButtonView removeFromSuperview];
+    [avatarButtonView setHidden:YES];  // Will be shown in layout.
+    [[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];
@@ -596,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])
@@ -610,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 {
@@ -630,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;
@@ -644,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();
@@ -675,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;
@@ -700,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];
@@ -741,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) {
@@ -803,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();
@@ -828,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];
@@ -839,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.
@@ -882,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];
 }
@@ -976,22 +1081,11 @@ willPositionSheet:(NSWindow*)sheet
   // transitioning between composited and non-composited mode.
   // http://crbug.com/279472
   allowOverlappingViews = YES;
+  contents->SetAllowOverlappingViews(allowOverlappingViews);
 
-  if (allowOverlappingViews &&
-      [self coreAnimationStatus] ==
-          browser_window_controller::kCoreAnimationEnabledLazy) {
-    [[[self window] contentView] setWantsLayer:YES];
-    [[self tabStripView] setWantsLayer:YES];
-  }
-
-  contents->GetView()->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 {
@@ -1000,21 +1094,4 @@ willPositionSheet:(NSWindow*)sheet
       setShouldSuppressTopInfoBarTip:![self hasToolbar]];
 }
 
-- (browser_window_controller::CoreAnimationStatus)coreAnimationStatus {
-  // TODO(sail) Remove this.
-  if (!CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kUseCoreAnimation)) {
-    return browser_window_controller::kCoreAnimationDisabled;
-  }
-  if (CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-          switches::kUseCoreAnimation) == "lazy") {
-    return browser_window_controller::kCoreAnimationEnabledLazy;
-  }
-  if (CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-          switches::kUseCoreAnimation) == "disabled") {
-    return browser_window_controller::kCoreAnimationDisabled;
-  }
-  return browser_window_controller::kCoreAnimationEnabledAlways;
-}
-
 @end  // @implementation BrowserWindowController(Private)