Upstream version 10.38.208.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / tabs / tab_strip_controller.mm
index 7c33924..9a0e525 100644 (file)
@@ -19,9 +19,6 @@
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/autocomplete/autocomplete_classifier.h"
 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
-#include "chrome/browser/autocomplete/autocomplete_input.h"
-#include "chrome/browser/autocomplete/autocomplete_match.h"
-#include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/extensions/tab_helper.h"
 #include "chrome/browser/favicon/favicon_tab_helper.h"
 #include "chrome/browser/profiles/profile.h"
@@ -43,7 +40,6 @@
 #import "chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_view.h"
-#import "chrome/browser/ui/cocoa/tabs/throbber_view.h"
 #include "chrome/browser/ui/find_bar/find_bar.h"
 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h"
 #include "chrome/browser/ui/tabs/tab_utils.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/net/url_fixer_upper.h"
 #include "chrome/common/pref_names.h"
+#include "components/metrics/proto/omnibox_event.pb.h"
+#include "components/omnibox/autocomplete_match.h"
+#include "components/url_fixer/url_fixer.h"
 #include "components/web_modal/web_contents_modal_dialog_manager.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/user_metrics.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_view.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "grit/ui_resources.h"
@@ -71,6 +68,7 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/theme_provider.h"
 #include "ui/gfx/image/image.h"
+#include "ui/gfx/mac/scoped_ns_disable_screen_updates.h"
 
 using base::UserMetricsAction;
 using content::OpenURLParams;
@@ -93,9 +91,6 @@ const CGFloat kTabOverlap = 19.0;
 // The amount by which mini tabs are separated from normal tabs.
 const CGFloat kLastMiniTabSpacing = 2.0;
 
-// The width and height for a tab's icon.
-const CGFloat kIconWidthAndHeight = 16.0;
-
 // The amount by which the new tab button is offset (from the tabs).
 const CGFloat kNewTabButtonOffset = 8.0;
 
@@ -153,7 +148,7 @@ NSImage* CreateImageWithSize(NSSize size,
   base::scoped_nsobject<NSImage> result([[NSImage alloc] initWithSize:size]);
   [NSGraphicsContext saveGraphicsState];
   for (ui::ScaleFactor scale_factor : ui::GetSupportedScaleFactors()) {
-    float scale = GetImageScale(scale_factor);
+    float scale = GetScaleForScaleFactor(scale_factor);
     NSBitmapImageRep *bmpImageRep = [[[NSBitmapImageRep alloc]
         initWithBitmapDataPlanes:NULL
                       pixelsWide:size.width * scale
@@ -236,13 +231,14 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
 - (void)addSubviewToPermanentList:(NSView*)aView;
 - (void)regenerateSubviewList;
 - (NSInteger)indexForContentsView:(NSView*)view;
-- (NSImageView*)iconImageViewForContents:(content::WebContents*)contents;
+- (NSImage*)iconImageForContents:(content::WebContents*)contents;
 - (void)updateIconsForContents:(content::WebContents*)contents
                        atIndex:(NSInteger)modelIndex;
 - (void)layoutTabsWithAnimation:(BOOL)animate
              regenerateSubviews:(BOOL)doUpdate;
-- (void)animationDidStopForController:(TabController*)controller
-                             finished:(BOOL)finished;
+- (void)animationDidStop:(CAAnimation*)animation
+           forController:(TabController*)controller
+                finished:(BOOL)finished;
 - (NSInteger)indexFromModelIndex:(NSInteger)index;
 - (void)clickNewTabButton:(id)sender;
 - (NSInteger)numberOfOpenTabs;
@@ -391,7 +387,9 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
 }
 
 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished {
-  [strip_ animationDidStopForController:controller_ finished:finished];
+  [strip_ animationDidStop:animation
+             forController:controller_
+                  finished:finished];
 }
 
 @end
@@ -477,6 +475,7 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
     [self addSubviewToPermanentList:dragBlockingView_];
 
     newTabButton_ = [view getNewTabButton];
+    [newTabButton_ setWantsLayer:YES];
     [self addSubviewToPermanentList:newTabButton_];
     [newTabButton_ setTarget:self];
     [newTabButton_ setAction:@selector(clickNewTabButton:)];
@@ -613,9 +612,11 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
   NSInteger index = [self indexFromModelIndex:modelIndex];
   TabContentsController* controller = [tabContentsArray_ objectAtIndex:index];
 
+  // Make sure we do not draw any transient arrangements of views.
+  gfx::ScopedNSDisableScreenUpdates ns_disabler;
   // Make sure that any layers that move are not animated to their new
   // positions.
-  ScopedCAActionDisabler disabler;
+  ScopedCAActionDisabler ca_disabler;
 
   // Resize the new view to fit the window. Calling |view| may lazily
   // instantiate the TabContentsController from the nib. Until we call
@@ -784,6 +785,14 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
   return -1;
 }
 
+- (NSArray*)selectedViews {
+  NSMutableArray* views = [NSMutableArray arrayWithCapacity:[tabArray_ count]];
+  for (TabController* tab in tabArray_.get()) {
+    if ([tab selected])
+      [views addObject:[tab tabView]];
+  }
+  return views;
+}
 
 // Returns the view at the given index, using the array of TabControllers to
 // get the associated view. Returns nil if out of range.
@@ -1254,12 +1263,8 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
 
   // Make a new tab. Load the contents of this tab from the nib and associate
   // the new controller with |contents| so it can be looked up later.
-  const BOOL autoEmbedFullscreen =
-      implicit_cast<content::WebContentsDelegate*>(browser_)->
-          EmbedsFullscreenWidget();
   base::scoped_nsobject<TabContentsController> contentsController(
-      [[TabContentsController alloc] initWithContents:contents
-                               andAutoEmbedFullscreen:autoEmbedFullscreen]);
+      [[TabContentsController alloc] initWithContents:contents]);
   [tabContentsArray_ insertObject:contentsController atIndex:index];
 
   // Make a new tab and add it to the strip. Keep track of its controller.
@@ -1300,7 +1305,7 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
 
 // Called before |contents| is deactivated.
 - (void)tabDeactivatedWithContents:(content::WebContents*)contents {
-  contents->GetView()->StoreFocus();
+  contents->StoreFocus();
 }
 
 // Called when a notification is received from the model to select a particular
@@ -1346,7 +1351,7 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
 
   if (newContents) {
     newContents->WasShown();
-    newContents->GetView()->RestoreFocus();
+    newContents->RestoreFocus();
   }
 }
 
