Back out e9a46afd9375 (bug 1279017) for 10.10 reftest-e10s failures in async scrolling tests
authorPhil Ringnalda <philringnalda@gmail.com>
Wed, 08 Jun 2016 20:34:36 -0700
changeset 301201 79fdba402322d545a40702e2894c9960685da06e
parent 301200 6d21ad903c7a293ffe7a76460f9f6f3fbe0b9104
child 301202 8987c204d2920c40e6bd6bd79d9626591df58a33
push id78249
push userphilringnalda@gmail.com
push dateThu, 09 Jun 2016 03:36:31 +0000
treeherdermozilla-inbound@75f65d79283f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1279017
milestone50.0a1
backs oute9a46afd9375bf14dbbef5fb775473745d26a12b
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Back out e9a46afd9375 (bug 1279017) for 10.10 reftest-e10s failures in async scrolling tests CLOSED TREE
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
widget/cocoa/nsCocoaFeatures.mm
widget/cocoa/nsCocoaUtils.h
widget/cocoa/nsCocoaWindow.h
widget/cocoa/nsCocoaWindow.mm
widget/cocoa/nsLookAndFeel.mm
widget/cocoa/nsMenuX.h
widget/cocoa/nsNativeThemeCocoa.mm
widget/cocoa/nsNativeThemeColors.h
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -99,16 +99,75 @@ class APZCTreeManager;
 - (NSView *)titlebarView; // Method of NSThemeFrame
 - (NSView *)titlebarContainerView; // Method of NSThemeFrame
 - (BOOL)transparent; // Method of NSTitlebarView and NSTitlebarContainerView
 - (void)setTransparent:(BOOL)transparent; // Method of NSTitlebarView and
                                           // NSTitlebarContainerView
 
 @end
 