@@ -1378,12 +1383,8 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
   // Simply create a new TabContentsController for |newContents| and place it
   // into the array, replacing |oldContents|.  An ActiveTabChanged notification
   // will follow, at which point we will install the new view.
-  const BOOL autoEmbedFullscreen =
-      implicit_cast<content::WebContentsDelegate*>(browser_)->
-          EmbedsFullscreenWidget();
   base::scoped_nsobject<TabContentsController> newController(
-      [[TabContentsController alloc] initWithContents:newContents
-                               andAutoEmbedFullscreen:autoEmbedFullscreen]);
+      [[TabContentsController alloc] initWithContents:newContents]);
 
   // Bye bye, |oldController|.
   [tabContentsArray_ replaceObjectAtIndex:index withObject:newController];
@@ -1435,8 +1436,10 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
 
 // Called by the CAAnimation delegate when the tab completes the closing
 // animation.
-- (void)animationDidStopForController:(TabController*)controller
-                             finished:(BOOL)finished {
+- (void)animationDidStop:(CAAnimation*)animation
+           forController:(TabController*)controller
+                finished:(BOOL)finished{
+  [[animation delegate] invalidate];
   [closingControllers_ removeObject:controller];
   [self removeTab:controller];
 }
@@ -1507,7 +1510,7 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
 
 // A helper routine for creating an NSImageView to hold the favicon or app icon
 // for |contents|.
-- (NSImageView*)iconImageViewForContents:(content::WebContents*)contents {
+- (NSImage*)iconImageForContents:(content::WebContents*)contents {
   extensions::TabHelper* extensions_tab_helper =
       extensions::TabHelper::FromWebContents(contents);
   BOOL isApp = extensions_tab_helper->is_app();
@@ -1527,10 +1530,8 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
   // from an SkBitmap. Either way, just show the default.
   if (!image)
     image = defaultFavicon_.get();
-  NSRect frame = NSMakeRect(0, 0, kIconWidthAndHeight, kIconWidthAndHeight);
-  NSImageView* view = [[[NSImageView alloc] initWithFrame:frame] autorelease];
-  [view setImage:image];
-  return view;
+
+  return image;
 }
 
 // Updates the current loading state, replacing the icon view with a favicon,
@@ -1569,7 +1570,7 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
   } else if (contents->IsWaitingForResponse()) {
     newState = kTabWaiting;
     throbberImage = throbberWaitingImage;
-  } else if (contents->IsLoading()) {
+  } else if (contents->IsLoadingToDifferentDocument()) {
     newState = kTabLoading;
     throbberImage = throbberLoadingImage;
   }
@@ -1583,10 +1584,9 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
   // every call to this function is significant.
   if (newState == kTabDone || oldState != newState ||
       oldHasIcon != newHasIcon) {
-    NSView* iconView = nil;
     if (newHasIcon) {
       if (newState == kTabDone) {
-        iconView = [self iconImageViewForContents:contents];
+        [tabController setIconImage:[self iconImageForContents:contents]];
         const TabMediaState mediaState =
             chrome::GetTabMediaStateForContents(contents);
         // Create MediaIndicatorView upon first use.
@@ -1598,30 +1598,14 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
         }
         [[tabController mediaIndicatorView] updateIndicator:mediaState];
       } else if (newState == kTabCrashed) {
-        NSImage* oldImage = [[self iconImageViewForContents:contents] image];
-        NSRect frame =
-            NSMakeRect(0, 0, kIconWidthAndHeight, kIconWidthAndHeight);
-        iconView = [ThrobberView toastThrobberViewWithFrame:frame
-                                                beforeImage:oldImage
-                                                 afterImage:sadFaviconImage];
+        [tabController setIconImage:sadFaviconImage withToastAnimation:YES];
         [[tabController mediaIndicatorView]
           updateIndicator:TAB_MEDIA_STATE_NONE];
       } else {
-        NSRect frame =
-            NSMakeRect(0, 0, kIconWidthAndHeight, kIconWidthAndHeight);
-        iconView = [ThrobberView filmstripThrobberViewWithFrame:frame
-                                                          image:throbberImage];
+        [tabController setIconImage:throbberImage];
       }
-    }
-
-    [tabController setIconView:iconView];
-    if (iconView) {
-      // See the comment above kTabOverlap for why these DCHECKs exist.
-      DCHECK_GE(NSMinX([iconView frame]), kTabOverlap);
-      // TODO(thakis): Ideally, this would be true too, but it's not true in
-      // some tests.
-      //DCHECK_LE(NSMaxX([iconView frame]),
-      //          NSWidth([[tabController view] frame]) - kTabOverlap);
+    } else {
+      [tabController setIconImage:nil];
     }
   }
 }
@@ -1711,8 +1695,7 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
   [self layoutTabs];
 }
 
-- (void)setFrameOfActiveTab:(NSRect)frame {
-  NSView* view = [self activeTabView];
+- (void)setFrame:(NSRect)frame ofTabView:(NSView*)view {
   NSValue* identifier = [NSValue valueWithPointer:view];
   [targetFrames_ setObject:[NSValue valueWithRect:frame]
                     forKey:identifier];
@@ -1723,6 +1706,14 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
   return tabStripModel_;
 }
 
+- (NSArray*)tabViews {
+  NSMutableArray* views = [NSMutableArray arrayWithCapacity:[tabArray_ count]];
+  for (TabController* tab in tabArray_.get()) {
+    [views addObject:[tab tabView]];
+  }
+  return views;
+}
+
 - (NSView*)activeTabView {
   int activeIndex = tabStripModel_->active_index();
   // Take closing tabs into account. They can't ever be selected.
@@ -1730,16 +1721,18 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
   return [self viewAtIndex:activeIndex];
 }
 
-// Find the model index based on the x coordinate of the placeholder. If there
-// is no placeholder, this returns the end of the tab strip. Closing tabs are
-// not considered in computing the index.
 - (int)indexOfPlaceholder {
-  double placeholderX = placeholderFrame_.origin.x;
-  int index = 0;
-  int location = 0;
   // Use |tabArray_| here instead of the tab strip count in order to get the
   // correct index when there are closing tabs to the left of the placeholder.
   const int count = [tabArray_ count];
+
+  // No placeholder, return the end of the strip.
+  if (placeholderTab_ == nil)
+    return count;
+
+  double placeholderX = placeholderFrame_.origin.x;
+  int index = 0;
+  int location = 0;
   while (index < count) {
     // Ignore closing tabs for simplicity. The only drawback of this is that
     // if the placeholder is placed right before one or several contiguous
@@ -1785,10 +1778,10 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
 // new window. Mini-tabs are either app or pinned tabs; the app state is stored
 // by the |contents|, but the |pinned| state is the caller's responsibility.
 - (void)dropWebContents:(WebContents*)contents
+                atIndex:(int)modelIndex
               withFrame:(NSRect)frame
-            asPinnedTab:(BOOL)pinned {
-  int modelIndex = [self indexOfPlaceholder];
-
+            asPinnedTab:(BOOL)pinned
+               activate:(BOOL)activate {
   // Mark that the new tab being created should start at |frame|. It will be
   // reset as soon as the tab has been positioned.
   droppedTabFrame_ = frame;
@@ -1796,8 +1789,10 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
   // Insert it into this tab strip. We want it in the foreground and to not
   // inherit the current tab's group.
   tabStripModel_->InsertWebContentsAt(
-      modelIndex, contents,
-      TabStripModel::ADD_ACTIVE | (pinned ? TabStripModel::ADD_PINNED : 0));
+      modelIndex,
+      contents,
+      (activate ? TabStripModel::ADD_ACTIVE : TabStripModel::ADD_NONE) |
+          (pinned ? TabStripModel::ADD_PINNED : TabStripModel::ADD_NONE));
 }
 
 // Called when the tab strip view changes size. As we only registered for
@@ -2074,7 +2069,7 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
     NOTIMPLEMENTED();
 
   // Get the first URL and fix it up.
-  GURL url(GURL(URLFixerUpper::FixupURL(
+  GURL url(GURL(url_fixer::FixupURL(
       base::SysNSStringToUTF8([urls objectAtIndex:0]), std::string())));
 
   [self openURL:&url inView:view at:point];
@@ -2087,8 +2082,8 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
   // If the input is plain text, classify the input and make the URL.
   AutocompleteMatch match;
   AutocompleteClassifierFactory::GetForProfile(browser_->profile())->Classify(
-      base::SysNSStringToUTF16(text), false, false, AutocompleteInput::BLANK,
-      &match, NULL);
+      base::SysNSStringToUTF16(text), false, false,
+      metrics::OmniboxEventProto::BLANK, &match, NULL);
   GURL url(match.destination_url);
 
   [self openURL:&url inView:view at:point];
@@ -2177,6 +2172,56 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
   return [tabContentsArray_ objectAtIndex:index];
 }
 
+- (void)addWindowControls {
+  if (!fullscreenWindowControls_) {
+    // Make the container view.
+    CGFloat height = NSHeight([tabStripView_ frame]);
+    NSRect frame = NSMakeRect(0, 0, [self leftIndentForControls], height);
+    fullscreenWindowControls_.reset([[NSView alloc] initWithFrame:frame]);
+    [fullscreenWindowControls_
+        setAutoresizingMask:NSViewMaxXMargin | NSViewHeightSizable];
+
+    // Add the traffic light buttons. The horizontal layout was determined by
+    // manual inspection on Yosemite.
+    CGFloat closeButtonX = 11;
+    CGFloat miniButtonX = 31;
+    CGFloat zoomButtonX = 51;
+
+    NSUInteger styleMask = [[tabStripView_ window] styleMask];
+    NSButton* closeButton = [NSWindow standardWindowButton:NSWindowCloseButton
+                                              forStyleMask:styleMask];
+
+    // Vertically center the buttons in the tab strip.
+    CGFloat buttonY = floor((height - NSHeight([closeButton bounds])) / 2);
+    [closeButton setFrameOrigin:NSMakePoint(closeButtonX, buttonY)];
+    [fullscreenWindowControls_ addSubview:closeButton];
+
+    NSButton* miniaturizeButton =
+        [NSWindow standardWindowButton:NSWindowMiniaturizeButton
+                          forStyleMask:styleMask];
+    [miniaturizeButton setFrameOrigin:NSMakePoint(miniButtonX, buttonY)];
+    [miniaturizeButton setEnabled:NO];
+    [fullscreenWindowControls_ addSubview:miniaturizeButton];
+
+    NSButton* zoomButton =
+        [NSWindow standardWindowButton:NSWindowZoomButton
+                          forStyleMask:styleMask];
+    [fullscreenWindowControls_ addSubview:zoomButton];
+    [zoomButton setFrameOrigin:NSMakePoint(zoomButtonX, buttonY)];
+  }
+
+  if (![permanentSubviews_ containsObject:fullscreenWindowControls_]) {
+    [self addSubviewToPermanentList:fullscreenWindowControls_];
+    [self regenerateSubviewList];
+  }
+}
+
+- (void)removeWindowControls {
+  if (fullscreenWindowControls_)
+    [permanentSubviews_ removeObject:fullscreenWindowControls_];
+  [self regenerateSubviewList];
+}
+
 - (void)themeDidChangeNotification:(NSNotification*)notification {
   [self setNewTabImages];
 }
@@ -2226,9 +2271,18 @@ NSView* GetSheetParentViewForWebContents(WebContents* web_contents) {
   // View hierarchy of the contents view:
   // NSView  -- switchView, same for all tabs
   // +- NSView  -- TabContentsController's view
-  //    +- TabContentsViewCocoa
+  //    +- WebContentsViewCocoa
   //
   // Changing it? Do not forget to modify
   // -[TabStripController swapInTabAtIndex:] too.
-  return [web_contents->GetView()->GetNativeView() superview];
+  return [web_contents->GetNativeView() superview];
+}
+
+NSRect GetSheetParentBoundsForParentView(NSView* view) {
+  // If the devtools view is open, it shrinks the size of the WebContents, so go
+  // up the hierarchy to the devtools container view to avoid that. Note that
+  // the devtools view is always in the hierarchy even if it is not open or it
+  // is detached.
+  NSView* devtools_view = [[[view superview] superview] superview];
+  return [devtools_view convertRect:[devtools_view bounds] toView:nil];
 }