+#if !defined(MAC_OS_X_VERSION_10_6) || \
+MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
+@interface NSEvent (SnowLeopardEventFeatures)
++ (NSUInteger)pressedMouseButtons;
++ (NSUInteger)modifierFlags;
+@end
+#endif
+
+// The following section, required to support fluid swipe tracking on OS X 10.7
+// and up, contains defines/declarations that are only available on 10.7 and up.
+// [NSEvent trackSwipeEventWithOptions:...] also requires that the compiler
+// support "blocks"
+// (http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html)
+// -- which it does on 10.6 and up (using the 10.6 SDK or higher).
+//
+// MAC_OS_X_VERSION_MAX_ALLOWED "controls which OS functionality, if used,
+// will result in a compiler error because that functionality is not
+// available" (quoting from AvailabilityMacros.h).  The compiler initializes
+// it to the version of the SDK being used.  Its value does *not* prevent the
+// binary from running on higher OS versions.  MAC_OS_X_VERSION_10_7 and
+// friends are defined (in AvailabilityMacros.h) as decimal numbers (not
+// hexadecimal numbers).
+#if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
+enum {
+   NSFullScreenWindowMask = 1 << 14
+};
+
+@interface NSWindow (LionWindowFeatures)
+- (NSRect)convertRectToScreen:(NSRect)aRect;
+@end
+
+#ifdef __LP64__
+enum {
+  NSEventSwipeTrackingLockDirection = 0x1 << 0,
+  NSEventSwipeTrackingClampGestureAmount = 0x1 << 1
+};
+typedef NSUInteger NSEventSwipeTrackingOptions;
+
+enum {
+  NSEventGestureAxisNone = 0,
+  NSEventGestureAxisHorizontal,
+  NSEventGestureAxisVertical
+};
+typedef NSInteger NSEventGestureAxis;
+
+@interface NSEvent (FluidSwipeTracking)
++ (BOOL)isSwipeTrackingFromScrollEventsEnabled;
+- (BOOL)hasPreciseScrollingDeltas;
+- (CGFloat)scrollingDeltaX;
+- (CGFloat)scrollingDeltaY;
+- (NSEventPhase)phase;
+- (void)trackSwipeEventWithOptions:(NSEventSwipeTrackingOptions)options
+          dampenAmountThresholdMin:(CGFloat)minDampenThreshold
+                               max:(CGFloat)maxDampenThreshold
+                      usingHandler:(void (^)(CGFloat gestureAmount, NSEventPhase phase, BOOL isComplete, BOOL *stop))trackingHandler;
+@end
+#endif // #ifdef __LP64__
+#endif // #if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
+
 @interface ChildView : NSView<
 #ifdef ACCESSIBILITY
                               mozAccessible,
 #endif
                               mozView, NSTextInputClient>
 {
 @private
   // the nsChildView that created the view. It retains this NSView, so
@@ -247,16 +306,19 @@ class APZCTreeManager;
 - (void)magnifyWithEvent:(NSEvent *)anEvent;
 - (void)smartMagnifyWithEvent:(NSEvent *)anEvent;
 - (void)rotateWithEvent:(NSEvent *)anEvent;
 - (void)endGestureWithEvent:(NSEvent *)anEvent;
 
 - (void)scrollWheel:(NSEvent *)anEvent;
 - (void)handleAsyncScrollEvent:(CGEventRef)cgEvent ofType:(CGEventType)type;
 
+// Helper function for Lion smart magnify events
++ (BOOL)isLionSmartMagnifyEvent:(NSEvent*)anEvent;
+
 - (void)setUsingOMTCompositor:(BOOL)aUseOMTC;
 
 - (NSEvent*)lastKeyDownEvent;
 @end
 
 class ChildViewMouseTracker {
 
 public:
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -482,21 +482,23 @@ nsresult nsChildView::Create(nsIWidget* 
   // (see bug 559075).
   nsAutoreleasePool localPool;
 
   // See NSView (MethodSwizzling) below.
   if (!gChildViewMethodsSwizzled) {
     nsToolkit::SwizzleMethods([NSView class], @selector(mouseDownCanMoveWindow),
                               @selector(nsChildView_NSView_mouseDownCanMoveWindow));
 #ifdef __LP64__
-    nsToolkit::SwizzleMethods([NSEvent class], @selector(addLocalMonitorForEventsMatchingMask:handler:),
-                              @selector(nsChildView_NSEvent_addLocalMonitorForEventsMatchingMask:handler:),
-                              true);
-    nsToolkit::SwizzleMethods([NSEvent class], @selector(removeMonitor:),
-                              @selector(nsChildView_NSEvent_removeMonitor:), true);
+    if (nsCocoaFeatures::OnLionOrLater()) {
+      nsToolkit::SwizzleMethods([NSEvent class], @selector(addLocalMonitorForEventsMatchingMask:handler:),
+                                @selector(nsChildView_NSEvent_addLocalMonitorForEventsMatchingMask:handler:),
+                                true);
+      nsToolkit::SwizzleMethods([NSEvent class], @selector(removeMonitor:),
+                                @selector(nsChildView_NSEvent_removeMonitor:), true);
+    }
 #endif
     gChildViewMethodsSwizzled = true;
   }
 
   mBounds = aRect;
 
   // Ensure that the toolkit is created.
   nsToolkit::GetToolkit();
@@ -4331,16 +4333,25 @@ NSEvent* gLastDragMouseDownEvent = nil;
 
 - (void)magnifyWithEvent:(NSEvent *)anEvent
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   if (!anEvent || !mGeckoChild)
     return;
 
+  /*
+   * In OS X 10.7.* (Lion), smart zoom events come through magnifyWithEvent,
+   * instead of smartMagnifyWithEvent. See bug 863841.
+   */
+  if ([ChildView isLionSmartMagnifyEvent: anEvent]) {
+    [self smartMagnifyWithEvent: anEvent];
+    return;
+  }
+
   nsAutoRetainCocoaObject kungFuDeathGrip(self);
 
   float deltaZ = [anEvent deltaZ];
 
   EventMessage msg;
   switch (mGestureState) {
   case eGestureState_StartGesture:
     msg = eMagnifyGestureStart;
@@ -4495,18 +4506,38 @@ NSEvent* gLastDragMouseDownEvent = nil;
   // Clear the gestures state.
   mGestureState = eGestureState_None;
   mCumulativeMagnification = 0.0;
   mCumulativeRotation = 0.0;
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
++ (BOOL)isLionSmartMagnifyEvent:(NSEvent*)anEvent
+{
+  /*
+   * On Lion, smart zoom events have type NSEventTypeGesture, subtype 0x16,
+   * whereas pinch zoom events have type NSEventTypeMagnify. So, use that to
+   * discriminate between the two. Smart zoom gestures do not call
+   * beginGestureWithEvent or endGestureWithEvent, so mGestureState is not
+   * changed. Documentation couldn't be found for the meaning of the subtype
+   * 0x16, but it will probably never change. See bug 863841.
+   */
+  return nsCocoaFeatures::OnLionOrLater() &&
+         !nsCocoaFeatures::OnMountainLionOrLater() &&
+         [anEvent type] == NSEventTypeGesture &&
+         [anEvent subtype] == 0x16;
+}
+
 - (bool)shouldConsiderStartingSwipeFromEvent:(NSEvent*)anEvent
 {
+  if (!nsCocoaFeatures::OnLionOrLater()) {
+    return false;
+  }
+
   // This method checks whether the AppleEnableSwipeNavigateWithScrolls global
   // preference is set.  If it isn't, fluid swipe tracking is disabled, and a
   // horizontal two-finger gesture is always a scroll (even in Safari).  This
   // preference can't (currently) be set from the Preferences UI -- only using
   // 'defaults write'.
   if (![NSEvent isSwipeTrackingFromScrollEventsEnabled]) {
     return false;
   }
--- a/widget/cocoa/nsCocoaFeatures.mm
+++ b/widget/cocoa/nsCocoaFeatures.mm
@@ -8,16 +8,17 @@
 // There are MOZ_ASSERTs for that.
 
 // The formula for the version integer based on OS X version 10.minor.bugfix is
 // 0x1000 + (minor << 4) + bugifix.  See AssembleVersion() below for major > 10.
 // Major version < 10 is not allowed.
 
 #define MAC_OS_X_VERSION_MASK      0x0000FFFF
 #define MAC_OS_X_VERSION_10_0_HEX  0x00001000
+#define MAC_OS_X_VERSION_10_6_HEX  0x00001060
 #define MAC_OS_X_VERSION_10_7_HEX  0x00001070
 #define MAC_OS_X_VERSION_10_8_HEX  0x00001080
 #define MAC_OS_X_VERSION_10_9_HEX  0x00001090
 #define MAC_OS_X_VERSION_10_10_HEX 0x000010A0
 #define MAC_OS_X_VERSION_10_11_HEX 0x000010B0
 
 #include "nsCocoaFeatures.h"
 #include "nsCocoaUtils.h"
@@ -77,22 +78,22 @@ void nsCocoaFeatures::GetSystemVersion(i
     }
 }
 
 int32_t nsCocoaFeatures::GetVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix)
 {
     int32_t osxVersion;
     if (aMajor < 10) {
         aMajor = 10;
-        NS_ERROR("Couldn't determine OS X version, assuming 10.7");
-        osxVersion = MAC_OS_X_VERSION_10_7_HEX;
-    } else if (aMinor < 7) {
-        aMinor = 7;
-        NS_ERROR("OS X version too old, assuming 10.7");
-        osxVersion = MAC_OS_X_VERSION_10_7_HEX;
+        NS_ERROR("Couldn't determine OS X version, assuming 10.6");
+        osxVersion = MAC_OS_X_VERSION_10_6_HEX;
+    } else if (aMinor < 6) {
+        aMinor = 6;
+        NS_ERROR("OS X version too old, assuming 10.6");
+        osxVersion = MAC_OS_X_VERSION_10_6_HEX;
     } else {
         MOZ_ASSERT(aMajor == 10); // For now, even though we're ready...
         MOZ_ASSERT(aMinor < 16);
         MOZ_ASSERT(aBugFix >= 0);
         MOZ_ASSERT(aBugFix < 16);
         osxVersion = AssembleVersion(aMajor, aMinor, aBugFix);
     }
     MOZ_ASSERT(aMajor == ExtractMajorVersion(osxVersion));
--- a/widget/cocoa/nsCocoaUtils.h
+++ b/widget/cocoa/nsCocoaUtils.h
@@ -20,21 +20,34 @@
 #include "mozilla/EventForwards.h"
 
 // Declare the backingScaleFactor method that we want to call
 // on NSView/Window/Screen objects, if they recognize it.
 @interface NSObject (BackingScaleFactorCategory)
 - (CGFloat)backingScaleFactor;
 @end
 
+// When building with a pre-10.7 SDK, NSEventPhase is not defined.
+#if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
+enum {
+  NSEventPhaseNone        = 0,
+  NSEventPhaseBegan       = 0x1 << 0,
+  NSEventPhaseStationary  = 0x1 << 1,
+  NSEventPhaseChanged     = 0x1 << 2,
+  NSEventPhaseEnded       = 0x1 << 3,
+  NSEventPhaseCancelled   = 0x1 << 4,
+};
+typedef NSUInteger NSEventPhase;
+#endif // #if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
+
 #if !defined(MAC_OS_X_VERSION_10_8) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8
 enum {
   NSEventPhaseMayBegin    = 0x1 << 5
 };
-#endif
+#endif // #if !defined(MAC_OS_X_VERSION_10_8) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8
 
 class nsIWidget;
 
 namespace mozilla {
 namespace gfx {
 class SourceSurface;
 } // namespace gfx
 } // namespace mozilla
@@ -81,16 +94,21 @@ private:
 // of the NSApplication class (in header files generated using class-dump).
 // Present in all versions of OS X from (at least) 10.2.8 through 10.5.
 - (void)_removeWindowFromCache:(NSWindow *)aWindow;
 
 // Send an event to the current Cocoa app-modal session.  Present in all
 // versions of OS X from (at least) 10.2.8 through 10.5.
 - (void)_modalSession:(NSModalSession)aSession sendEvent:(NSEvent *)theEvent;
 
+// Present (and documented) on OS X 10.6 and above.  Not present before 10.6.
+// This declaration needed to avoid compiler warnings when compiling on 10.5
+// and below (or using the 10.5 SDK and below).
+- (void)setHelpMenu:(NSMenu *)helpMenu;
+
 @end
 
 struct KeyBindingsCommand
 {
   SEL selector;
   id data;
 };
 
--- a/widget/cocoa/nsCocoaWindow.h
+++ b/widget/cocoa/nsCocoaWindow.h
@@ -15,16 +15,46 @@
 #include "nsPIWidgetCocoa.h"
 #include "nsCocoaUtils.h"
 
 class nsCocoaWindow;
 class nsChildView;
 class nsMenuBarX;
 @class ChildView;
 
+// If we are using an SDK older than 10.7, define bits we need that are missing
+// from it.
+#if !defined(MAC_OS_X_VERSION_10_7) || \
+    MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
+
+enum {
+    NSWindowAnimationBehaviorDefault = 0,
+    NSWindowAnimationBehaviorNone = 2,
+    NSWindowAnimationBehaviorDocumentWindow = 3,
+    NSWindowAnimationBehaviorUtilityWindow = 4,
+    NSWindowAnimationBehaviorAlertPanel = 5,
+    NSWindowCollectionBehaviorFullScreenPrimary = 128, // 1 << 7
+};
+
+typedef NSInteger NSWindowAnimationBehavior;
+
+@interface NSWindow (LionWindowFeatures)
+- (void)setAnimationBehavior:(NSWindowAnimationBehavior)newAnimationBehavior;
+- (void)toggleFullScreen:(id)sender;
+@end
+
+typedef struct NSEdgeInsets {
+    CGFloat top;
+    CGFloat left;
+    CGFloat bottom;
+    CGFloat right;
+} NSEdgeInsets;
+
+#endif
+
 typedef struct _nsCocoaWindowList {
   _nsCocoaWindowList() : prev(nullptr), window(nullptr) {}
   struct _nsCocoaWindowList *prev;
   nsCocoaWindow *window; // Weak
 } nsCocoaWindowList;
 
 // NSWindow subclass that is the base class for all of our own window classes.
 // Among other things, this class handles the storage of those settings that
@@ -147,17 +177,21 @@ typedef struct _nsCocoaWindowList {
 {
 }
 
 - (BOOL)canBecomeKeyWindow;
 - (BOOL)canBecomeMainWindow;
 
 @end
 
+#if defined( MAC_OS_X_VERSION_10_6 ) && ( MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 )
 @interface WindowDelegate : NSObject <NSWindowDelegate>
+#else
+@interface WindowDelegate : NSObject
+#endif
 {
   nsCocoaWindow* mGeckoWindow; // [WEAK] (we are owned by the window)
   // Used to avoid duplication when we send NS_ACTIVATE and
   // NS_DEACTIVATE to Gecko for toplevel widgets.  Starts out
   // false.
   bool mToplevelActiveState;
   BOOL mHasEverBeenZoomed;
 }
@@ -407,18 +441,19 @@ protected:
   bool                 mInFullScreenMode;
   bool                 mInFullScreenTransition; // true from the request to enter/exit fullscreen
                                                 // (MakeFullScreen() call) to EnteredFullScreen()
   bool                 mModal;
   bool                 mFakeModal;
 
   // Only true on 10.7+ if SetShowsFullScreenButton(true) is called.
   bool                 mSupportsNativeFullScreen;
-  // Whether we are currently using native fullscreen. It could be false because
-  // we are in the DOM fullscreen where we do not use the native fullscreen.
+  // Whether we are currently using Lion native fullscreen. It could be
+  // false either because we are not on Lion, or we are in the DOM
+  // fullscreen where we do not use the native fullscreen.
   bool                 mInNativeFullScreenMode;
 
   bool                 mIsAnimationSuppressed;
 
   bool                 mInReportMoveEvent; // true if in a call to ReportMoveEvent().
   bool                 mInResize; // true if in a call to DoResize().
 
   int32_t              mNumModalDescendents;
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -3258,17 +3258,17 @@ static const NSString* kStateCollectionB
   // text at all is selected.  (This always happens when accessibility is off.
   // It doesn't happen in Firefox releases because Apple has (on OS X 10.7)
   // special-cased the handling of apps whose CFBundleIdentifier is
   // org.mozilla.firefox.)
   //
   // We work around this problem by only returning AXChildren that are
   // mozAccessible object or are one of the titlebar's buttons (which
   // instantiate subclasses of NSButtonCell).
-  if ([retval isKindOfClass:[NSArray class]] &&
+  if (nsCocoaFeatures::OnLionOrLater() && [retval isKindOfClass:[NSArray class]] &&
       [attribute isEqualToString:@"AXChildren"]) {
     NSMutableArray *holder = [NSMutableArray arrayWithCapacity:10];
     [holder addObjectsFromArray:(NSArray *)retval];
     NSUInteger count = [holder count];
     for (NSInteger i = count - 1; i >= 0; --i) {
       id item = [holder objectAtIndex:i];
       // Remove anything from holder that isn't one of the titlebar's buttons
       // (which instantiate subclasses of NSButtonCell) or a mozAccessible
@@ -3279,16 +3279,32 @@ static const NSString* kStateCollectionB
       }
     }
     retval = [NSArray arrayWithArray:holder];
   }
 
   return retval;
 }
 
+// If we were built on OS X 10.6 or with the 10.6 SDK and are running on Lion,
+// the OS (specifically -[NSWindow sendEvent:]) won't send NSEventTypeGesture
+// events to -[ChildView magnifyWithEvent:] as it should.  The following code
+// gets around this.  See bug 863841.
+#if !defined( MAC_OS_X_VERSION_10_7 ) || \
+    ( MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 )
+- (void)sendEvent:(NSEvent *)anEvent
+{
+  if ([ChildView isLionSmartMagnifyEvent: anEvent]) {
+    [[self mainChildView] magnifyWithEvent:anEvent];
+    return;
+  }
+  [super sendEvent:anEvent];
+}
+#endif
+
 @end
 
 // This class allows us to exercise control over the window's title bar. This
 // allows for a "unified toolbar" look without having to extend the content
 // area into the title bar. It works like this:
 // 1) We set the window's style to textured.
 // 2) Because of this, the background color applies to the entire window, including
 //     the titlebar area. For normal textured windows, the default pattern is a 
@@ -3340,17 +3356,17 @@ static const NSString* kStateCollectionB
 
     mUnifiedToolbarHeight = 22.0f;
     mWindowButtonsRect = NSZeroRect;
     mFullScreenButtonRect = NSZeroRect;
 
     // setBottomCornerRounded: is a private API call, so we check to make sure
     // we respond to it just in case.
     if ([self respondsToSelector:@selector(setBottomCornerRounded:)])
-      [self setBottomCornerRounded:YES];
+      [self setBottomCornerRounded:nsCocoaFeatures::OnLionOrLater()];
 
     [self setAutorecalculatesContentBorderThickness:NO forEdge:NSMaxYEdge];
     [self setContentBorderThickness:0.0f forEdge:NSMaxYEdge];
   }
   return self;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
@@ -3636,21 +3652,24 @@ static const NSString* kStateCollectionB
 }
 
 static void
 DrawNativeTitlebar(CGContextRef aContext, CGRect aTitlebarRect,
                    CGFloat aUnifiedToolbarHeight, BOOL aIsMain)
 {
   nsNativeThemeCocoa::DrawNativeTitlebar(aContext, aTitlebarRect, aUnifiedToolbarHeight, aIsMain, NO);
 
-  // The call to CUIDraw doesn't draw the top pixel strip at some window widths.
-  // We don't want to have a flickering transparent line, so we overdraw it.
-  CGContextSetRGBFillColor(aContext, 0.95, 0.95, 0.95, 1);
-  CGContextFillRect(aContext, CGRectMake(0, CGRectGetMaxY(aTitlebarRect) - 1,
+  if (nsCocoaFeatures::OnLionOrLater()) {
+    // On Lion the call to CUIDraw doesn't draw the top pixel strip at some
+    // window widths. We don't want to have a flickering transparent line, so
+    // we overdraw it.
+    CGContextSetRGBFillColor(aContext, 0.95, 0.95, 0.95, 1);
+    CGContextFillRect(aContext, CGRectMake(0, CGRectGetMaxY(aTitlebarRect) - 1,
                                            aTitlebarRect.size.width, 1));
+  }
 }
 
 // Pattern draw callback for standard titlebar gradients and solid titlebar colors
 static void
 TitlebarDrawCallback(void* aInfo, CGContextRef aContext)
 {
   ToolbarWindow *window = (ToolbarWindow*)aInfo;
   if (![window drawsContentsIntoWindowFrame]) {
--- a/widget/cocoa/nsLookAndFeel.mm
+++ b/widget/cocoa/nsLookAndFeel.mm
@@ -341,17 +341,31 @@ nsLookAndFeel::GetIntImpl(IntID aID, int
     case eIntID_SkipNavigatingDisabledMenuItem:
       aResult = 1;
       break;
     case eIntID_DragThresholdX:
     case eIntID_DragThresholdY:
       aResult = 4;
       break;
     case eIntID_ScrollArrowStyle:
-      aResult = eScrollArrow_None;
+      if (nsCocoaFeatures::OnLionOrLater()) {
+        // OS X Lion's scrollbars have no arrows
+        aResult = eScrollArrow_None;
+      } else {
+        NSString *buttonPlacement = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleScrollBarVariant"];
+        if ([buttonPlacement isEqualToString:@"Single"]) {
+          aResult = eScrollArrowStyle_Single;
+        } else if ([buttonPlacement isEqualToString:@"DoubleMin"]) {
+          aResult = eScrollArrowStyle_BothAtTop;
+        } else if ([buttonPlacement isEqualToString:@"DoubleBoth"]) {
+          aResult = eScrollArrowStyle_BothAtEachEnd;
+        } else {
+          aResult = eScrollArrowStyle_BothAtBottom; // The default is BothAtBottom.
+        }
+      }
       break;
     case eIntID_ScrollSliderStyle:
       aResult = eScrollThumbStyle_Proportional;
       break;
     case eIntID_UseOverlayScrollbars:
       if (!mUseOverlayScrollbarsCached) {
         mUseOverlayScrollbars = SystemWantsOverlayScrollbars() ? 1 : 0;
         mUseOverlayScrollbarsCached = true;
@@ -506,17 +520,17 @@ bool nsLookAndFeel::UseOverlayScrollbars
 bool nsLookAndFeel::SystemWantsOverlayScrollbars()
 {
   return ([NSScroller respondsToSelector:@selector(preferredScrollerStyle)] &&
           [NSScroller preferredScrollerStyle] == mozNSScrollerStyleOverlay);
 }
 
 bool nsLookAndFeel::AllowOverlayScrollbarsOverlap()
 {
-  return UseOverlayScrollbars();
+  return (UseOverlayScrollbars() && nsCocoaFeatures::OnMountainLionOrLater());
 }
 
 bool
 nsLookAndFeel::GetFontImpl(FontID aID, nsString &aFontName,
                            gfxFontStyle &aFontStyle,
                            float aDevPixPerCSSPixel)
 {
     NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
--- a/widget/cocoa/nsMenuX.h
+++ b/widget/cocoa/nsMenuX.h
@@ -18,17 +18,21 @@
 
 class nsMenuX;
 class nsMenuItemIconX;
 class nsMenuItemX;
 class nsIWidget;
 
 // MenuDelegate is used to receive Cocoa notifications for setting
 // up carbon events. Protocol is defined as of 10.6 SDK.
+#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6)
 @interface MenuDelegate : NSObject < NSMenuDelegate >
+#else
+@interface MenuDelegate : NSObject
+#endif
 {
   nsMenuX* mGeckoMenu; // weak ref
 }
 - (id)initWithGeckoMenu:(nsMenuX*)geckoMenu;
 @end
 
 // Once instantiated, this object lives until its DOM node or its parent window is destroyed.
 // Do not hold references to this, they can become invalid any time the DOM node can be destroyed.
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -465,16 +465,18 @@ static NSWindow* NativeWindowForFrame(ns
 }
 
 static NSSize
 WindowButtonsSize(nsIFrame* aFrame)
 {
   NSWindow* window = NativeWindowForFrame(aFrame);
   if (!window) {
     // Return fallback values.
+    if (!nsCocoaFeatures::OnLionOrLater())
+      return NSMakeSize(57, 16);
     return NSMakeSize(54, 16);
   }
 
   NSRect buttonBox = NSZeroRect;
   NSButton* closeButton = [window standardWindowButton:NSWindowCloseButton];
   if (closeButton) {
     buttonBox = NSUnionRect(buttonBox, [closeButton frame]);
   }
@@ -1108,17 +1110,18 @@ nsNativeThemeCocoa::DrawSearchField(CGCo
                        IsFrameRTL(aFrame));
 
   [cell setContext:nullptr];
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 static const NSSize kCheckmarkSize = NSMakeSize(11, 11);
-static const NSSize kMenuarrowSize = NSMakeSize(9, 10);
+static const NSSize kMenuarrowSize = nsCocoaFeatures::OnLionOrLater() ?
+                                     NSMakeSize(9, 10) : NSMakeSize(8, 10);
 static const NSSize kMenuScrollArrowSize = NSMakeSize(10, 8);
 static NSString* kCheckmarkImage = @"MenuOnState";
 static NSString* kMenuarrowRightImage = @"MenuSubmenu";
 static NSString* kMenuarrowLeftImage = @"MenuSubmenuLeft";
 static NSString* kMenuDownScrollArrowImage = @"MenuScrollDown";
 static NSString* kMenuUpScrollArrowImage = @"MenuScrollUp";
 static const CGFloat kMenuIconIndent = 6.0f;
 
@@ -1136,33 +1139,49 @@ nsNativeThemeCocoa::DrawMenuIcon(CGConte
   CGFloat paddingStartX = std::min(paddingX, kMenuIconIndent);
   CGFloat paddingEndX = std::max(CGFloat(0.0), paddingX - kMenuIconIndent);
   CGRect drawRect = CGRectMake(
     aRect.origin.x + (aCenterHorizontally ? ceil(paddingX / 2) :
                       IsFrameRTL(aFrame) ? paddingEndX : paddingStartX),
     aRect.origin.y + ceil(paddingY / 2),
     aIconSize.width, aIconSize.height);
 
-  NSString* state = IsDisabled(aFrame, inState) ? @"disabled" :
-    (CheckBooleanAttr(aFrame, nsGkAtoms::menuactive) ? @"pressed" : @"normal");
+  BOOL isDisabled = IsDisabled(aFrame, inState);
+  BOOL isActive = CheckBooleanAttr(aFrame, nsGkAtoms::menuactive);
+
+  // On 10.6 and at least on 10.7.0, Apple doesn’t seem to have implemented all
+  // keys and values used on 10.7.5 and later. We can however draw menu icons
+  // on earlier OS versions by using different keys/values.
+  BOOL otherKeysAndValues = !nsCocoaFeatures::IsAtLeastVersion(10,7,5);
+
+  // 2 states combined with 2 different backgroundTypeKeys on earlier versions.
+  NSString* state = isDisabled ? @"disabled" :
+    (isActive && !otherKeysAndValues) ? @"pressed" : @"normal";
+  NSString* backgroundTypeKey = !otherKeysAndValues ? @"kCUIBackgroundTypeMenu" :
+    !isDisabled && isActive ? @"backgroundTypeDark" : @"backgroundTypeLight";
 
   NSString* imageName = aImageName;
   if (!nsCocoaFeatures::OnElCapitanOrLater()) {
     // Pre-10.11, image names are prefixed with "image."
     imageName = [@"image." stringByAppendingString:aImageName];
   }
 
+  NSMutableArray* keys = [NSMutableArray arrayWithObjects:@"backgroundTypeKey",
+    @"imageNameKey", @"state", @"widget", @"is.flipped", nil];
+  NSMutableArray* values = [NSMutableArray arrayWithObjects: backgroundTypeKey,
+    imageName, state, @"image", [NSNumber numberWithBool:YES], nil];
+
+  if (otherKeysAndValues) { // Earlier versions used one more key-value pair.
+    [keys insertObject:@"imageIsGrayscaleKey" atIndex:1];
+    [values insertObject:[NSNumber numberWithBool:YES] atIndex:1];
+  }
+
   RenderWithCoreUI(drawRect, cgContext,
-          [NSDictionary dictionaryWithObjectsAndKeys:
-            @"kCUIBackgroundTypeMenu", @"backgroundTypeKey",
-            aImageName, @"imageNameKey",
-            state, @"state",
-            @"image", @"widget",
-            [NSNumber numberWithBool:YES], @"is.flipped",
-            nil]);
+                  [NSDictionary dictionaryWithObjects:values
+                                              forKeys:keys]);
 
 #if DRAW_IN_FRAME_DEBUG
   CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
   CGContextFillRect(cgContext, drawRect);
 #endif
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
@@ -2048,16 +2067,23 @@ nsNativeThemeCocoa::DrawSegment(CGContex
             (isPressed ? @"pressed" : (isActive ? @"normal" : @"inactive")), @"state",
             [NSNumber numberWithBool:isFocused], @"focus",
             CUIControlSizeForCocoaSize(controlSize), @"size",
             [NSNumber numberWithBool:YES], @"is.flipped",
             @"up", @"direction",
             nil]);
 }
 
+static inline UInt8
+ConvertToPressState(EventStates aButtonState, UInt8 aPressState)
+{
+  // If the button is pressed, return the press state passed in. Otherwise, return 0.
+  return aButtonState.HasAllStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_HOVER) ? aPressState : 0;
+}
+
 void 
 nsNativeThemeCocoa::GetScrollbarPressStates(nsIFrame* aFrame,
                                             EventStates aButtonStates[])
 {
   static nsIContent::AttrValuesArray attributeValues[] = {
     &nsGkAtoms::scrollbarUpTop,
     &nsGkAtoms::scrollbarDownTop,
     &nsGkAtoms::scrollbarUpBottom,
@@ -2129,16 +2155,40 @@ nsNativeThemeCocoa::GetScrollbarDrawInfo
   }
   else if (longSideLength < (isSmall ? MIN_SMALL_SCROLLBAR_SIZE : MIN_SCROLLBAR_SIZE)) {
     aTdi.enableState = kThemeTrackNothingToScroll;
     return;
   }
 
   aTdi.trackInfo.scrollbar.pressState = 0;
 
+  // Only go get these scrollbar button states if we need it. For example,
+  // there's no reason to look up scrollbar button states when we're only
+  // creating a TrackDrawInfo to determine the size of the thumb. There's
+  // also no reason to do this on Lion or later, whose scrollbars have no
+  // arrow buttons.
+  if (aShouldGetButtonStates && !nsCocoaFeatures::OnLionOrLater()) {
+    EventStates buttonStates[4];
+    GetScrollbarPressStates(aFrame, buttonStates);
+    NSString *buttonPlacement = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleScrollBarVariant"];
+    // It seems that unless all four buttons are showing, kThemeTopOutsideArrowPressed is the correct constant for
+    // the up scrollbar button.
+    if ([buttonPlacement isEqualToString:@"DoubleBoth"]) {
+      aTdi.trackInfo.scrollbar.pressState = ConvertToPressState(buttonStates[0], kThemeTopOutsideArrowPressed) |
+                                            ConvertToPressState(buttonStates[1], kThemeTopInsideArrowPressed) |
+                                            ConvertToPressState(buttonStates[2], kThemeBottomInsideArrowPressed) |
+                                            ConvertToPressState(buttonStates[3], kThemeBottomOutsideArrowPressed);
+    } else {
+      aTdi.trackInfo.scrollbar.pressState = ConvertToPressState(buttonStates[0], kThemeTopOutsideArrowPressed) |
+                                            ConvertToPressState(buttonStates[1], kThemeBottomOutsideArrowPressed) |
+                                            ConvertToPressState(buttonStates[2], kThemeTopOutsideArrowPressed) |
+                                            ConvertToPressState(buttonStates[3], kThemeBottomOutsideArrowPressed);
+    }
+  }
+
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 static void
 RenderScrollbar(CGContextRef cgContext, const HIRect& aRenderRect, void* aData)
 {
   HIThemeTrackDrawInfo* tdi = (HIThemeTrackDrawInfo*)aData;
   HIThemeDrawTrack(tdi, NULL, cgContext, HITHEME_ORIENTATION);
@@ -2336,17 +2386,17 @@ DrawVibrancyBackground(CGContextRef cgCo
     [NSGraphicsContext restoreGraphicsState];
     [NSGraphicsContext setCurrentContext:savedContext];
   }
 }
 
 static bool
 ScrollbarTrackAndThumbDrawSeparately()
 {
-  return nsLookAndFeel::UseOverlayScrollbars();
+  return nsLookAndFeel::UseOverlayScrollbars() || nsCocoaFeatures::OnLionOrLater();
 }
 
 bool
 nsNativeThemeCocoa::IsParentScrollbarRolledOver(nsIFrame* aFrame)
 {
   nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame);
   return nsLookAndFeel::UseOverlayScrollbars()
     ? CheckBooleanAttr(scrollbarFrame, nsGkAtoms::hover)
@@ -2827,17 +2877,17 @@ nsNativeThemeCocoa::DrawWidgetBackground
     case NS_THEME_SCROLLBARTHUMB_VERTICAL:
     case NS_THEME_SCROLLBARTHUMB_HORIZONTAL:
       if (ScrollbarTrackAndThumbDrawSeparately()) {
         BOOL isOverlay = nsLookAndFeel::UseOverlayScrollbars();
         BOOL isHorizontal = (aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL);
         BOOL isRolledOver = IsParentScrollbarRolledOver(aFrame);
         nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame);
         bool isSmall = (scrollbarFrame && scrollbarFrame->StyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL);
-        if (isOverlay && !isRolledOver) {
+        if (isOverlay && (!nsCocoaFeatures::OnMountainLionOrLater() || !isRolledOver)) {
           if (isHorizontal) {
             macRect.origin.y += 4;
             macRect.size.height -= 4;
           } else {
             if (aFrame->StyleVisibility()->mDirection !=
                 NS_STYLE_DIRECTION_RTL) {
               macRect.origin.x += 4;
             }
@@ -2878,16 +2928,31 @@ nsNativeThemeCocoa::DrawWidgetBackground
     case NS_THEME_SCROLLBARTRACK_HORIZONTAL:
     case NS_THEME_SCROLLBARTRACK_VERTICAL:
       if (ScrollbarTrackAndThumbDrawSeparately()) {
         BOOL isOverlay = nsLookAndFeel::UseOverlayScrollbars();
         if (!isOverlay || IsParentScrollbarRolledOver(aFrame)) {
           BOOL isHorizontal = (aWidgetType == NS_THEME_SCROLLBARTRACK_HORIZONTAL);
           nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame);
           bool isSmall = (scrollbarFrame && scrollbarFrame->StyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL);
+          if (isOverlay && !nsCocoaFeatures::OnMountainLionOrLater()) {
+            // On OSX 10.7, scrollbars don't grow when hovered.
+            // The adjustments below were obtained by trial and error.
+            if (isHorizontal) {
+              macRect.origin.y += 2.0;
+            } else {
+              if (aFrame->StyleVisibility()->mDirection !=
+                    NS_STYLE_DIRECTION_RTL) {
+                macRect.origin.x += 3.0;
+              } else {
+                macRect.origin.x -= 1.0;
+              }
+            }
+          }
+
           const BOOL isOnTopOfDarkBackground = IsDarkBackground(aFrame);
           RenderWithCoreUILegacy(macRect, cgContext,
                   [NSDictionary dictionaryWithObjectsAndKeys:
                     (isOverlay ? @"kCUIWidgetOverlayScrollBar" : @"scrollbar"), @"widget",
                     (isSmall ? @"small" : @"regular"), @"size",
                     (isHorizontal ? @"kCUIOrientHorizontal" : @"kCUIOrientVertical"), @"kCUIOrientationKey",
                     (isOnTopOfDarkBackground ? @"kCUIVariantWhite" : @""), @"kCUIVariantKey",
                     [NSNumber numberWithBool:YES], @"noindicator",
@@ -3095,16 +3160,37 @@ nsNativeThemeCocoa::GetWidgetBorder(nsDe
       aResult->SizeTo(frameOutset, frameOutset, frameOutset, frameOutset);
       break;
     }
 
     case NS_THEME_SCROLLBARTRACK_HORIZONTAL:
     case NS_THEME_SCROLLBARTRACK_VERTICAL:
     {
       bool isHorizontal = (aWidgetType == NS_THEME_SCROLLBARTRACK_HORIZONTAL);
+
+      // On Lion and later, scrollbars have no arrows.
+      if (!nsCocoaFeatures::OnLionOrLater()) {
+        // There's only an endcap to worry about when both arrows are on the bottom
+        NSString *buttonPlacement = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleScrollBarVariant"];
+        if (!buttonPlacement || [buttonPlacement isEqualToString:@"DoubleMax"]) {
+          nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame);
+          if (!scrollbarFrame) return NS_ERROR_FAILURE;
+          bool isSmall = (scrollbarFrame->StyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL);
+
+          // There isn't a metric for this, so just hardcode a best guess at the value.
+          // This value is even less exact due to the fact that the endcap is partially concave.
+          int32_t endcapSize = isSmall ? 5 : 6;
+
+          if (isHorizontal)
+            aResult->SizeTo(0, 0, 0, endcapSize);
+          else
+            aResult->SizeTo(endcapSize, 0, 0, 0);
+        }
+      }
+
       if (nsLookAndFeel::UseOverlayScrollbars()) {
         if (isHorizontal) {
           aResult->SizeTo(2, 1, 1, 1);
         } else {
           aResult->SizeTo(1, 1, 1, 2);
         }
       }
 
--- a/widget/cocoa/nsNativeThemeColors.h
+++ b/widget/cocoa/nsNativeThemeColors.h
@@ -10,16 +10,24 @@
 #import <Cocoa/Cocoa.h>
 
 enum ColorName {
   toolbarTopBorderGrey,
   toolbarFillGrey,
   toolbarBottomBorderGrey,
 };
 
+static const int sSnowLeopardThemeColors[][2] = {
+  /* { active window, inactive window } */
+  // toolbar:
+  { 0xD0, 0xF1 }, // top separator line
+  { 0xA7, 0xD8 }, // fill color
+  { 0x51, 0x99 }, // bottom separator line
+};
+
 static const int sLionThemeColors[][2] = {
   /* { active window, inactive window } */
   // toolbar:
   { 0xD0, 0xF0 }, // top separator line
   { 0xB2, 0xE1 }, // fill color
   { 0x59, 0x87 }, // bottom separator line
 };
 
@@ -31,17 +39,21 @@ static const int sYosemiteThemeColors[][
   { 0xB3, 0xD1 }, // bottom separator line
 };
 
 __attribute__((unused))
 static int NativeGreyColorAsInt(ColorName name, BOOL isMain)
 {
   if (nsCocoaFeatures::OnYosemiteOrLater())
     return sYosemiteThemeColors[name][isMain ? 0 : 1];
-  return sLionThemeColors[name][isMain ? 0 : 1];
+
+  if (nsCocoaFeatures::OnLionOrLater())
+    return sLionThemeColors[name][isMain ? 0 : 1];
+
+  return sSnowLeopardThemeColors[name][isMain ? 0 : 1];
 }
 
 __attribute__((unused))
 static float NativeGreyColorAsFloat(ColorName name, BOOL isMain)
 {
   return NativeGreyColorAsInt(name, isMain) / 255.0f;
 }