Merge the last PGO-green inbound changeset to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 31 Jul 2012 22:11:13 -0400
changeset 101024 582d4c67b3a7c68ce2b371704d3d9057575beb0c
parent 100965 02346e2e71564af46bc6a9e382dab9e4434a74f1 (current diff)
parent 101023 3ab53aa585144e4c5a7f5a55003c86fcbe9347c6 (diff)
child 101027 e5000bb5fa0380000530ef64cc42f32aae7b5e7a
push id23206
push userryanvm@gmail.com
push dateWed, 01 Aug 2012 02:11:21 +0000
treeherdermozilla-central@582d4c67b3a7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone17.0a1
first release with
nightly linux32
582d4c67b3a7 / 17.0a1 / 20120801030520 / files
nightly linux64
582d4c67b3a7 / 17.0a1 / 20120801030520 / files
nightly mac
582d4c67b3a7 / 17.0a1 / 20120801030520 / files
nightly win32
582d4c67b3a7 / 17.0a1 / 20120801030520 / files
nightly win64
582d4c67b3a7 / 17.0a1 / 20120801030520 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge the last PGO-green inbound changeset to m-c.
gfx/thebes/nsCoreAnimationSupport.h
gfx/thebes/nsCoreAnimationSupport.mm
gfx/thebes/nsIOSurface.h
layout/reftests/svg/viewBox-and-pattern-01.svg
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -80,17 +80,18 @@ DocAccessible::
                   nsIPresShell* aPresShell) :
   HyperTextAccessibleWrap(aRootContent, this),
   mDocument(aDocument), mScrollPositionChangedTicks(0),
   mLoadState(eTreeConstructionPending), mLoadEventType(0),
   mVirtualCursor(nullptr),
   mPresShell(aPresShell)
 {
   mFlags |= eDocAccessible;
-  mPresShell->SetAccDocument(this);
+  if (mPresShell)
+    mPresShell->SetAccDocument(this);
 
   mDependentIDsHash.Init();
   // XXX aaronl should we use an algorithm for the initial cache size?
   mAccessibleCache.Init(kDefaultCacheSize);
   mNodeToAccessibleMap.Init(kDefaultCacheSize);
 
   // If this is a XUL Document, it should not implement nsHyperText
   if (mDocument && mDocument->IsXUL())
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -1,16 +1,18 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 MOZ_APP_BASENAME=B2G
 MOZ_APP_VENDOR=Mozilla
 
 MOZ_APP_VERSION=17.0a1
+
+MOZ_UA_OS_AGNOSTIC=1
 MOZ_APP_UA_NAME=Firefox
 
 MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
 MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
 # MOZ_APP_DISPLAYNAME is set by branding/configure.sh
 
 MOZ_SAFE_BROWSING=
 MOZ_SERVICES_SYNC=1
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2489,174 +2489,218 @@ function BrowserOnAboutPageLoad(document
     if (!ss.canRestoreLastSession)
       document.getElementById("launcher").removeAttribute("session");
   }
 }
 
 /**
  * Handle command events bubbling up from error page content
  */
-function BrowserOnClick(event) {
-    if (!event.isTrusted || // Don't trust synthetic events
-        event.button == 2 || event.target.localName != "button")
+let BrowserOnClick = {
+  handleEvent: function BrowserOnClick_handleEvent(aEvent) {
+    if (!aEvent.isTrusted || // Don't trust synthetic events
+        aEvent.button == 2 || aEvent.target.localName != "button") {
       return;
-
-    var ot = event.originalTarget;
-    var ownerDoc = ot.ownerDocument;
+    }
+
+    let originalTarget = aEvent.originalTarget;
+    let ownerDoc = originalTarget.ownerDocument;
 
     // If the event came from an ssl error page, it is probably either the "Add
     // Exception…" or "Get me out of here!" button
     if (/^about:certerror/.test(ownerDoc.documentURI)) {
-      if (ot == ownerDoc.getElementById('exceptionDialogButton')) {
-        var params = { exceptionAdded : false, handlePrivateBrowsing : true };
+      this.onAboutCertError(originalTarget, ownerDoc);
+    }
+    else if (/^about:blocked/.test(ownerDoc.documentURI)) {
+      this.onAboutBlocked(originalTarget, ownerDoc);
+    }
+    else if (/^about:home$/i.test(ownerDoc.documentURI)) {
+      this.onAboutHome(originalTarget, ownerDoc);
+    }
+  },
+
+  onAboutCertError: function BrowserOnClick_onAboutCertError(aTargetElm, aOwnerDoc) {
+    let elmId = aTargetElm.getAttribute("id");
+
+    switch (elmId) {
+      case "exceptionDialogButton":
+        let params = { exceptionAdded : false, handlePrivateBrowsing : true };
 
         try {
-          switch (gPrefService.getIntPref("browser.ssl_override_behavior")) {
+          switch (Services.prefs.getIntPref("browser.ssl_override_behavior")) {
             case 2 : // Pre-fetch & pre-populate
               params.prefetchCert = true;
             case 1 : // Pre-populate
-              params.location = ownerDoc.location.href;
+              params.location = aOwnerDoc.location.href;
           }
         } catch (e) {
           Components.utils.reportError("Couldn't get ssl_override pref: " + e);
         }
 
         window.openDialog('chrome://pippki/content/exceptionDialog.xul',
                           '','chrome,centerscreen,modal', params);
 
         // If the user added the exception cert, attempt to reload the page
-        if (params.exceptionAdded)
-          ownerDoc.location.reload();
-      }
-      else if (ot == ownerDoc.getElementById('getMeOutOfHereButton')) {
+        if (params.exceptionAdded) {
+          aOwnerDoc.location.reload();
+        }
+        break;
+
+      case "getMeOutOfHereButton":
         getMeOutOfHere();
-      }
-    }
-    else if (/^about:blocked/.test(ownerDoc.documentURI)) {
-      // The event came from a button on a malware/phishing block page
-      // First check whether it's malware or phishing, so that we can
-      // use the right strings/links
-      var isMalware = /e=malwareBlocked/.test(ownerDoc.documentURI);
-
-      if (ot == ownerDoc.getElementById('getMeOutButton')) {
+        break;
+    }
+  },
+
+  onAboutBlocked: function BrowserOnClick_onAboutBlocked(aTargetElm, aOwnerDoc) {
+    let elmId = aTargetElm.getAttribute("id");
+
+    // The event came from a button on a malware/phishing block page
+    // First check whether it's malware or phishing, so that we can
+    // use the right strings/links
+    let isMalware = /e=malwareBlocked/.test(aOwnerDoc.documentURI);
+
+    switch (elmId) {
+      case "getMeOutButton":
         getMeOutOfHere();
-      }
-      else if (ot == ownerDoc.getElementById('reportButton')) {
+        break;
+
+      case "reportButton":
         // This is the "Why is this site blocked" button.  For malware,
         // we can fetch a site-specific report, for phishing, we redirect
         // to the generic page describing phishing protection.
 
         if (isMalware) {
           // Get the stop badware "why is this blocked" report url,
           // append the current url, and go there.
           try {
             let reportURL = formatURL("browser.safebrowsing.malware.reportURL", true);
-            reportURL += ownerDoc.location.href;
+            reportURL += aOwnerDoc.location.href;
             content.location = reportURL;
           } catch (e) {
             Components.utils.reportError("Couldn't get malware report URL: " + e);
           }
         }
         else { // It's a phishing site, not malware
           try {
             content.location = formatURL("browser.safebrowsing.warning.infoURL", true);
           } catch (e) {
             Components.utils.reportError("Couldn't get phishing info URL: " + e);
           }
         }
-      }
-      else if (ot == ownerDoc.getElementById('ignoreWarningButton')) {
-        // Allow users to override and continue through to the site,
-        // but add a notify bar as a reminder, so that they don't lose
-        // track after, e.g., tab switching.
-        gBrowser.loadURIWithFlags(content.location.href,
-                                  nsIWebNavigation.LOAD_FLAGS_BYPASS_CLASSIFIER,
-                                  null, null, null);
-
-        Services.perms.add(makeURI(content.location.href), "safe-browsing",
-                           Ci.nsIPermissionManager.ALLOW_ACTION,
-                           Ci.nsIPermissionManager.EXPIRE_SESSION);
-
-        let buttons = [{
-          label: gNavigatorBundle.getString("safebrowsing.getMeOutOfHereButton.label"),
-          accessKey: gNavigatorBundle.getString("safebrowsing.getMeOutOfHereButton.accessKey"),
-          callback: function() { getMeOutOfHere(); }
-        }];
-
-        let title;
-        if (isMalware) {
-          title = gNavigatorBundle.getString("safebrowsing.reportedAttackSite");
-          buttons[1] = {
-            label: gNavigatorBundle.getString("safebrowsing.notAnAttackButton.label"),
-            accessKey: gNavigatorBundle.getString("safebrowsing.notAnAttackButton.accessKey"),
-            callback: function() {
-              openUILinkIn(gSafeBrowsing.getReportURL('MalwareError'), 'tab');
-            }
-          };
-        } else {
-          title = gNavigatorBundle.getString("safebrowsing.reportedWebForgery");
-          buttons[1] = {
-            label: gNavigatorBundle.getString("safebrowsing.notAForgeryButton.label"),
-            accessKey: gNavigatorBundle.getString("safebrowsing.notAForgeryButton.accessKey"),
-            callback: function() {
-              openUILinkIn(gSafeBrowsing.getReportURL('Error'), 'tab');
-            }
-          };
+        break;
+
+      case "ignoreWarningButton":
+        this.ignoreWarningButton(isMalware);
+        break;
+    }
+  },
+
+  ignoreWarningButton: function BrowserOnClick_ignoreWarningButton(aIsMalware) {
+    // Allow users to override and continue through to the site,
+    // but add a notify bar as a reminder, so that they don't lose
+    // track after, e.g., tab switching.
+    gBrowser.loadURIWithFlags(content.location.href,
+                              nsIWebNavigation.LOAD_FLAGS_BYPASS_CLASSIFIER,
+                              null, null, null);
+
+    Services.perms.add(makeURI(content.location.href), "safe-browsing",
+                       Ci.nsIPermissionManager.ALLOW_ACTION,
+                       Ci.nsIPermissionManager.EXPIRE_SESSION);
+
+    let buttons = [{
+      label: gNavigatorBundle.getString("safebrowsing.getMeOutOfHereButton.label"),
+      accessKey: gNavigatorBundle.getString("safebrowsing.getMeOutOfHereButton.accessKey"),
+      callback: function() { getMeOutOfHere(); }
+    }];
+
+    let title;
+    if (aIsMalware) {
+      title = gNavigatorBundle.getString("safebrowsing.reportedAttackSite");
+      buttons[1] = {
+        label: gNavigatorBundle.getString("safebrowsing.notAnAttackButton.label"),
+        accessKey: gNavigatorBundle.getString("safebrowsing.notAnAttackButton.accessKey"),
+        callback: function() {
+          openUILinkIn(gSafeBrowsing.getReportURL('MalwareError'), 'tab');
         }
-
-        let notificationBox = gBrowser.getNotificationBox();
-        let value = "blocked-badware-page";
-
-        let previousNotification = notificationBox.getNotificationWithValue(value);
-        if (previousNotification)
-          notificationBox.removeNotification(previousNotification);
-
-        let notification = notificationBox.appendNotification(
-          title,
-          value,
-          "chrome://global/skin/icons/blacklist_favicon.png",
-          notificationBox.PRIORITY_CRITICAL_HIGH,
-          buttons
-        );
-        // Persist the notification until the user removes so it
-        // doesn't get removed on redirects.
-        notification.persistence = -1;
-      }
-    }
-    else if (/^about:home$/i.test(ownerDoc.documentURI)) {
-      if (ot == ownerDoc.getElementById("restorePreviousSession")) {
+      };
+    } else {
+      title = gNavigatorBundle.getString("safebrowsing.reportedWebForgery");
+      buttons[1] = {
+        label: gNavigatorBundle.getString("safebrowsing.notAForgeryButton.label"),
+        accessKey: gNavigatorBundle.getString("safebrowsing.notAForgeryButton.accessKey"),
+        callback: function() {
+          openUILinkIn(gSafeBrowsing.getReportURL('Error'), 'tab');
+        }
+      };
+    }
+
+    let notificationBox = gBrowser.getNotificationBox();
+    let value = "blocked-badware-page";
+
+    let previousNotification = notificationBox.getNotificationWithValue(value);
+    if (previousNotification) {
+      notificationBox.removeNotification(previousNotification);
+    }
+
+    let notification = notificationBox.appendNotification(
+      title,
+      value,
+      "chrome://global/skin/icons/blacklist_favicon.png",
+      notificationBox.PRIORITY_CRITICAL_HIGH,
+      buttons
+    );
+    // Persist the notification until the user removes so it
+    // doesn't get removed on redirects.
+    notification.persistence = -1;
+  },
+
+  onAboutHome: function BrowserOnClick_onAboutHome(aTargetElm, aOwnerDoc) {
+    let elmId = aTargetElm.getAttribute("id");
+
+    switch (elmId) {
+      case "restorePreviousSession":
         let ss = Cc["@mozilla.org/browser/sessionstore;1"].
                  getService(Ci.nsISessionStore);
-        if (ss.canRestoreLastSession)
+        if (ss.canRestoreLastSession) {
           ss.restoreLastSession();
-        ownerDoc.getElementById("launcher").removeAttribute("session");
-      }
-      else if (ot == ownerDoc.getElementById("downloads")) {
+        }
+        aOwnerDoc.getElementById("launcher").removeAttribute("session");
+        break;
+
+      case "downloads":
         BrowserDownloadsUI();
-      }
-      else if (ot == ownerDoc.getElementById("bookmarks")) {
+        break;
+
+      case "bookmarks":
         PlacesCommandHook.showPlacesOrganizer("AllBookmarks");
-      }
-      else if (ot == ownerDoc.getElementById("history")) {
+        break;
+
+      case "history":
         PlacesCommandHook.showPlacesOrganizer("History");
-      }
-      else if (ot == ownerDoc.getElementById("apps")) {
+        break;
+
+      case "apps":
         openUILinkIn("https://marketplace.mozilla.org/", "tab");
-      }
-      else if (ot == ownerDoc.getElementById("addons")) {
+        break;
+
+      case "addons":
         BrowserOpenAddonsMgr();
-      }
-      else if (ot == ownerDoc.getElementById("sync")) {
+        break;
+
+      case "sync":
         openPreferences("paneSync");
-      }
-      else if (ot == ownerDoc.getElementById("settings")) {
+        break;
+
+      case "settings":
         openPreferences();
-      }
-    }
-}
+        break;
+    }
+  },
+};
 
 /**
  * Re-direct the browser to a known-safe page.  This function is
  * used when, for example, the user browses to a known malware page
  * and is presented with about:blocked.  The "Get me out of here!"
  * button should take the user to the default start page so that even
  * when their own homepage is infected, we can get them somewhere safe.
  */
--- a/build/mobile/sutagent/android/SUTAgentAndroid.java
+++ b/build/mobile/sutagent/android/SUTAgentAndroid.java
@@ -372,16 +372,49 @@ public class SUTAgentAndroid extends Act
             System.exit(0);
             }
         else
             {
             logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "onDestroy - not finishing");
             }
         }
 
+    @Override
+    public void onLowMemory()
+        {
+        System.gc();
+        DoCommand dc = new DoCommand(getApplication());
+        if (dc != null)
+            {
+            logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "onLowMemory");
+            logToFile(dc.GetTestRoot(), dc.GetSystemTime(), dc.GetMemoryInfo());
+            String procInfo = dc.GetProcessInfo();
+            if (procInfo != null)
+                {
+                String lines[] = procInfo.split("\n");
+                for (String line : lines) 
+                    {
+                    if (line.contains("mozilla"))
+                        {
+                        logToFile(dc.GetTestRoot(), dc.GetSystemTime(), line);
+                        String words[] = line.split("\t");
+                        if ((words != null) && (words.length > 1))
+                            {
+                            logToFile(dc.GetTestRoot(), dc.GetSystemTime(), dc.StatProcess(words[1]));
+                            }
+                        }
+                    }
+                }
+            }
+        else
+            {
+            Log.e("SUTAgentAndroid", "onLowMemory: unable to log to file!");
+            }
+        }
+
     private void monitorBatteryState()
         {
         battReceiver = new BroadcastReceiver()
             {
             public void onReceive(Context context, Intent intent)
                 {
                 StringBuilder sb = new StringBuilder();
 
--- a/caps/idl/nsIPrincipal.idl
+++ b/caps/idl/nsIPrincipal.idl
@@ -16,17 +16,17 @@ struct JSPrincipals;
 
 interface nsIURI;
 interface nsIContentSecurityPolicy;
 
 [ptr] native JSContext(JSContext);
 [ptr] native JSPrincipals(JSPrincipals);
 [ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
 
-[scriptable, uuid(fbb93cc7-9a94-4743-8e89-9e6939cac083)]
+[scriptable, uuid(8a74b011-667d-4cfa-b2a2-b27582ba5f38)]
 interface nsIPrincipal : nsISerializable
 {
     /**
      * Values of capabilities for each principal. Order is
      * significant: if an operation is performed on a set
      * of capabilities, the minimum is computed.
      */
     const short ENABLE_DENIED                = 1;
@@ -240,16 +240,21 @@ interface nsIPrincipal : nsISerializable
      */
     readonly attribute unsigned short appStatus;
 
     /**
      * Returns the app id the principal is in.
      * Returns nsIAppsService::NO_APP_ID if this principal isn't part of an app.
      */
     readonly attribute unsigned long appId;
+
+    /**
+     * Returns true iif the principal is inside a browser element.
+     */
+    readonly attribute boolean isInBrowserElement;
 };
 
 /**
  * If nsSystemPrincipal is too risky to use, but we want a principal to access 
  * more than one origin, nsExpandedPrincipals letting us define an array of 
  * principals it subsumes. So script with an nsExpandedPrincipals will gain
  * same origin access when at least one of its principals it contains gained 
  * sameorigin acccess. An nsExpandedPrincipal will be subsumed by the system
--- a/caps/include/nsPrincipal.h
+++ b/caps/include/nsPrincipal.h
@@ -122,16 +122,17 @@ public:
   NS_IMETHOD SetDomain(nsIURI* aDomain);
   NS_IMETHOD GetOrigin(char** aOrigin);
   NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval);
   NS_IMETHOD SubsumesIgnoringDomain(nsIPrincipal* other, bool* _retval);
   NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report);
   NS_IMETHOD GetExtendedOrigin(nsACString& aExtendedOrigin);
   NS_IMETHOD GetAppStatus(PRUint16* aAppStatus);
   NS_IMETHOD GetAppId(PRUint32* aAppStatus);
+  NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement);
 #ifdef DEBUG
   virtual void dumpImpl();
 #endif
 
   nsPrincipal();
 
   // Either Init() or InitFromPersistent() must be called before
   // the principal is in a usable state.
@@ -200,16 +201,17 @@ public:
   NS_IMETHOD SetDomain(nsIURI* aDomain);
   NS_IMETHOD GetOrigin(char** aOrigin);
   NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval);
   NS_IMETHOD SubsumesIgnoringDomain(nsIPrincipal* other, bool* _retval);
   NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report);
   NS_IMETHOD GetExtendedOrigin(nsACString& aExtendedOrigin);
   NS_IMETHOD GetAppStatus(PRUint16* aAppStatus);
   NS_IMETHOD GetAppId(PRUint32* aAppStatus);
+  NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement);
 #ifdef DEBUG
   virtual void dumpImpl();
 #endif
   
   virtual void GetScriptLocation(nsACString &aStr) MOZ_OVERRIDE;
 
 private:
   nsTArray< nsCOMPtr<nsIPrincipal> > mPrincipals;
--- a/caps/src/nsNullPrincipal.cpp
+++ b/caps/src/nsNullPrincipal.cpp
@@ -330,16 +330,23 @@ nsNullPrincipal::GetAppStatus(PRUint16* 
 
 NS_IMETHODIMP
 nsNullPrincipal::GetAppId(PRUint32* aAppId)
 {
   *aAppId = nsIScriptSecurityManager::NO_APP_ID;
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsNullPrincipal::GetIsInBrowserElement(bool* aIsInBrowserElement)
+{
+  *aIsInBrowserElement = false;
+  return NS_OK;
+}
+
 /**
  * nsISerializable implementation
  */
 NS_IMETHODIMP
 nsNullPrincipal::Read(nsIObjectInputStream* aStream)
 {
   // no-op: CID is sufficient to create a useful nsNullPrincipal, since the URI
   // is not really relevant.
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -1089,16 +1089,23 @@ nsPrincipal::GetAppId(PRUint32* aAppId)
     return NS_OK;
   }
 
   *aAppId = mAppId;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsPrincipal::GetIsInBrowserElement(bool* aIsInBrowserElement)
+{
+  *aIsInBrowserElement = mInMozBrowser;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsPrincipal::Read(nsIObjectInputStream* aStream)
 {
   bool hasCapabilities;
   nsresult rv = aStream->ReadBoolean(&hasCapabilities);
   if (NS_SUCCEEDED(rv) && hasCapabilities) {
     mCapabilities = new nsHashtable(aStream, ReadAnnotationEntry,
                                     FreeAnnotationEntry, &rv);
     NS_ENSURE_TRUE(mCapabilities, NS_ERROR_OUT_OF_MEMORY);
@@ -1471,16 +1478,22 @@ nsExpandedPrincipal::GetAppStatus(PRUint
 }
 
 NS_IMETHODIMP
 nsExpandedPrincipal::GetAppId(PRUint32* aAppId)
 {
   return NS_ERROR_NOT_AVAILABLE;
 }
 
+NS_IMETHODIMP
+nsExpandedPrincipal::GetIsInBrowserElement(bool* aIsInBrowserElement)
+{
+  return NS_ERROR_NOT_AVAILABLE;
+}
+
 void
 nsExpandedPrincipal::GetScriptLocation(nsACString& aStr)
 {
   if (mCert) {
     aStr.Assign(mCert->fingerprint);
   } else {
     // Is that a good idea to list it's principals?
     aStr.Assign(EXPANDED_PRINCIPAL_SPEC);
--- a/caps/src/nsSystemPrincipal.cpp
+++ b/caps/src/nsSystemPrincipal.cpp
@@ -253,16 +253,23 @@ nsSystemPrincipal::GetAppStatus(PRUint16
 
 NS_IMETHODIMP
 nsSystemPrincipal::GetAppId(PRUint32* aAppId)
 {
   *aAppId = nsIScriptSecurityManager::NO_APP_ID;
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsSystemPrincipal::GetIsInBrowserElement(bool* aIsInBrowserElement)
+{
+  *aIsInBrowserElement = false;
+  return NS_OK;
+}
+
 //////////////////////////////////////////
 // Methods implementing nsISerializable //
 //////////////////////////////////////////
 
 NS_IMETHODIMP
 nsSystemPrincipal::Read(nsIObjectInputStream* aStream)
 {
     // no-op: CID is sufficient to identify the mSystemPrincipal singleton
--- a/caps/tests/mochitest/test_principal_extendedorigin_appid_appstatus.html
+++ b/caps/tests/mochitest/test_principal_extendedorigin_appid_appstatus.html
@@ -246,16 +246,17 @@ var gData = [
   // browser containing an iframe is part of the browser
   {
     src: "http://example.org/",
     isapp: false,
     browser: true,
     child: {
       src: "http://example.org/chrome/",
       isapp: false,
+      inBrowser: true,
     },
     test: [ "child-has-same-eo" ],
   },
 ];
 
 // The list of all data ids generated by this test.
 var eoList = [];
 
@@ -305,24 +306,30 @@ function checkIFrame(aFrame, data) {
     is(eoList.indexOf(principal.extendedOrigin), -1,
        "extendedOrigin should be unique");
   }
   if (data.test.indexOf("eo-as-last") != -1) {
     is(principal.extendedOrigin, eoList[eoList.length-1],
        "extendedOrigin should be the same as the last inserted one");
   }
 
+  is(principal.isInBrowserElement, !!data.browser,
+     "check principal.isInBrowserElement");
+
   if (data.child) {
     let childPrincipal = aFrame.contentWindow.frames[0].document.nodePrincipal;
 
     if (data.child.isapp) {
       is(childPrincipal.appStatus, Ci.nsIPrincipal.APP_STATUS_INSTALLED,
          "child should be an installed app");
     }
 
+    is(childPrincipal.isInBrowserElement, !!data.child.browser || !!data.child.inBrowser,
+       "check childPrincipal.isInBrowserElement");
+
     if (data.test.indexOf("child-has-same-eo") != -1) {
       is(childPrincipal.extendedOrigin, principal.extendedOrigin,
          "child should have the same extendedOrigin as parent");
       is(childPrincipal.appStatus, principal.appStatus,
          "child should have the same appStatus if it has the same extendedOrigin");
       is(childPrincipal.appId, principal.appId,
          "child should have the same appId if it has the same extendedOrigin");
     }
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -17,16 +17,17 @@ MOZ_APP_BASENAME = @MOZ_APP_BASENAME@
 MOZ_APP_VENDOR = @MOZ_APP_VENDOR@
 MOZ_APP_PROFILE = @MOZ_APP_PROFILE@
 MOZ_APP_ID = @MOZ_APP_ID@
 MAR_CHANNEL_ID = @MAR_CHANNEL_ID@
 ACCEPTED_MAR_CHANNEL_IDS = @ACCEPTED_MAR_CHANNEL_IDS@
 MOZ_PROFILE_MIGRATOR = @MOZ_PROFILE_MIGRATOR@
 MOZ_EXTENSION_MANAGER = @MOZ_EXTENSION_MANAGER@
 MOZ_APP_UA_NAME = @MOZ_APP_UA_NAME@
+MOZ_UA_OS_AGNOSTIC = @MOZ_UA_OS_AGNOSTIC@
 MOZ_APP_VERSION = @MOZ_APP_VERSION@
 MOZ_APP_MAXVERSION = @MOZ_APP_MAXVERSION@
 MOZ_MACBUNDLE_NAME = @MOZ_MACBUNDLE_NAME@
 MOZ_MACBUNDLE_ID = @MOZ_MACBUNDLE_ID@
 MOZ_APP_STATIC_INI = @MOZ_APP_STATIC_INI@
 
 MOZ_PKG_SPECIAL = @MOZ_PKG_SPECIAL@
 
--- a/configure.in
+++ b/configure.in
@@ -8406,16 +8406,20 @@ AC_SUBST(MOZ_PROFILE_MIGRATOR)
 AC_SUBST(MOZ_EXTENSION_MANAGER)
 AC_DEFINE_UNQUOTED(MOZ_APP_UA_NAME, "$MOZ_APP_UA_NAME")
 AC_SUBST(MOZ_APP_UA_NAME)
 AC_DEFINE_UNQUOTED(MOZ_APP_UA_VERSION, "$MOZ_APP_VERSION")
 AC_SUBST(MOZ_APP_VERSION)
 AC_SUBST(MOZ_APP_MAXVERSION)
 AC_DEFINE_UNQUOTED(FIREFOX_VERSION,$FIREFOX_VERSION)
 AC_SUBST(FIREFOX_VERSION)
+AC_SUBST(MOZ_UA_OS_AGNOSTIC)
+if test -n "$MOZ_UA_OS_AGNOSTIC"; then
+  AC_DEFINE(MOZ_UA_OS_AGNOSTIC)
+fi
 
 # We can't use the static application.ini data when building against
 # a libxul SDK.
 if test -n "$LIBXUL_SDK"; then
     MOZ_APP_STATIC_INI=
 fi
 AC_SUBST(MOZ_APP_STATIC_INI)
 
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -6,16 +6,17 @@
 #define nsIContent_h___
 
 #include "nsCOMPtr.h" // for already_AddRefed
 #include "nsStringGlue.h"
 #include "nsCaseTreatment.h"
 #include "nsChangeHint.h"
 #include "nsINode.h"
 #include "nsIDocument.h" // for IsInHTMLDocument
+#include "nsCSSProperty.h"
 
 // Forward declarations
 class nsIAtom;
 class nsIDOMEvent;
 class nsIContent;
 class nsEventListenerManager;
 class nsIURI;
 class nsRuleWalker;
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -1286,16 +1286,18 @@ private:
     // Set if the element has some style states locked
     ElementHasLockedStyleStates,
     // Set if element has pointer locked
     ElementHasPointerLock,
     // Set if the node may have DOMMutationObserver attached to it.
     NodeMayHaveDOMMutationObserver,
     // Set if node is Content
     NodeIsContent,
+    // Set if the node has animations or transitions
+    ElementHasAnimations,
     // Guard value
     BooleanFlagCount
   };
 
   void SetBoolFlag(BooleanFlag name, bool value) {
     PR_STATIC_ASSERT(BooleanFlagCount <= 8*sizeof(mBoolFlags));
     mBoolFlags = (mBoolFlags & ~(1 << name)) | (value << name);
   }
@@ -1351,16 +1353,18 @@ public:
   bool MayHaveDOMMutationObserver()
     { return GetBoolFlag(NodeMayHaveDOMMutationObserver); }
   void SetMayHaveDOMMutationObserver()
     { SetBoolFlag(NodeMayHaveDOMMutationObserver, true); }
   bool HasListenerManager() { return HasFlag(NODE_HAS_LISTENERMANAGER); }
   bool HasPointerLock() const { return GetBoolFlag(ElementHasPointerLock); }
   void SetPointerLock() { SetBoolFlag(ElementHasPointerLock); }
   void ClearPointerLock() { ClearBoolFlag(ElementHasPointerLock); }
+  bool MayHaveAnimations() { return GetBoolFlag(ElementHasAnimations); }
+  void SetMayHaveAnimations() { SetBoolFlag(ElementHasAnimations); }
 protected:
   void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
   void SetInDocument() { SetBoolFlag(IsInDocument); }
   void SetNodeIsContent() { SetBoolFlag(NodeIsContent); }
   void ClearInDocument() { ClearBoolFlag(IsInDocument); }
   void SetIsElement() { SetBoolFlag(NodeIsElement); }
   void ClearIsElement() { ClearBoolFlag(NodeIsElement); }
   void SetHasID() { SetBoolFlag(ElementHasID); }
--- a/content/canvas/src/CustomQS_Canvas.h
+++ b/content/canvas/src/CustomQS_Canvas.h
@@ -4,16 +4,18 @@
 
 #ifndef CustomQS_Canvas_h
 #define CustomQS_Canvas_h
 
 #include "jsapi.h"
 
 #include "mozilla/dom/ImageData.h"
 
+#include "XPCQuickStubs.h"
+
 static bool
 GetImageData(JSContext* cx, JS::Value& imageData,
              uint32_t* width, uint32_t* height, JS::Anchor<JSObject*>* array)
 {
   if (!imageData.isObject()) {
     return xpc_qsThrow(cx, NS_ERROR_DOM_TYPE_MISMATCH_ERR);
   }
 
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -83,16 +83,19 @@
 #include "mozilla/CheckedInt.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/PBrowserParent.h"
 #include "mozilla/ipc/DocumentRendererParent.h"
 #include "mozilla/ipc/PDocumentRendererParent.h"
 #include "mozilla/unused.h"
 
+#include "CustomQS_Canvas.h"
+#include "jsfriendapi.h"
+
 // windows.h (included by chromium code) defines this, in its infinite wisdom
 #undef DrawText
 
 using namespace mozilla;
 using namespace mozilla::CanvasUtils;
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 using namespace mozilla::layers;
@@ -4031,22 +4034,72 @@ nsCanvasRenderingContext2D::EnsurePremul
 
   for (int a = 0; a <= 255; a++) {
     for (int c = 0; c <= 255; c++) {
       sPremultiplyTable[a][c] = (a * c + 254) / 255;
     }
   }
 }
 
-// void putImageData (in ImageData d, in float x, in float y);
+// void putImageData (in jsval d, in double x, in double y);
+// void putImageData (in jsval d, in double x, in double y, in double dirtyX, in double dirtyY, in double dirtyWidth, in double dirtyHeight);
 NS_IMETHODIMP
-nsCanvasRenderingContext2D::PutImageData()
+nsCanvasRenderingContext2D::PutImageData(const JS::Value& dataArg,
+                                         double xd, double yd,
+                                         double dirtyXd, double dirtyYd,
+                                         double dirtyWidthd,
+                                         double dirtyHeightd,
+                                         JSContext* cx,
+                                         PRUint8 optional_argc)
 {
-    /* Should never be called -- PutImageData_explicit is the QS entry point */
-    return NS_ERROR_NOT_IMPLEMENTED;
+    // GetImageData wants a non-const JS::Value
+    JS::Value dataVal(dataArg);
+
+    // Total copy/paste from the quickstub
+    uint32_t w, h;
+    JS::Anchor<JSObject*> darray;
+    if (!::GetImageData(cx, dataVal, &w, &h, &darray)) {
+        return NS_ERROR_UNEXPECTED;
+    }
+
+    if (!FloatValidate(xd, yd)) {
+        return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
+    }
+
+    int32_t x = JS_DoubleToInt32(xd);
+    int32_t y = JS_DoubleToInt32(yd);
+
+    // The dirty rect is optional
+    bool hasDirtyRect = false;
+    int32_t dirtyX = 0, dirtyY = 0, dirtyWidth = w, dirtyHeight = h;
+
+    if (optional_argc != 0 && optional_argc != 4) {
+        // Wrong number of arguments
+        return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
+    }
+
+    if (optional_argc == 4) {
+        if (!FloatValidate(dirtyXd, dirtyYd, dirtyWidthd, dirtyHeightd)) {
+            return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
+        }
+
+        dirtyX = JS_DoubleToInt32(dirtyXd);
+        dirtyY = JS_DoubleToInt32(dirtyYd);
+        dirtyWidth = JS_DoubleToInt32(dirtyWidthd);
+        dirtyHeight = JS_DoubleToInt32(dirtyHeightd);
+
+        hasDirtyRect = true;
+    }
+
+    PRUint8* data =
+        reinterpret_cast<PRUint8*>(JS_GetArrayBufferViewData(darray.get(), cx));
+    uint32_t byteLength = JS_GetTypedArrayByteLength(darray.get(), cx);
+
+    return PutImageData_explicit(x, y, w, h, data, byteLength, hasDirtyRect,
+                                 dirtyX, dirtyY, dirtyWidth, dirtyHeight);
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2D::PutImageData_explicit(PRInt32 x, PRInt32 y, PRUint32 w, PRUint32 h,
                                                   unsigned char *aData, PRUint32 aDataLen,
                                                   bool hasDirtyRect, PRInt32 dirtyX, PRInt32 dirtyY,
                                                   PRInt32 dirtyWidth, PRInt32 dirtyHeight)
 {
@@ -4162,21 +4215,86 @@ nsCanvasRenderingContext2D::GetThebesSur
     }
 
     *surface = mSurface.get();
     NS_ADDREF(*surface);
 
     return NS_OK;
 }
 
-NS_IMETHODIMP
-nsCanvasRenderingContext2D::CreateImageData()
+static nsresult
+CreateImageData(JSContext* cx, uint32_t w, uint32_t h,
+                nsIDOMImageData** retval)
 {
-    /* Should never be called; handled entirely in the quickstub */
-    return NS_ERROR_NOT_IMPLEMENTED;
+    using mozilla::CheckedInt;
+
+    if (w == 0)
+        w = 1;
+    if (h == 0)
+        h = 1;
+
+    CheckedInt<uint32_t> len = CheckedInt<uint32_t>(w) * h * 4;
+    if (!len.isValid()) {
+        return NS_ERROR_DOM_INDEX_SIZE_ERR;
+    }
+
+    // Create the fast typed array; it's initialized to 0 by default.
+    JSObject* darray = JS_NewUint8ClampedArray(cx, len.value());
+    JS::AutoObjectRooter rd(cx, darray);
+    if (!darray) {
+        return NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    nsRefPtr<mozilla::dom::ImageData> imageData =
+        new mozilla::dom::ImageData(w, h, *darray);
+    imageData.forget(retval);
+    return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsCanvasRenderingContext2D::CreateImageData(const JS::Value &a1,
+                                            const JS::Value &a2,
+                                            JSContext* cx,
+                                            PRUint8 optional_argc,
+                                            nsIDOMImageData** retval)
+{
+    // GetImageData wants mutable jsvals, so make copies
+    JS::Value arg1(a1);
+    JS::Value arg2(a2);
+
+    // Forwarding to the quickstub leads to pain and suffering, so
+    // we'll do this the hard way.
+    if (optional_argc == 0) {
+        uint32_t data_width, data_height;
+        JS::Anchor<JSObject*> darray;
+        if (!::GetImageData(cx, arg1, &data_width, &data_height, &darray)) {
+            return NS_ERROR_FAILURE;
+        }
+        return ::CreateImageData(cx, data_width, data_height, retval);
+    }
+
+    // This is total copy/paste from the quickstub code
+    double width, height;
+    if (!JS_ValueToNumber(cx, arg1, &width) ||
+        !JS_ValueToNumber(cx, arg2, &height))
+        return NS_ERROR_FAILURE;
+
+    if (!FloatValidate(width, height))
+        return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
+
+    if (!width || !height)
+        return NS_ERROR_DOM_INDEX_SIZE_ERR;
+
+    int32_t wi = JS_DoubleToInt32(width);
+    int32_t hi = JS_DoubleToInt32(height);
+
+    uint32_t w = NS_ABS(wi);
+    uint32_t h = NS_ABS(hi);
+    return ::CreateImageData(cx, w, h, retval);
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2D::GetMozImageSmoothingEnabled(bool *retVal)
 {
     *retVal = CurrentState().imageSmoothingEnabled;
     return NS_OK;
 }
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -4375,20 +4375,24 @@ nsCanvasRenderingContext2DAzure::PutImag
                                 arr.mData, arr.mLength, true,
                                 JS_DoubleToInt32(dirtyX),
                                 JS_DoubleToInt32(dirtyY),
                                 JS_DoubleToInt32(dirtyWidth),
                                 JS_DoubleToInt32(dirtyHeight));
 }
 
 // void putImageData (in ImageData d, in float x, in float y);
+// void putImageData (in ImageData d, in double x, in double y, in double dirtyX, in double dirtyY, in double dirtyWidth, in double dirtyHeight);
 NS_IMETHODIMP
-nsCanvasRenderingContext2DAzure::PutImageData()
+nsCanvasRenderingContext2DAzure::PutImageData(const JS::Value&, double, double,
+                                              double, double, double, double,
+                                              JSContext*, PRUint8)
 {
-  /* Should never be called -- PutImageData_explicit is the QS entry point */
+  /* Should never be called -- the new binding code handles it, and
+     C++ callers should call PutImageData_explicit */
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::PutImageData_explicit(PRInt32 x, PRInt32 y, PRUint32 w, PRUint32 h,
                                                        unsigned char *aData, PRUint32 aDataLen,
                                                        bool hasDirtyRect, PRInt32 dirtyX, PRInt32 dirtyY,
                                                        PRInt32 dirtyWidth, PRInt32 dirtyHeight)
@@ -4582,19 +4586,23 @@ nsCanvasRenderingContext2DAzure::CreateI
                                                  ImageData* imagedata,
                                                  ErrorResult& error)
 {
   return ::CreateImageData(cx, this, imagedata->GetWidth(),
                            imagedata->GetHeight(), error);
 }
 
 NS_IMETHODIMP
-nsCanvasRenderingContext2DAzure::CreateImageData()
+nsCanvasRenderingContext2DAzure::CreateImageData(const JS::Value &arg1,
+                                                 const JS::Value &arg2,
+                                                 JSContext* cx,
+                                                 PRUint8 optional_argc,
+                                                 nsIDOMImageData** retval)
 {
-  /* Should never be called; handled entirely in the quickstub */
+  /* Should never be called; handled entirely in new bindings */
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::GetMozImageSmoothingEnabled(bool *retVal)
 {
   *retVal = GetImageSmoothingEnabled();
   return NS_OK;
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -969,25 +969,37 @@ nsHTMLFormElement::NotifySubmitObservers
 
 nsresult
 nsHTMLFormElement::WalkFormElements(nsFormSubmission* aFormSubmission)
 {
   nsTArray<nsGenericHTMLFormElement*> sortedControls;
   nsresult rv = mControls->GetSortedControls(sortedControls);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  PRUint32 len = sortedControls.Length();
+
+  // Hold a reference to the elements so they can't be deleted while
+  // calling SubmitNamesValues().
+  for (PRUint32 i = 0; i < len; ++i) {
+    static_cast<nsGenericHTMLElement*>(sortedControls[i])->AddRef();
+  }
+
   //
   // Walk the list of nodes and call SubmitNamesValues() on the controls
   //
-  PRUint32 len = sortedControls.Length();
   for (PRUint32 i = 0; i < len; ++i) {
     // Tell the control to submit its name/value pairs to the submission
     sortedControls[i]->SubmitNamesValues(aFormSubmission);
   }
 
+  // Release the references.
+  for (PRUint32 i = 0; i < len; ++i) {
+    static_cast<nsGenericHTMLElement*>(sortedControls[i])->Release();
+  }
+
   return NS_OK;
 }
 
 // nsIForm
 
 NS_IMETHODIMP_(PRUint32)
 nsHTMLFormElement::GetElementCount() const 
 {
--- a/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/content/html/content/src/nsHTMLSelectElement.cpp
@@ -329,18 +329,17 @@ nsHTMLSelectElement::InsertOptionsIntoLi
 {
   // We *assume* here that someone's brain has not gone horribly
   // wrong by putting <option> inside of <option>.  I'm sorry, I'm
   // just not going to look for an option inside of an option.
   // Sue me.
 
   nsHTMLOptionElement *optElement = nsHTMLOptionElement::FromContent(aOptions);
   if (optElement) {
-    nsresult rv = mOptions->InsertOptionAt(optElement, *aInsertIndex);
-    NS_ENSURE_SUCCESS(rv, rv);
+    mOptions->InsertOptionAt(optElement, *aInsertIndex);
     (*aInsertIndex)++;
     return NS_OK;
   }
 
   // If it's at the top level, then we just found out there are non-options
   // at the top level, which will throw off the insert count
   if (aDepth == 0) {
     mNonOptionChildren++;
@@ -1804,17 +1803,16 @@ nsHTMLSelectElement::DispatchContentRese
 static void
 AddOptionsRecurse(nsIContent* aRoot, nsHTMLOptionCollection* aArray)
 {
   for (nsIContent* cur = aRoot->GetFirstChild();
        cur;
        cur = cur->GetNextSibling()) {
     nsHTMLOptionElement* opt = nsHTMLOptionElement::FromContent(cur);
     if (opt) {
-      // If we fail here, then at least we've tried our best
       aArray->AppendOption(opt);
     } else if (cur->IsHTML(nsGkAtoms::optgroup)) {
       AddOptionsRecurse(cur, aArray);
     }
   }
 }
 
 void
--- a/content/html/content/src/nsHTMLSelectElement.h
+++ b/content/html/content/src/nsHTMLSelectElement.h
@@ -57,19 +57,19 @@ public:
                                                          nsIHTMLCollection)
 
   // Helpers for nsHTMLSelectElement
   /**
    * Insert an option
    * @param aOption the option to insert
    * @param aIndex the index to insert at
    */
-  bool InsertOptionAt(nsHTMLOptionElement* aOption, PRUint32 aIndex)
+  void InsertOptionAt(nsHTMLOptionElement* aOption, PRUint32 aIndex)
   {
-    return !!mElements.InsertElementAt(aIndex, aOption);
+    mElements.InsertElementAt(aIndex, aOption);
   }
 
   /**
    * Remove an option
    * @param aIndex the index of the option to remove
    */
   void RemoveOptionAt(PRUint32 aIndex)
   {
@@ -92,19 +92,19 @@ public:
   void Clear()
   {
     mElements.Clear();
   }
 
   /**
    * Append an option to end of array
    */
-  bool AppendOption(nsHTMLOptionElement* aOption)
+  void AppendOption(nsHTMLOptionElement* aOption)
   {
-    return !!mElements.AppendElement(aOption);
+    mElements.AppendElement(aOption);
   }
 
   /**
    * Drop the reference to the select.  Called during select destruction.
    */
   void DropReference();
 
   /**
@@ -117,17 +117,18 @@ public:
    * @param aForward TRUE to look forward, FALSE to look backward
    * @return the option index
    */
   nsresult GetOptionIndex(mozilla::dom::Element* aOption,
                           PRInt32 aStartIndex, bool aForward,
                           PRInt32* aIndex);
 
 private:
-  /** The list of options (holds strong references) */
+  /** The list of options (holds strong references).  This is infallible, so
+   * various members such as InsertOptionAt are also infallible. */
   nsTArray<nsRefPtr<nsHTMLOptionElement> > mElements;
   /** The select element that contains this array */
   nsHTMLSelectElement* mSelect;
 };
 
 #define NS_SELECT_STATE_IID                        \
 { /* 4db54c7c-d159-455f-9d8e-f60ee466dbf3 */       \
   0x4db54c7c,                                      \
--- a/content/smil/nsSMILKeySpline.h
+++ b/content/smil/nsSMILKeySpline.h
@@ -21,16 +21,21 @@ public:
    * SMILANIM 3.2.3. They must each be in the range 0.0 <= x <= 1.0
    */
   nsSMILKeySpline(double aX1, double aY1,
                   double aX2, double aY2)
   {
     Init(aX1, aY1, aX2, aY2);
   }
 
+  double X1() const { return mX1; }
+  double Y1() const { return mY1; }
+  double X2() const { return mX2; }
+  double Y2() const { return mY2; }
+
   void Init(double aX1, double aY1,
             double aX2, double aY2);
 
   /**
    * Gets the output (y) value for an input (x).
    *
    * @param aX  The input x value. A floating-point number between 0 and
    *            1 (inclusive).
--- a/content/xul/document/src/nsXULDocument.cpp
+++ b/content/xul/document/src/nsXULDocument.cpp
@@ -2533,17 +2533,18 @@ nsXULDocument::InsertXULOverlayPI(const 
                    mCurrentPrototype->GetURI());
     if (NS_SUCCEEDED(rv)) {
         // We insert overlays into mUnloadedOverlays at the same index in
         // document order, so they end up in the reverse of the document
         // order in mUnloadedOverlays.
         // This is needed because the code in ResumeWalk loads the overlays
         // by processing the last item of mUnloadedOverlays and removing it
         // from the array.
-        rv = mUnloadedOverlays.InsertObjectAt(uri, 0);
+        mUnloadedOverlays.InsertElementAt(0, uri);
+        rv = NS_OK;
     } else if (rv == NS_ERROR_MALFORMED_URI) {
         // The URL is bad, move along. Don't propagate for now.
         // XXX report this to the Error Console (bug 359846)
         rv = NS_OK;
     }
 
     return rv;
 }
@@ -2580,18 +2581,17 @@ nsXULDocument::AddChromeOverlays()
 
         uri = do_QueryInterface(next);
         if (!uri) {
             NS_ERROR("Chrome registry handed me a non-nsIURI object!");
             continue;
         }
 
         // Same comment as in nsXULDocument::InsertXULOverlayPI
-        rv = mUnloadedOverlays.InsertObjectAt(uri, 0);
-        if (NS_FAILED(rv)) break;
+        mUnloadedOverlays.InsertElementAt(0, uri);
     }
 
     return rv;
 }
 
 NS_IMETHODIMP
 nsXULDocument::LoadOverlay(const nsAString& aURL, nsIObserver* aObserver)
 {
@@ -3047,22 +3047,22 @@ nsXULDocument::ResumeWalk()
         // Once we get here, the context stack will have been
         // depleted. That means that the entire prototype has been
         // walked and content has been constructed.
 
         // If we're not already, mark us as now processing overlays.
         mState = eState_Overlay;
 
         // If there are no overlay URIs, then we're done.
-        PRUint32 count = mUnloadedOverlays.Count();
+        PRUint32 count = mUnloadedOverlays.Length();
         if (! count)
             break;
 
         nsCOMPtr<nsIURI> uri = mUnloadedOverlays[count-1];
-        mUnloadedOverlays.RemoveObjectAt(count-1);
+        mUnloadedOverlays.RemoveElementAt(count - 1);
 
         bool shouldReturn, failureFromContent;
         rv = LoadOverlayInternal(uri, false, &shouldReturn,
                                  &failureFromContent);
         if (failureFromContent)
             // The failure |rv| was the result of a problem in the content
             // rather than an unexpected problem in our implementation, so
             // just continue with the next overlay.
--- a/content/xul/document/src/nsXULDocument.h
+++ b/content/xul/document/src/nsXULDocument.h
@@ -340,17 +340,17 @@ protected:
      * array are resolved before overlays earlier in the array (i.e.,
      * it is a stack).
      *
      * In the current implementation the order the overlays are loaded
      * in is as follows: first overlays from xul-overlay PIs, in the
      * same order as in the document, then the overlays from the chrome
      * registry.
      */
-    nsCOMArray<nsIURI> mUnloadedOverlays;
+    nsTArray<nsCOMPtr<nsIURI> > mUnloadedOverlays;
 
     /**
      * Load the transcluded script at the specified URI. If the
      * prototype construction must 'block' until the load has
      * completed, aBlock will be set to true.
      */
     nsresult LoadScript(nsXULPrototypeScript *aScriptProto, bool* aBlock);
 
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.cpp
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.cpp
@@ -47,25 +47,25 @@ nsIRDFResource*           nsXULTemplateQ
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateQueryProcessorRDF)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateQueryProcessorRDF)
     tmp->Done();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 static PLDHashOperator
 BindingDependenciesTraverser(nsISupports* key,
-                             nsCOMArray<nsXULTemplateResultRDF>* array,
+                             nsXULTemplateQueryProcessorRDF::ResultArray* array,
                              void* userArg)
 {
     nsCycleCollectionTraversalCallback *cb = 
         static_cast<nsCycleCollectionTraversalCallback*>(userArg);
 
-    PRInt32 i, count = array->Count();
+    PRInt32 i, count = array->Length();
     for (i = 0; i < count; ++i) {
-        cb->NoteXPCOMChild(array->ObjectAt(i));
+        cb->NoteXPCOMChild(array->ElementAt(i));
     }
 
     return PL_DHASH_NEXT;
 }
 
 static PLDHashOperator
 MemoryElementTraverser(const PRUint32& key,
                        nsCOMArray<nsXULTemplateResultRDF>* array,
@@ -102,17 +102,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
     }
     if (tmp->mMemoryElementToResultMap.IsInitialized()) {
         tmp->mMemoryElementToResultMap.EnumerateRead(MemoryElementTraverser,
                                                      &cb);
     }
     if (tmp->mRuleToBindingsMap.IsInitialized()) {
         tmp->mRuleToBindingsMap.EnumerateRead(RuleToBindingTraverser, &cb);
     }
-    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mQueries)
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(mQueries)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULTemplateQueryProcessorRDF)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULTemplateQueryProcessorRDF)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULTemplateQueryProcessorRDF)
     NS_INTERFACE_MAP_ENTRY(nsIXULTemplateQueryProcessor)
     NS_INTERFACE_MAP_ENTRY(nsIRDFObserver)
     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULTemplateQueryProcessor)
@@ -428,19 +428,17 @@ nsXULTemplateQueryProcessorRDF::CompileQ
         delete instnode;
         return rv;
     }
 
     rv = lastnode->AddChild(instnode);
     if (NS_FAILED(rv))
         return rv;
 
-    rv = mQueries.AppendObject(query);
-    if (NS_FAILED(rv))
-        return rv;
+    mQueries.AppendElement(query);
 
     *_retval = query;
     NS_ADDREF(*_retval);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -467,17 +465,17 @@ nsXULTemplateQueryProcessorRDF::Generate
         // make sure that cached results were generated for this ref, and if not,
         // regenerate them. Otherwise, things will go wrong for templates bound to
         // an HTML element as they are not generated lazily.
         if (aRef == mLastRef) {
             query->UseCachedResults(getter_AddRefs(results));
         }
         else {
             // clear the cached results
-            PRInt32 count = mQueries.Count();
+            PRInt32 count = mQueries.Length();
             for (PRInt32 r = 0; r < count; r++) {
                 mQueries[r]->ClearCachedResults();
             }
         }
 
         if (! results) {
             if (! query->mRefVariable)
                 query->mRefVariable = do_GetAtom("?uri");
@@ -1008,21 +1006,21 @@ nsXULTemplateQueryProcessorRDF::Synchron
                                                nsIRDFResource* aProperty,
                                                nsIRDFNode* aOldTarget,
                                                nsIRDFNode* aNewTarget)
 {
     // Update each match that contains <aSource, aProperty, aOldTarget>.
 
     // Get all the matches whose assignments are currently supported
     // by aSource and aProperty: we'll need to recompute them.
-    nsCOMArray<nsXULTemplateResultRDF>* results;
+    ResultArray* results;
     if (!mBindingDependencies.Get(aSource, &results) || !mBuilder)
         return NS_OK;
 
-    PRUint32 length = results->Count();
+    PRUint32 length = results->Length();
 
     for (PRUint32 r = 0; r < length; r++) {
         nsXULTemplateResultRDF* result = (*results)[r];
         if (result) {
             // synchronize the result's bindings and then update the builder
             // so that content can be updated
             if (result->SyncAssignments(aSource, aProperty, aNewTarget)) {
                 nsITemplateRDFQuery* query = result->Query();
@@ -1707,48 +1705,42 @@ nsXULTemplateQueryProcessorRDF::CompileS
 }
 
 RDFBindingSet*
 nsXULTemplateQueryProcessorRDF::GetBindingsForRule(nsIDOMNode* aRuleNode)
 {
     return mRuleToBindingsMap.GetWeak(aRuleNode);
 }
 
-nsresult
+void
 nsXULTemplateQueryProcessorRDF::AddBindingDependency(nsXULTemplateResultRDF* aResult,
                                                      nsIRDFResource* aResource)
 {
-    nsCOMArray<nsXULTemplateResultRDF>* arr;
+    ResultArray* arr;
     if (!mBindingDependencies.Get(aResource, &arr)) {
-        arr = new nsCOMArray<nsXULTemplateResultRDF>();
-        if (!arr)
-            return NS_ERROR_OUT_OF_MEMORY;
+        arr = new ResultArray();
 
         mBindingDependencies.Put(aResource, arr);
     }
 
     PRInt32 index = arr->IndexOf(aResult);
     if (index == -1)
-        return arr->AppendObject(aResult);
-
-    return NS_OK;
+        arr->AppendElement(aResult);
 }
 
-nsresult
+void
 nsXULTemplateQueryProcessorRDF::RemoveBindingDependency(nsXULTemplateResultRDF* aResult,
                                                         nsIRDFResource* aResource)
 {
-    nsCOMArray<nsXULTemplateResultRDF>* arr;
+    ResultArray* arr;
     if (mBindingDependencies.Get(aResource, &arr)) {
         PRInt32 index = arr->IndexOf(aResult);
         if (index >= 0)
-            return arr->RemoveObjectAt(index);
+            arr->RemoveElementAt(index);
     }
-
-    return NS_OK;
 }
 
 
 nsresult
 nsXULTemplateQueryProcessorRDF::AddMemoryElements(const Instantiation& aInst,
                                                   nsXULTemplateResultRDF* aResult)
 {
     // Add the result to a table indexed by supporting MemoryElement
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.h
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.h
@@ -42,16 +42,17 @@ class nsXULTemplateResultRDF;
 
 /**
  * An object that generates results from a query on an RDF graph
  */
 class nsXULTemplateQueryProcessorRDF MOZ_FINAL : public nsIXULTemplateQueryProcessor,
                                                  public nsIRDFObserver
 {
 public:
+    typedef nsTArray<nsCOMPtr<nsXULTemplateResultRDF> > ResultArray;
 
     nsXULTemplateQueryProcessorRDF();
 
     ~nsXULTemplateQueryProcessorRDF();
 
     nsresult InitGlobals();
 
     // nsISupports interface
@@ -196,24 +197,24 @@ public:
     RDFBindingSet*
     GetBindingsForRule(nsIDOMNode* aRule);
 
     /*
      * Indicate that a result is dependant on a particular resource. When an
      * assertion is added to or removed from the graph involving that
      * resource, that result must be recalculated.
      */
-    nsresult
+    void
     AddBindingDependency(nsXULTemplateResultRDF* aResult,
                          nsIRDFResource* aResource);
 
     /**
      * Remove a dependency a result has on a particular resource.
      */
-    nsresult
+    void
     RemoveBindingDependency(nsXULTemplateResultRDF* aResult,
                             nsIRDFResource* aResource);
 
     /**
      * A memory element is a hash of an RDF triple. One exists for each triple
      * that was involved in generating a result. This function adds this to a
      * map, keyed by memory element, when the value is a list of results that
      * depend on that memory element. When an RDF triple is removed from the
@@ -309,18 +310,17 @@ protected:
 
     /**
      * A map between nsIRDFNodes that form the left-hand side (the subject) of
      * a <binding> and an array of nsIXULTemplateResults. When a new assertion
      * is added to the graph involving a particular rdf node, it is looked up
      * in this binding map. If it exists, the corresponding results must then
      * be synchronized.
      */
-    nsClassHashtable<nsISupportsHashKey,
-                     nsCOMArray<nsXULTemplateResultRDF> > mBindingDependencies;
+    nsClassHashtable<nsISupportsHashKey, ResultArray> mBindingDependencies;
 
     /**
      * A map between memory elements and an array of nsIXULTemplateResults.
      * When a triple is unasserted from the graph, the corresponding results
      * no longer match so they must be removed.
      */
     nsClassHashtable<nsUint32HashKey,
                      nsCOMArray<nsXULTemplateResultRDF> > mMemoryElementToResultMap;
@@ -328,17 +328,17 @@ protected:
     // map of the rules to the bindings for those rules.
     // XXXndeakin this might be better just as an array since there is usually
     //            ten or fewer rules
     nsRefPtrHashtable<nsISupportsHashKey, RDFBindingSet> mRuleToBindingsMap;
 
     /**
      * The queries
      */
-    nsCOMArray<nsITemplateRDFQuery> mQueries;
+    nsTArray<nsCOMPtr<nsITemplateRDFQuery> > mQueries;
 
     /**
      * All of the RDF tests in the rule network, which are checked when a new
      * assertion is added to the graph. This is a subset of mAllTests, which
      * also includes non-RDF tests.
      */
     ReteNodeSet mRDFTests;
 
--- a/dom/alarm/nsIAlarmHalService.idl
+++ b/dom/alarm/nsIAlarmHalService.idl
@@ -8,26 +8,26 @@
 interface nsIAlarmFiredCb : nsISupports 
 {
   void onAlarmFired();
 };
 
 [scriptable, function, uuid(0ca52e84-ba8f-11e1-87e8-63235527db9e)]
 interface nsITimezoneChangedCb : nsISupports 
 {
-  void onTimezoneChanged(in long aTimezoneOffset);
+  void onTimezoneChanged(in PRInt32 aTimezoneOffset);
 };
 
 %{C++
 #define NS_ALARMHALSERVICE_CID { 0x7dafea4c, 0x7163, 0x4b70, { 0x95, 0x4e, 0x5a, 0xd4, 0x09, 0x94, 0x83, 0xd7 } }
 #define ALARMHALSERVICE_CONTRACTID "@mozilla.org/alarmHalService;1"
 %}
 
 [scriptable, builtinclass, uuid(057b1ee4-f696-486d-bd55-205e21e88fab)]
 interface nsIAlarmHalService : nsISupports
 {
-  bool setAlarm(in long aSeconds, in long aNanoseconds);
+  bool setAlarm(in PRInt32 aSeconds, in PRInt32 aNanoseconds);
   void setAlarmFiredCb(in nsIAlarmFiredCb aAlarmFiredCb);
   void setTimezoneChangedCb(in nsITimezoneChangedCb aTimezoneChangedCb);
 };
 
 
 
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -175,18 +175,23 @@ let DOMApplicationRegistry = {
           if (aCallback)
             aCallback(null);
           return;
         }
 
         // Read json file into a string
         let data = null;
         try {
-          data = JSON.parse(NetUtil.readInputStreamToString(aStream,
-                                                            aStream.available()) || "");
+          // Obtain a converter to read from a UTF-8 encoded input stream.
+          let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
+                          .createInstance(Ci.nsIScriptableUnicodeConverter);
+          converter.charset = "UTF-8";
+
+          data = JSON.parse(converter.ConvertToUnicode(NetUtil.readInputStreamToString(aStream,
+                                                            aStream.available()) || ""));
           aStream.close();
           if (aCallback)
             aCallback(data);
         } catch (ex) {
           Cu.reportError("DOMApplicationRegistry: Could not parse JSON: " + ex);
           if (aCallback)
             aCallback(null);
         }
--- a/dom/base/nsIScriptGlobalObject.h
+++ b/dom/base/nsIScriptGlobalObject.h
@@ -115,17 +115,18 @@ public:
    */
   virtual void SetScriptsEnabled(bool aEnabled, bool aFireTimeouts) = 0;
 
   /**
    * Handle a script error.  Generally called by a script context.
    */
   virtual nsresult HandleScriptError(nsScriptErrorEvent *aErrorEvent,
                                      nsEventStatus *aEventStatus) {
-    return NS_HandleScriptError(this, aErrorEvent, aEventStatus);
+    NS_ENSURE_STATE(NS_HandleScriptError(this, aErrorEvent, aEventStatus));
+    return NS_OK;
   }
 
   virtual bool IsBlackForCC() { return false; }
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptGlobalObject,
                               NS_ISCRIPTGLOBALOBJECT_IID)
 
--- a/dom/bindings/test/test_sequence_wrapping.html
+++ b/dom/bindings/test/test_sequence_wrapping.html
@@ -14,38 +14,47 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"></p>
 <div id="content" style="display: none">
   <canvas width="1" height="1" id="c"></canvas>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 775852 **/
-var gl = $("c").getContext("experimental-webgl");
-var setterCalled = false;
+function doTest() {
+  try {
+    var gl = $("c").getContext("experimental-webgl");
+  } catch (e) {
+    // No WebGL support on MacOS 10.5.  Just skip this test
+    todo(false, "WebGL not supported");
+    return;
+  }
+  var setterCalled = false;
 
-extLength = gl.getSupportedExtensions().length;
-ok(extLength > 0,
-   "This test won't work right if we have no supported extensions");
+  extLength = gl.getSupportedExtensions().length;
+  ok(extLength > 0,
+     "This test won't work right if we have no supported extensions");
 
-Object.defineProperty(Array.prototype, "0",
-  {
-    set: function(val) {
-           setterCalled = true;
-         }
-  });
+  Object.defineProperty(Array.prototype, "0",
+    {
+      set: function(val) {
+             setterCalled = true;
+           }
+    });
 
-// Test that our property got defined correctly
-var arr = []
-arr[0] = 5;
-is(setterCalled, true, "Setter should be called when setting prop on array");
+  // Test that our property got defined correctly
+  var arr = []
+  arr[0] = 5;
+  is(setterCalled, true, "Setter should be called when setting prop on array");
+
+  setterCalled = false;
 
-setterCalled = false;
+  is(gl.getSupportedExtensions().length, extLength,
+     "We should still have the same number of extensions");
 
-is(gl.getSupportedExtensions().length, extLength,
-   "We should still have the same number of extensions");
-
-is(setterCalled, false,
-   "Setter should not be called when getting supported extensions");
+  is(setterCalled, false,
+     "Setter should not be called when getting supported extensions");
+}
+doTest();
 </script>
 </pre>
 </body>
 </html>
--- a/dom/interfaces/canvas/nsIDOMCanvasRenderingContext2D.idl
+++ b/dom/interfaces/canvas/nsIDOMCanvasRenderingContext2D.idl
@@ -178,31 +178,35 @@ enum CanvasMultiGetterType {
   // pixel manipulation
   // ImageData getImageData (in float x, in float y, in float width, in float height);
   // void putImageData (in ImageData d, in float x, in float y);
   // ImageData = { width: #, height: #, data: [r, g, b, a, ...] }
 
   [implicit_jscontext]
   nsIDOMImageData getImageData(in double sx, in double sy, in double sw, in double sh);
 
-  // This is just a dummy function; for JS, it is implemented as a quickstub
-  // that call the _explicit methods below.  Native callers should use the
-  // _explicit method directly.
-  void putImageData();
+
+  // void putImageData(ImageData imagedata, double dx, double dy);
+  // void putImageDataHD(ImageData imagedata, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight);
+  // We use jsval for the imageData because that's what our C++ code wants
+  [implicit_jscontext, optional_argc]
+  void putImageData(in jsval imageData, in double dx, in double dy,
+                    [optional] in double dirtyX, [optional] in double dirtyY,
+                    [optional] in double dirtyWidth,
+                    [optional] in double dirtyHeight);
 
   // dataLen must be == width*height*4 in this call
   [noscript] void putImageData_explicit(in long x, in long y, in unsigned long width, in unsigned long height,
                                         [array, size_is(dataLen)] in octet dataPtr, in unsigned long dataLen, in boolean hasDirtyRect,
                                         in long dirtyX, in long dirtyY, in long dirtyWidth, in long dirtyHeight);
 
-  // ImageData createImageData(in float w, in float h);
-  // Note: this is basically script-only (and really, quickstub-only).  Native callers
-  // should just use the noscript 'explicit' get/put methods above, instead of using
-  // a separate ImageData object.
-  void createImageData();
+  // ImageData createImageData(double w, double h);
+  // ImageData createImageData(ImageData data);
+  [implicit_jscontext, optional_argc]
+  nsIDOMImageData createImageData(in jsval arg1, [optional] in jsval arg2);
 
   // image smoothing mode -- if disabled, images won't be smoothed
   // if scaled.
   attribute boolean mozImageSmoothingEnabled;
 
   // Show the caret if appropriate when drawing
   const unsigned long DRAWWINDOW_DRAW_CARET   = 0x01;
   // Don't flush pending layout notifications that could otherwise
--- a/dom/interfaces/css/nsIDOMCSS2Properties.idl
+++ b/dom/interfaces/css/nsIDOMCSS2Properties.idl
@@ -9,17 +9,17 @@
  * The nsIDOMCSS2Properties interface is a datatype for additional
  * reflection of data already provided in nsIDOMCSSStyleDeclaration in
  * the Document Object Model.
  *
  * For more information on this interface please see
  * http://www.w3.org/TR/DOM-Level-2-Style
  */
 
-[builtinclass, scriptable, uuid(492673d6-039b-4d94-a598-dbf82abc174f)]
+[builtinclass, scriptable, uuid(243898eb-0e13-416d-9a2e-33af084985ed)]
 interface nsIDOMCSS2Properties : nsISupports
 {
            attribute DOMString        background;
                                         // raises(DOMException) on setting
 
            attribute DOMString        backgroundAttachment;
                                         // raises(DOMException) on setting
 
@@ -493,16 +493,19 @@ interface nsIDOMCSS2Properties : nsISupp
                                         // raises(DOMException) on setting
 
            attribute DOMString        MozColumnCount;
                                         // raises(DOMException) on setting
 
            attribute DOMString        MozColumnWidth;
                                         // raises(DOMException) on setting
 
+           attribute DOMString        MozColumnFill;
+                                        // raises(DOMException) on setting
+
            attribute DOMString        MozColumnGap;
                                         // raises(DOMException) on setting
 
            attribute DOMString        MozFloatEdge;
                                         // raises(DOMException) on setting
 
            attribute DOMString        MozFontFeatureSettings;
                                         // raises(DOMException) on setting
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -531,27 +531,27 @@ nsresult
 nsNPAPIPlugin::RetainStream(NPStream *pstream, nsISupports **aRetainedPeer)
 {
   if (!aRetainedPeer)
     return NS_ERROR_NULL_POINTER;
 
   *aRetainedPeer = NULL;
 
   if (!pstream || !pstream->ndata)
-    return NPERR_INVALID_PARAM;
+    return NS_ERROR_NULL_POINTER;
 
   nsNPAPIStreamWrapper* streamWrapper = static_cast<nsNPAPIStreamWrapper*>(pstream->ndata);
   nsNPAPIPluginStreamListener* listener = streamWrapper->GetStreamListener();
   if (!listener) {
-    return NPERR_GENERIC_ERROR;
+    return NS_ERROR_NULL_POINTER;
   }
 
   nsIStreamListener* streamListener = listener->GetStreamListenerPeer();
   if (!streamListener) {
-    return NPERR_GENERIC_ERROR;
+    return NS_ERROR_NULL_POINTER;
   }
 
   *aRetainedPeer = streamListener;
   NS_ADDREF(*aRetainedPeer);
   return NS_OK;
 }
 
 // Create a new NPP GET or POST (given in the type argument) url
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -1490,58 +1490,62 @@ void nsPluginInstanceOwner::RemoveFromCA
 }
 
 void nsPluginInstanceOwner::RenderCoreAnimation(CGContextRef aCGContext,
                                                 int aWidth, int aHeight)
 {
   if (aWidth == 0 || aHeight == 0)
     return;
 
+  if (!mCARenderer) {
+    mCARenderer = new nsCARenderer();
+  }
+
   if (!mIOSurface ||
       (mIOSurface->GetWidth() != (size_t)aWidth ||
        mIOSurface->GetHeight() != (size_t)aHeight)) {
     mIOSurface = nullptr;
 
     // If the renderer is backed by an IOSurface, resize it as required.
-    mIOSurface = nsIOSurface::CreateIOSurface(aWidth, aHeight);
+    mIOSurface = MacIOSurface::CreateIOSurface(aWidth, aHeight);
     if (mIOSurface) {
-      nsRefPtr<nsIOSurface> attachSurface = nsIOSurface::LookupSurface(
+      RefPtr<MacIOSurface> attachSurface = MacIOSurface::LookupSurface(
                                               mIOSurface->GetIOSurfaceID());
       if (attachSurface) {
-        mCARenderer.AttachIOSurface(attachSurface);
+        mCARenderer->AttachIOSurface(attachSurface);
       } else {
         NS_ERROR("IOSurface attachment failed");
         mIOSurface = nullptr;
       }
     }
   }
 
   if (!mColorProfile) {
     mColorProfile = CreateSystemColorSpace();
   }
 
-  if (mCARenderer.isInit() == false) {
+  if (mCARenderer->isInit() == false) {
     void *caLayer = NULL;
     nsresult rv = mInstance->GetValueFromPlugin(NPPVpluginCoreAnimationLayer, &caLayer);
     if (NS_FAILED(rv) || !caLayer) {
       return;
     }
 
     // We don't run Flash in-process so we can unconditionally disallow
     // the offliner renderer.
-    mCARenderer.SetupRenderer(caLayer, aWidth, aHeight, DISALLOW_OFFLINE_RENDERER);
+    mCARenderer->SetupRenderer(caLayer, aWidth, aHeight, DISALLOW_OFFLINE_RENDERER);
 
     // Setting up the CALayer requires resetting the painting otherwise we
     // get garbage for the first few frames.
     FixUpPluginWindow(ePluginPaintDisable);
     FixUpPluginWindow(ePluginPaintEnable);
   }
 
   CGImageRef caImage = NULL;
-  nsresult rt = mCARenderer.Render(aWidth, aHeight, &caImage);
+  nsresult rt = mCARenderer->Render(aWidth, aHeight, &caImage);
   if (rt == NS_OK && mIOSurface && mColorProfile) {
     nsCARenderer::DrawSurfaceToCGContext(aCGContext, mIOSurface, mColorProfile,
                                          0, 0, aWidth, aHeight);
   } else if (rt == NS_OK && caImage != NULL) {
     // Significant speed up by resetting the scaling
     ::CGContextSetInterpolationQuality(aCGContext, kCGInterpolationNone );
     ::CGContextTranslateCTM(aCGContext, 0, aHeight);
     ::CGContextScaleCTM(aCGContext, 1.0, -1.0);
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -21,17 +21,17 @@
 #include "gfxRect.h"
 
 // X.h defines KeyPress
 #ifdef KeyPress
 #undef KeyPress
 #endif
 
 #ifdef XP_MACOSX
-#include "nsCoreAnimationSupport.h"
+#include "mozilla/gfx/QuartzSupport.h"
 #include <ApplicationServices/ApplicationServices.h>
 #endif
 
 class nsIInputStream;
 struct nsIntRect;
 class nsPluginDOMContextMenuListener;
 class nsObjectFrame;
 class nsDisplayListBuilder;
@@ -300,18 +300,18 @@ private:
   nsRefPtr<nsPluginHost>      mPluginHost;
   
 #ifdef XP_MACOSX
   NP_CGContext                              mCGPluginPortCopy;
 #ifndef NP_NO_QUICKDRAW
   NP_Port                                   mQDPluginPortCopy;
 #endif
   PRInt32                                   mInCGPaintLevel;
-  nsRefPtr<nsIOSurface>                     mIOSurface;
-  nsCARenderer                              mCARenderer;
+  mozilla::RefPtr<MacIOSurface>             mIOSurface;
+  mozilla::RefPtr<nsCARenderer>             mCARenderer;
   CGColorSpaceRef                           mColorProfile;
   static nsCOMPtr<nsITimer>                *sCATimer;
   static nsTArray<nsPluginInstanceOwner*>  *sCARefreshListeners;
   bool                                      mSentInitialTopLevelWindowEvent;
 #endif
 
   // Initially, the event loop nesting level we were created on, it's updated
   // if we detect the appshell is on a lower level as long as we're not stopped.
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -901,54 +901,58 @@ PluginInstanceChild::AnswerNPP_HandleEve
                                                      int16_t* handled)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
     AssertPluginThread();
 
     PaintTracker pt;
 
     NPCocoaEvent evcopy = event.event;
-    nsRefPtr<nsIOSurface> surf = nsIOSurface::LookupSurface(surfaceid);
+    RefPtr<MacIOSurface> surf = MacIOSurface::LookupSurface(surfaceid);
     if (!surf) {
         NS_ERROR("Invalid IOSurface.");
         *handled = false;
         return false;
     }
 
+    if (!mCARenderer) {
+      mCARenderer = new nsCARenderer();
+    }
+
     if (evcopy.type == NPCocoaEventDrawRect) {
-        mCARenderer.AttachIOSurface(surf);
-        if (!mCARenderer.isInit()) {
+        mCARenderer->AttachIOSurface(surf);
+        if (!mCARenderer->isInit()) {
             void *caLayer = nullptr;
             NPError result = mPluginIface->getvalue(GetNPP(), 
                                      NPPVpluginCoreAnimationLayer,
                                      &caLayer);
             
             if (result != NPERR_NO_ERROR || !caLayer) {
                 PLUGIN_LOG_DEBUG(("Plugin requested CoreAnimation but did not "
                                   "provide CALayer."));
                 *handled = false;
                 return false;
             }
 
-            mCARenderer.SetupRenderer(caLayer, mWindow.width, mWindow.height,
+            mCARenderer->SetupRenderer(caLayer, mWindow.width, mWindow.height,
                             GetQuirks() & PluginModuleChild::QUIRK_ALLOW_OFFLINE_RENDERER ?
                             ALLOW_OFFLINE_RENDERER : DISALLOW_OFFLINE_RENDERER);
 
             // Flash needs to have the window set again after this step
             if (mPluginIface->setwindow)
                 (void) mPluginIface->setwindow(&mData, &mWindow);
         }
     } else {
         PLUGIN_LOG_DEBUG(("Invalid event type for "
                           "AnswerNNP_HandleEvent_IOSurface."));
         *handled = false;
         return false;
     } 
 
-    mCARenderer.Render(mWindow.width, mWindow.height, nullptr);
+    mCARenderer->Render(mWindow.width, mWindow.height, nullptr);
 
     return true;
 
 }
 
 #else
 bool
 PluginInstanceChild::AnswerNPP_HandleEvent_IOSurface(const NPRemoteEvent& event,
--- a/dom/plugins/ipc/PluginInstanceChild.h
+++ b/dom/plugins/ipc/PluginInstanceChild.h
@@ -12,17 +12,17 @@
 #include "mozilla/plugins/StreamNotifyChild.h"
 #include "mozilla/plugins/PPluginSurfaceChild.h"
 #include "mozilla/ipc/CrossProcessMutex.h"
 #include "nsClassHashtable.h"
 #if defined(OS_WIN)
 #include "mozilla/gfx/SharedDIBWin.h"
 #elif defined(MOZ_WIDGET_COCOA)
 #include "PluginUtilsOSX.h"
-#include "nsCoreAnimationSupport.h"
+#include "mozilla/gfx/QuartzSupport.h"
 #include "base/timer.h"
 
 using namespace mozilla::plugins::PluginUtilsOSX;
 #endif
 
 #include "npfunctions.h"
 #include "nsAutoPtr.h"
 #include "nsTArray.h"
@@ -415,25 +415,25 @@ private:
       PRUint16        doublePass;
       HDC             hdc;
       HBITMAP         bmp;
     } mAlphaExtract;
 #endif // defined(OS_WIN)
 #if defined(MOZ_WIDGET_COCOA)
 private:
 #if defined(__i386__)
-    NPEventModel          mEventModel;
+    NPEventModel                  mEventModel;
 #endif
-    CGColorSpaceRef       mShColorSpace;
-    CGContextRef          mShContext;
-    nsCARenderer          mCARenderer;
-    void                 *mCGLayer;
+    CGColorSpaceRef               mShColorSpace;
+    CGContextRef                  mShContext;
+    mozilla::RefPtr<nsCARenderer> mCARenderer;
+    void                         *mCGLayer;
 
     // Core Animation drawing model requires a refresh timer.
-    uint32_t mCARefreshTimer;
+    uint32_t                      mCARefreshTimer;
 
 public:
     const NPCocoaEvent* getCurrentEvent() {
         return mCurrentEvent;
     }
   
     bool CGDraw(CGContextRef ref, nsIntRect aUpdateRect);
 
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -586,17 +586,17 @@ PluginInstanceParent::RecvShow(const NPR
             return false;
         }
         surface = gfxSharedImageSurface::Open(newSurface.get_Shmem());
     }
 #ifdef XP_MACOSX
     else if (newSurface.type() == SurfaceDescriptor::TIOSurfaceDescriptor) {
         IOSurfaceDescriptor iodesc = newSurface.get_IOSurfaceDescriptor();
     
-        nsRefPtr<nsIOSurface> newIOSurface = nsIOSurface::LookupSurface(iodesc.surfaceId());
+        RefPtr<MacIOSurface> newIOSurface = MacIOSurface::LookupSurface(iodesc.surfaceId());
 
         if (!newIOSurface) {
             NS_WARNING("Got bad IOSurfaceDescriptor in RecvShow");
             return false;
         }
       
         if (mFrontIOSurface)
             *prevSurface = IOSurfaceDescriptor(mFrontIOSurface->GetIOSurfaceID());
@@ -704,17 +704,17 @@ PluginInstanceParent::HandleGUIEvent(con
     return NS_OK;
 }
 #endif
 
 nsresult
 PluginInstanceParent::GetImageContainer(ImageContainer** aContainer)
 {
 #ifdef XP_MACOSX
-    nsIOSurface* ioSurface = NULL;
+    MacIOSurface* ioSurface = NULL;
   
     if (mFrontIOSurface) {
       ioSurface = mFrontIOSurface;
     } else if (mIOSurface) {
       ioSurface = mIOSurface;
     }
 
     if (!mFrontSurface && !ioSurface)
@@ -1014,17 +1014,17 @@ PluginInstanceParent::NPP_SetWindow(cons
     window.clipRect = aWindow->clipRect; // MacOS specific
     window.type = aWindow->type;
 #endif
 
 #if defined(XP_MACOSX)
     if (mShWidth != window.width || mShHeight != window.height) {
         if (mDrawingModel == NPDrawingModelCoreAnimation || 
             mDrawingModel == NPDrawingModelInvalidatingCoreAnimation) {
-            mIOSurface = nsIOSurface::CreateIOSurface(window.width, window.height);
+            mIOSurface = MacIOSurface::CreateIOSurface(window.width, window.height);
         } else if (mShWidth * mShHeight != window.width * window.height) {
             if (mShWidth != 0 && mShHeight != 0) {
                 DeallocShmem(mShSurface);
                 mShWidth = 0;
                 mShHeight = 0;
             }
 
             if (window.width != 0 && window.height != 0) {
--- a/dom/plugins/ipc/PluginInstanceParent.h
+++ b/dom/plugins/ipc/PluginInstanceParent.h
@@ -9,17 +9,17 @@
 
 #include "mozilla/plugins/PPluginInstanceParent.h"
 #include "mozilla/plugins/PluginScriptableObjectParent.h"
 #if defined(OS_WIN)
 #include "mozilla/gfx/SharedDIBWin.h"
 #include <d3d10_1.h>
 #include "nsRefPtrHashtable.h"
 #elif defined(MOZ_WIDGET_COCOA)
-#include "nsCoreAnimationSupport.h"
+#include "mozilla/gfx/QuartzSupport.h"
 #endif
 
 #include "npfunctions.h"
 #include "nsAutoPtr.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsRect.h"
 #include "gfxASurface.h"
@@ -341,18 +341,18 @@ private:
     nsRefPtrHashtable<nsPtrHashKey<void>, ID3D10Texture2D> mTextureMap;
 #endif // defined(XP_WIN)
 #if defined(MOZ_WIDGET_COCOA)
 private:
     Shmem                  mShSurface; 
     uint16_t               mShWidth;
     uint16_t               mShHeight;
     CGColorSpaceRef        mShColorSpace;
-    nsRefPtr<nsIOSurface> mIOSurface;
-    nsRefPtr<nsIOSurface> mFrontIOSurface;
+    RefPtr<MacIOSurface> mIOSurface;
+    RefPtr<MacIOSurface> mFrontIOSurface;
 #endif // definied(MOZ_WIDGET_COCOA)
 
     // ObjectFrame layer wrapper
     nsRefPtr<gfxASurface>    mFrontSurface;
     // For windowless+transparent instances, this surface contains a
     // "pretty recent" copy of the pixels under its <object> frame.
     // On the plugin side, we use this surface to avoid doing alpha
     // recovery when possible.  This surface is created and owned by
--- a/dom/plugins/ipc/PluginUtilsOSX.h
+++ b/dom/plugins/ipc/PluginUtilsOSX.h
@@ -4,17 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef dom_plugins_PluginUtilsOSX_h
 #define dom_plugins_PluginUtilsOSX_h 1
 
 #include "npapi.h"
 #include "nsRect.h"
-#include "nsCoreAnimationSupport.h"
+#include "mozilla/gfx/QuartzSupport.h"
 
 namespace mozilla {
 namespace plugins {
 namespace PluginUtilsOSX {
 
 // Need to call back into the browser's message loop to process event.
 typedef void (*RemoteProcessEvents) (void*);
 
@@ -56,18 +56,18 @@ public:
   bool InitFrontSurface(size_t aWidth, size_t aHeight, AllowOfflineRendererEnum aAllowOfflineRenderer);
   void Render();
   void SwapSurfaces();
   void ClearFrontSurface();
   void ClearBackSurface();
 
 private:
   void *mCALayer;
-  nsRefPtr<nsCARenderer> mCARenderer;
-  nsRefPtr<nsIOSurface> mFrontSurface;
-  nsRefPtr<nsIOSurface> mBackSurface;
+  RefPtr<nsCARenderer> mCARenderer;
+  RefPtr<MacIOSurface> mFrontSurface;
+  RefPtr<MacIOSurface> mBackSurface;
 };
 
 } // namespace PluginUtilsOSX
 } // namespace plugins
 } // namespace mozilla
 
 #endif //dom_plugins_PluginUtilsOSX_h
--- a/dom/plugins/ipc/PluginUtilsOSX.mm
+++ b/dom/plugins/ipc/PluginUtilsOSX.mm
@@ -305,17 +305,17 @@ void nsDoubleBufferCARenderer::SetCALaye
 }
 
 bool nsDoubleBufferCARenderer::InitFrontSurface(size_t aWidth, size_t aHeight,
                                                 AllowOfflineRendererEnum aAllowOfflineRenderer) {
   if (!mCALayer) {
     return false;
   }
 
-  mFrontSurface = nsIOSurface::CreateIOSurface(aWidth, aHeight);
+  mFrontSurface = MacIOSurface::CreateIOSurface(aWidth, aHeight);
   if (!mFrontSurface) {
     mCARenderer = nullptr;
     return false;
   }
 
   if (!mCARenderer) {
     mCARenderer = new nsCARenderer();
     if (!mCARenderer) {
@@ -346,17 +346,17 @@ void nsDoubleBufferCARenderer::Render() 
   if (!HasFrontSurface() || !mCARenderer) {
     return;
   }
 
   mCARenderer->Render(GetFrontSurfaceWidth(), GetFrontSurfaceHeight(), nullptr);
 }
 
 void nsDoubleBufferCARenderer::SwapSurfaces() {
-  nsRefPtr<nsIOSurface> prevFrontSurface = mFrontSurface;
+  RefPtr<MacIOSurface> prevFrontSurface = mFrontSurface;
   mFrontSurface = mBackSurface;
   mBackSurface = prevFrontSurface;
 
   if (mFrontSurface) {
     mCARenderer->AttachIOSurface(mFrontSurface);
   }
 }
 
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -454,20 +454,21 @@ const MSISDN_MAX_NUMBER_SIZE_BYTES = 10;
 // READ_RECORD mode,  TS 102.221
 const READ_RECORD_ABSOLUTE_MODE = 4;
 
 // GET_RESPONSE mandatory response size for EF, see TS 51.011 clause 9, 
 // 'Response data in case of an EF.'
 const GET_RESPONSE_EF_SIZE_BYTES = 15;
 
 // EF path
-const EF_PATH_MF_SIM = "3f00";
+const EF_PATH_MF_SIM       = "3f00";
 const EF_PATH_DF_PHONEBOOK = "5f3a";
-const EF_PATH_DF_TELECOM = "7f10";
-const EF_PATH_DF_GSM = "7f20";
+const EF_PATH_DF_TELECOM   = "7f10";
+const EF_PATH_DF_GSM       = "7f20";
+const EF_PATH_ADF_USIM     = "7fff";
 
 // Status code of sw1 for ICC I/O,
 // see GSM11.11 and TS 51.011 clause 9.4, and ISO 7816-4
 const ICC_STATUS_NORMAL_ENDING = 0x90;
 const ICC_STATUS_NORMAL_ENDING_WITH_EXTRA = 0x91;
 const ICC_STATUS_WITH_SIM_DATA = 0x9e;
 const ICC_STATUS_WITH_RESPONSE_DATA = 0x9f;
 const ICC_STATUS_ERROR_WRONG_LENGTH = 0x67;
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -952,46 +952,48 @@ let RIL = {
     Buf.writeString(options.enabled ? "1" : "0");
     Buf.writeString(options.password);
     Buf.writeString(options.serviceClass.toString());
     Buf.sendParcel();
   },
 
   /**
    *  Request an ICC I/O operation.
-   * 
+   *
    *  See TS 27.007 "restricted SIM" operation, "AT Command +CRSM".
    *  The sequence is in the same order as how libril reads this parcel,
    *  see the struct RIL_SIM_IO_v5 or RIL_SIM_IO_v6 defined in ril.h
    *
-   *  @param command 
+   *  @param command
    *         The I/O command, one of the ICC_COMMAND_* constants.
    *  @param fileId
    *         The file to operate on, one of the ICC_EF_* constants.
    *  @param pathId
    *         String type, check the 'pathid' parameter from TS 27.007 +CRSM.
    *  @param p1, p2, p3
    *         Arbitrary integer parameters for the command.
    *  @param data
    *         String parameter for the command.
    *  @param pin2 [optional]
    *         String containing the PIN2.
+   *  @param aid
+   *         String for the AID.
    */
   iccIO: function iccIO(options) {
     let token = Buf.newParcel(REQUEST_SIM_IO, options);
     Buf.writeUint32(options.command);
     Buf.writeUint32(options.fileId);
     Buf.writeString(options.pathId);
     Buf.writeUint32(options.p1);
     Buf.writeUint32(options.p2);
     Buf.writeUint32(options.p3);
     Buf.writeString(options.data);
-    if (options.pin2 != null) {
-      Buf.writeString(options.pin2);
-    }
+    Buf.writeString(options.pin2 ? options.pin2 : null);
+    let appIndex = this.iccStatus.gsmUmtsSubscriptionAppIndex;
+    Buf.writeString(this.iccStatus.apps[appIndex].aid);
     Buf.sendParcel();
   },
 
   /**
    * Fetch ICC records.
    */
   fetchICCRecords: function fetchICCRecords() {
     this.getIMSI();
@@ -1011,17 +1013,18 @@ let RIL = {
 
   getIMSI: function getIMSI() {
     if (RILQUIRKS_V5_LEGACY) {
       Buf.simpleRequest(REQUEST_GET_IMSI);
       return;
     }
     let token = Buf.newParcel(REQUEST_GET_IMSI);
     Buf.writeUint32(1);
-    Buf.writeString(null);
+    let appIndex = this.iccStatus.gsmUmtsSubscriptionAppIndex;
+    Buf.writeString(this.iccStatus.apps[appIndex].aid);
     Buf.sendParcel();
   },
 
   /**
    * Read the MSISDN from the ICC.
    */
   getMSISDN: function getMSISDN() {
     function callback() {
@@ -1045,17 +1048,17 @@ let RIL = {
       if (this.iccInfo.msisdn) {
         this._handleICCInfoChange();
       }
     }
 
     this.iccIO({
       command:   ICC_COMMAND_GET_RESPONSE,
       fileId:    ICC_EF_MSISDN,
-      pathId:    EF_PATH_MF_SIM + EF_PATH_DF_TELECOM,
+      pathId:    EF_PATH_MF_SIM + EF_PATH_ADF_USIM,
       p1:        0, // For GET_RESPONSE, p1 = 0
       p2:        0, // For GET_RESPONSE, p2 = 0
       p3:        GET_RESPONSE_EF_SIZE_BYTES,
       data:      null,
       pin2:      null,
       type:      EF_TYPE_LINEAR_FIXED,
       callback:  callback,
     });
@@ -1088,17 +1091,17 @@ let RIL = {
         if (DEBUG) debug("MCC: " + this.iccInfo.mcc + " MNC: " + this.iccInfo.mnc);
         this._handleICCInfoChange();
       }
     }
 
     this.iccIO({
       command:   ICC_COMMAND_GET_RESPONSE,
       fileId:    ICC_EF_AD,
-      pathId:    EF_PATH_MF_SIM + EF_PATH_DF_GSM,
+      pathId:    EF_PATH_MF_SIM + EF_PATH_ADF_USIM,
       p1:        0, // For GET_RESPONSE, p1 = 0
       p2:        0, // For GET_RESPONSE, p2 = 0
       p3:        GET_RESPONSE_EF_SIZE_BYTES,
       data:      null,
       pin2:      null,
       type:      EF_TYPE_TRANSPARENT,
       callback:  callback,
     });
@@ -1140,17 +1143,17 @@ let RIL = {
         }
         debug("UST: " + str);
       }
     }
 
     this.iccIO({
       command:   ICC_COMMAND_GET_RESPONSE,
       fileId:    ICC_EF_UST,
-      pathId:    EF_PATH_MF_SIM + EF_PATH_DF_GSM,
+      pathId:    EF_PATH_MF_SIM + EF_PATH_ADF_USIM,
       p1:        0, // For GET_RESPONSE, p1 = 0
       p2:        0, // For GET_RESPONSE, p2 = 0
       p3:        GET_RESPONSE_EF_SIZE_BYTES,
       data:      null,
       pin2:      null,
       type:      EF_TYPE_TRANSPARENT,
       callback:  callback,
     });
@@ -1176,17 +1179,17 @@ let RIL = {
     let length = Buf.readUint32();
 
     let alphaLen = options.recordSize - MSISDN_FOOTER_SIZE_BYTES;
     let alphaId = GsmPDUHelper.readAlphaIdentifier(alphaLen);
 
     let numLen = GsmPDUHelper.readHexOctet();
     if (numLen != 0xff) {
       if (numLen > MSISDN_MAX_NUMBER_SIZE_BYTES) {
-        debug("ICC_EF_FDN: invalid length of BCD number/SSC contents - " + numLen);
+        debug("invalid length of BCD number/SSC contents - " + numLen);
         return;
       }
 
       if (addCallback) {
         addCallback.call(this, {alphaId: alphaId,
                                 number: GsmPDUHelper.readDiallingNumber(numLen)});
       }
 
@@ -1283,17 +1286,17 @@ let RIL = {
       };
       this.parseDiallingNumber(options, add, finish);
     }
 
     this.iccInfo.adn = [];
     this.iccIO({
       command:   ICC_COMMAND_GET_RESPONSE,
       fileId:    options.fileId,
-      pathId:    EF_PATH_MF_SIM + EF_PATH_DF_TELECOM,
+      pathId:    EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK,
       p1:        0, // For GET_RESPONSE, p1 = 0
       p2:        0, // For GET_RESPONSE, p2 = 0
       p3:        GET_RESPONSE_EF_SIZE_BYTES,
       data:      null,
       pin2:      null,
       type:      EF_TYPE_LINEAR_FIXED,
       callback:  callback,
       loadAll:   true,
@@ -1320,17 +1323,17 @@ let RIL = {
       };
 
       this.parseDiallingNumber(options, parseCallback);
     }
 
     this.iccIO({
       command:   ICC_COMMAND_GET_RESPONSE,
       fileId:    ICC_EF_MBDN,
-      pathId:    EF_PATH_MF_SIM + EF_PATH_DF_GSM,
+      pathId:    EF_PATH_MF_SIM + EF_PATH_ADF_USIM,
       p1:        0, // For GET_RESPONSE, p1 = 0
       p2:        0, // For GET_RESPONSE, p2 = 0
       p3:        GET_RESPONSE_EF_SIZE_BYTES,
       data:      null,
       pin2:      null,
       type:      EF_TYPE_LINEAR_FIXED,
       callback:  callback,
     });
@@ -3213,20 +3216,18 @@ RIL[REQUEST_SETUP_DATA_CALL] = function 
     this.getDataCallList();
     return;
   }
   // Pass `options` along. That way we retain the APN and other info about
   // how the data call was set up.
   this[REQUEST_DATA_CALL_LIST](length, options);
 };
 RIL[REQUEST_SIM_IO] = function REQUEST_SIM_IO(length, options) {
-  if (options.rilRequestError) {
-    return;
-  }
-
+  // Don't need to read rilRequestError since we can know error status from
+  // sw1 and sw2.
   let sw1 = Buf.readUint32();
   let sw2 = Buf.readUint32();
   if (sw1 != ICC_STATUS_NORMAL_ENDING) {
     // See GSM11.11, TS 51.011 clause 9.4, and ISO 7816-4 for the error
     // description.
     if (DEBUG) {
       debug("ICC I/O Error EF id = " + options.fileId.toString(16) +
             " command = " + options.command.toString(16) +
--- a/dom/tests/mochitest/chrome/test_sandbox_bindings.xul
+++ b/dom/tests/mochitest/chrome/test_sandbox_bindings.xul
@@ -43,16 +43,36 @@ https://bugzilla.mozilla.org/show_bug.cg
         ok(false, "'XMLHttpRequest()' shouldn't throw in a sandbox");
       }
       try {
         var canvas = Components.utils.evalInSandbox("document.createElement('canvas').getContext('2d')", sandbox);
         is(canvas.DRAWWINDOW_DRAW_CARET, CanvasRenderingContext2D.DRAWWINDOW_DRAW_CARET, "Constants should be defined on DOM objects in a sandbox");
       } catch (e) {
         ok(false, "'document.createElement('canvas').getContext('2D')' shouldn't throw in a sandbox");
       }
+      try {
+        var ctx = Components.utils.evalInSandbox("var ctx = document.createElement('canvas').getContext('2d'); ctx.foopy = 5; ctx", sandbox);
+        ok(!("foopy" in ctx), "We should have an Xray here");
+        var data = ctx.createImageData(1, 1);
+        for (var i = 0; i < data.data.length; ++i) {
+          // Watch out for premultiplied bits... just set all the alphas to 255
+          if (i % 4 == 3) {
+            data.data[i] = 255;
+          } else {
+            data.data[i] = i;
+          }
+        }
+        ctx.putImageData(data, 0, 0);
+        var data2 = ctx.getImageData(0, 0, 1, 1);
+        is(data2.data.length, data.data.length, "Lengths must match");
+        for (i = 0; i < data.data.length; ++i)
+          is(data.data[i], data2.data[i], "Data at " + i + " should match");
+      } catch (e) {
+        ok(false, "Imagedata manipulation via an Xray shouldn't throw " + e);
+      }
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addLoadEvent(doTest);
   ]]>
   </script>
 </window>
--- a/editor/reftests/reftest.list
+++ b/editor/reftests/reftest.list
@@ -91,8 +91,10 @@ skip-if(Android) == 462758-grabbers-resi
 == readwrite-editable.html readwrite-editable-ref.html
 == readonly-non-editable.html readonly-non-editable-ref.html
 == readonly-editable.html readonly-editable-ref.html
 == dynamic-overflow-change.html dynamic-overflow-change-ref.html
 == 694880-1.html 694880-ref.html
 == 694880-2.html 694880-ref.html
 == 694880-3.html 694880-ref.html
 == 388980-1.html 388980-1-ref.html
+needs-focus == spellcheck-superscript-1.html spellcheck-superscript-1-ref.html
+needs-focus != spellcheck-superscript-2.html spellcheck-superscript-2-ref.html
new file mode 100644
--- /dev/null
+++ b/editor/reftests/spellcheck-superscript-1-ref.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<textarea spellcheck=false>&sup1; &sup2; &sup3;</textarea>
+<script>document.body.firstChild.focus()</script>
new file mode 100644
--- /dev/null
+++ b/editor/reftests/spellcheck-superscript-1.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<textarea>&sup1; &sup2; &sup3;</textarea>
+<script>document.body.firstChild.focus()</script>
new file mode 100644
--- /dev/null
+++ b/editor/reftests/spellcheck-superscript-2-ref.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<textarea>&sup1; &sup2; &sup3; mispeled</textarea>
+<script>document.body.firstChild.focus()</script>
new file mode 100644
--- /dev/null
+++ b/editor/reftests/spellcheck-superscript-2.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<textarea spellcheck=false>&sup1; &sup2; &sup3; mispeled</textarea>
+<script>document.body.firstChild.focus()</script>
--- a/embedding/components/commandhandler/src/nsCommandManager.cpp
+++ b/embedding/components/commandhandler/src/nsCommandManager.cpp
@@ -33,25 +33,26 @@ nsCommandManager::nsCommandManager()
 
 nsCommandManager::~nsCommandManager()
 {
   /* destructor code */
 }
 
 
 static PLDHashOperator
-TraverseCommandObservers(const char* aKey, nsCOMArray<nsIObserver>* aObservers,
+TraverseCommandObservers(const char* aKey,
+                         nsCommandManager::ObserverList* aObservers,
                          void* aClosure)
 {
   nsCycleCollectionTraversalCallback *cb = 
     static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
 
-  PRInt32 i, numItems = aObservers->Count();
+  PRInt32 i, numItems = aObservers->Length();
   for (i = 0; i < numItems; ++i) {
-    cb->NoteXPCOMChild(aObservers->ObjectAt(i));
+    cb->NoteXPCOMChild(aObservers->ElementAt(i));
   }
 
   return PL_DHASH_NEXT;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsCommandManager)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCommandManager)
   tmp->mObserversTable.Clear();
@@ -85,26 +86,26 @@ nsCommandManager::Init(nsIDOMWindow *aWi
   mObserversTable.Init();
   return NS_OK;
 }
 
 /* void commandStatusChanged (in DOMString aCommandName, in long aChangeFlags); */
 NS_IMETHODIMP
 nsCommandManager::CommandStatusChanged(const char * aCommandName)
 {
-  nsCOMArray<nsIObserver>* commandObservers;
+  ObserverList* commandObservers;
   mObserversTable.Get(aCommandName, &commandObservers);
 
   if (commandObservers)
   {
     // XXX Should we worry about observers removing themselves from Observe()?
-    PRInt32 i, numItems = commandObservers->Count();
+    PRInt32 i, numItems = commandObservers->Length();
     for (i = 0; i < numItems;  ++i)
     {
-      nsCOMPtr<nsIObserver> observer = commandObservers->ObjectAt(i);
+      nsCOMPtr<nsIObserver> observer = commandObservers->ElementAt(i);
       // should we get the command state to pass here? This might be expensive.
       observer->Observe(NS_ISUPPORTS_CAST(nsICommandManager*, this),
                         aCommandName,
                         NS_LITERAL_STRING("command_status_changed").get());
     }
   }
 
   return NS_OK;
@@ -115,54 +116,51 @@ nsCommandManager::CommandStatusChanged(c
 #endif
 
 /* void addCommandObserver (in nsIObserver aCommandObserver, in wstring aCommandToObserve); */
 NS_IMETHODIMP
 nsCommandManager::AddCommandObserver(nsIObserver *aCommandObserver, const char *aCommandToObserve)
 {
   NS_ENSURE_ARG(aCommandObserver);
 
-  nsresult rv = NS_OK;
-
   // XXX todo: handle special cases of aCommandToObserve being null, or empty
 
   // for each command in the table, we make a list of observers for that command
-  nsCOMArray<nsIObserver>* commandObservers;
+  ObserverList* commandObservers;
   if (!mObserversTable.Get(aCommandToObserve, &commandObservers))
   {
-    nsAutoPtr<nsCOMArray<nsIObserver> > array(new nsCOMArray<nsIObserver>);
-    mObserversTable.Put(aCommandToObserve, array);
-
-    commandObservers = array.forget();
+    commandObservers = new ObserverList;
+    mObserversTable.Put(aCommandToObserve, commandObservers);
   }
 
   // need to check that this command observer hasn't already been registered
   PRInt32 existingIndex = commandObservers->IndexOf(aCommandObserver);
   if (existingIndex == -1)
-    rv = commandObservers->AppendObject(aCommandObserver);
+    commandObservers->AppendElement(aCommandObserver);
   else
     NS_WARNING("Registering command observer twice on the same command");
   
-  return rv;
+  return NS_OK;
 }
 
 /* void removeCommandObserver (in nsIObserver aCommandObserver, in wstring aCommandObserved); */
 NS_IMETHODIMP
 nsCommandManager::RemoveCommandObserver(nsIObserver *aCommandObserver, const char *aCommandObserved)
 {
   NS_ENSURE_ARG(aCommandObserver);
 
   // XXX todo: handle special cases of aCommandToObserve being null, or empty
 
-  nsCOMArray<nsIObserver>* commandObservers;
+  ObserverList* commandObservers;
   if (!mObserversTable.Get(aCommandObserved, &commandObservers))
     return NS_ERROR_UNEXPECTED;
 
-  return commandObservers->RemoveObject(aCommandObserver) ? NS_OK :
-                                                            NS_ERROR_FAILURE;
+  commandObservers->RemoveElement(aCommandObserver);
+
+  return NS_OK;
 }
 
 /* boolean isCommandSupported(in string aCommandName,
                               in nsIDOMWindow aTargetWindow); */
 NS_IMETHODIMP
 nsCommandManager::IsCommandSupported(const char *aCommandName,
                                      nsIDOMWindow *aTargetWindow,
                                      bool *outCommandSupported)
--- a/embedding/components/commandhandler/src/nsCommandManager.h
+++ b/embedding/components/commandhandler/src/nsCommandManager.h
@@ -21,16 +21,18 @@ template<class E> class nsCOMArray;
 
 class nsCommandManager :  public nsICommandManager,
                           public nsPICommandUpdater,
                        // public nsISecurityCheckedComponent,
                           public nsSupportsWeakReference
 
 {
 public:
+  typedef nsTArray<nsCOMPtr<nsIObserver> > ObserverList;
+
                         nsCommandManager();
   virtual               ~nsCommandManager();
 
   // nsISupports
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsCommandManager, nsICommandManager)
   
   // nsICommandManager
@@ -45,16 +47,15 @@ protected:
 
   nsresult  IsCallerChrome(bool *aIsCallerChrome);
   nsresult  GetControllerForCommand(const char * aCommand,
                                     nsIDOMWindow *aDirectedToThisWindow,
                                     nsIController** outController);
 
 
 protected:
-
-  nsClassHashtable<nsCharPtrHashKey, nsCOMArray<nsIObserver> > mObserversTable;
+  nsClassHashtable<nsCharPtrHashKey, ObserverList> mObserversTable;
 
   nsIDOMWindow*         mWindow;      // weak ptr. The window should always outlive us
 };
 
 
 #endif // nsCommandManager_h__
--- a/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
@@ -943,20 +943,19 @@ WordSplitState::IsSpecialWord()
 
 bool
 WordSplitState::ShouldSkipWord(PRInt32 aStart, PRInt32 aLength)
 {
   PRInt32 last = aStart + aLength;
 
   // check to see if the word contains a digit
   for (PRInt32 i = aStart; i < last; i ++) {
-    PRUnichar ch = mDOMWordText[i];
-    // XXX Shouldn't this be something a lot more complex, Unicode-based?
-    if (ch >= '0' && ch <= '9')
+    if (unicode::GetGenCategory(mDOMWordText[i]) == nsIUGenCategory::kNumber) {
       return true;
+    }
   }
 
   // not special
   return false;
 }
 
 // mozInlineSpellWordUtil::SplitDOMWord
 
--- a/gfx/2d/DrawTargetCG.cpp
+++ b/gfx/2d/DrawTargetCG.cpp
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "DrawTargetCG.h"
 #include "SourceSurfaceCG.h"
 #include "Rect.h"
 #include "ScaledFontMac.h"
 #include "Tools.h"
 #include <vector>
+#include "QuartzSupport.h"
 
 //CG_EXTERN void CGContextSetCompositeOperation (CGContextRef, PrivateCGCompositeMode);
 
 // A private API that Cairo has been using for a long time
 CG_EXTERN void CGContextSetCTM(CGContextRef, CGAffineTransform);
 
 namespace mozilla {
 namespace gfx {
@@ -87,33 +88,49 @@ DrawTargetCG::~DrawTargetCG()
   // We need to conditionally release these because Init can fail without initializing these.
   if (mColorSpace)
     CGColorSpaceRelease(mColorSpace);
   if (mCg)
     CGContextRelease(mCg);
   free(mData);
 }
 
+BackendType
+DrawTargetCG::GetType() const
+{
+  // It may be worth spliting Bitmap and IOSurface DrawTarget
+  // into seperate classes.
+  if (GetContextType(mCg) == CG_CONTEXT_TYPE_IOSURFACE) {
+    return BACKEND_COREGRAPHICS_ACCELERATED;
+  } else {
+    return BACKEND_COREGRAPHICS;
+  }
+}
+
 TemporaryRef<SourceSurface>
 DrawTargetCG::Snapshot()
 {
   if (!mSnapshot) {
-    mSnapshot = new SourceSurfaceCGBitmapContext(this);
+    if (GetContextType(mCg) == CG_CONTEXT_TYPE_IOSURFACE) {
+      return new SourceSurfaceCGIOSurfaceContext(this);
+    } else {
+      mSnapshot = new SourceSurfaceCGBitmapContext(this);
+    }
   }
 
   return mSnapshot;
 }
 
 TemporaryRef<DrawTarget>
 DrawTargetCG::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
 {
   // XXX: in thebes we use CGLayers to do this kind of thing. It probably makes sense
   // to add that in somehow, but at a higher level
   RefPtr<DrawTargetCG> newTarget = new DrawTargetCG();
-  if (newTarget->Init(aSize, aFormat)) {
+  if (newTarget->Init(GetType(), aSize, aFormat)) {
     return newTarget;
   } else {
     return NULL;
   }
 }
 
 TemporaryRef<SourceSurface>
 DrawTargetCG::CreateSourceSurfaceFromData(unsigned char *aData,
@@ -131,17 +148,17 @@ DrawTargetCG::CreateSourceSurfaceFromDat
 }
 
 static CGImageRef
 GetImageFromSourceSurface(SourceSurface *aSurface)
 {
   if (aSurface->GetType() == SURFACE_COREGRAPHICS_IMAGE)
     return static_cast<SourceSurfaceCG*>(aSurface)->GetImage();
   else if (aSurface->GetType() == SURFACE_COREGRAPHICS_CGCONTEXT)
-    return static_cast<SourceSurfaceCGBitmapContext*>(aSurface)->GetImage();
+    return static_cast<SourceSurfaceCGContext*>(aSurface)->GetImage();
   else if (aSurface->GetType() == SURFACE_DATA)
     return static_cast<DataSourceSurfaceCG*>(aSurface)->GetImage();
   abort();
 }
 
 TemporaryRef<SourceSurface>
 DrawTargetCG::OptimizeSourceSurface(SourceSurface *aSurface) const
 {
@@ -272,16 +289,18 @@ class GradientStopsCG : public GradientS
                                                     &colors.front(),
                                                     &offsets.front(),
                                                     aNumStops);
     CGColorSpaceRelease(colorSpace);
   }
   virtual ~GradientStopsCG() {
     CGGradientRelease(mGradient);
   }
+  // Will always report BACKEND_COREGRAPHICS, but it is compatible
+  // with BACKEND_COREGRAPHICS_ACCELERATED
   BackendType GetBackendType() const { return BACKEND_COREGRAPHICS; }
   CGGradientRef mGradient;
 };
 
 TemporaryRef<GradientStops>
 DrawTargetCG::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops,
                                   ExtendMode aExtendMode) const
 {
@@ -794,17 +813,18 @@ DrawTargetCG::DrawSurfaceWithShadow(Sour
 
   CGContextDrawImage(mCg, flippedRect, image);
 
   CGContextRestoreGState(mCg);
 
 }
 
 bool
-DrawTargetCG::Init(unsigned char* aData,
+DrawTargetCG::Init(BackendType aType,
+                   unsigned char* aData,
                    const IntSize &aSize,
                    int32_t aStride,
                    SurfaceFormat aFormat)
 {
   // XXX: we should come up with some consistent semantics for dealing
   // with zero area drawtargets
   if (aSize.width <= 0 || aSize.height <= 0 ||
       // 32767 is the maximum size supported by cairo
@@ -816,43 +836,51 @@ DrawTargetCG::Init(unsigned char* aData,
     return false;
   }
 
   //XXX: handle SurfaceFormat
 
   //XXX: we'd be better off reusing the Colorspace across draw targets
   mColorSpace = CGColorSpaceCreateDeviceRGB();
 
-  if (aData == NULL) {
+  if (aData == NULL && aType != BACKEND_COREGRAPHICS_ACCELERATED) {
     // XXX: Currently, Init implicitly clears, that can often be a waste of time
     mData = calloc(aSize.height * aStride, 1);
     aData = static_cast<unsigned char*>(mData);  
   } else {
     // mData == NULL means DrawTargetCG doesn't own the image data and will not
     // delete it in the destructor
     mData = NULL;
   }
 
   mSize = aSize;
-  
-  int bitsPerComponent = 8;
 
-  CGBitmapInfo bitinfo;
+  if (aType == BACKEND_COREGRAPHICS_ACCELERATED) {
+    RefPtr<MacIOSurface> ioSurface = MacIOSurface::CreateIOSurface(aSize.width, aSize.height);
+    mCg = ioSurface->CreateIOSurfaceContext();
+    // If we don't have the symbol for 'CreateIOSurfaceContext' mCg will be null
+    // and we will fallback to software below
+    mData = NULL;
+  }
 
-  bitinfo = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst;
+  if (!mCg || aType == BACKEND_COREGRAPHICS) {
+    int bitsPerComponent = 8;
 
-  // XXX: what should we do if this fails?
-  mCg = CGBitmapContextCreate (aData,
-                               mSize.width,
-                               mSize.height,
-                               bitsPerComponent,
-                               aStride,
-                               mColorSpace,
-                               bitinfo);
+    CGBitmapInfo bitinfo;
+    bitinfo = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst;
 
+    // XXX: what should we do if this fails?
+    mCg = CGBitmapContextCreate (aData,
+                                 mSize.width,
+                                 mSize.height,
+                                 bitsPerComponent,
+                                 aStride,
+                                 mColorSpace,
+                                 bitinfo);
+  }
 
   assert(mCg);
   // CGContext's default to have the origin at the bottom left
   // so flip it to the top left
   CGContextTranslateCTM(mCg, 0, mSize.height);
   CGContextScaleCTM(mCg, 1, -1);
   // See Bug 722164 for performance details
   // Medium or higher quality lead to expensive interpolation
@@ -861,19 +889,32 @@ DrawTargetCG::Init(unsigned char* aData,
   // implementation.
   // XXX: Create input parameter to control interpolation and
   //      use the default for content.
   CGContextSetInterpolationQuality(mCg, kCGInterpolationLow);
 
   // XXX: set correct format
   mFormat = FORMAT_B8G8R8A8;
 
+  if (aType == BACKEND_COREGRAPHICS_ACCELERATED) {
+    // The bitmap backend uses callac to clear, we can't do that without
+    // reading back the surface. This should trigger something equivilent
+    // to glClear.
+    ClearRect(Rect(0, 0, mSize.width, mSize.height));
+  }
+
   return true;
 }
 
+void
+DrawTargetCG::Flush()
+{
+  CGContextFlush(mCg);
+}
+
 bool
 DrawTargetCG::Init(CGContextRef cgContext, const IntSize &aSize)
 {
   // XXX: we should come up with some consistent semantics for dealing
   // with zero area drawtargets
   if (aSize.width == 0 || aSize.height == 0) {
     mColorSpace = NULL;
     mCg = NULL;
@@ -900,35 +941,36 @@ DrawTargetCG::Init(CGContextRef cgContex
 
   //XXX: set correct format
   mFormat = FORMAT_B8G8R8A8;
 
   return true;
 }
 
 bool
-DrawTargetCG::Init(const IntSize &aSize, SurfaceFormat &aFormat)
+DrawTargetCG::Init(BackendType aType, const IntSize &aSize, SurfaceFormat &aFormat)
 {
   int stride = aSize.width*4;
   
   // Calling Init with aData == NULL will allocate.
-  return Init(NULL, aSize, stride, aFormat);
+  return Init(aType, NULL, aSize, stride, aFormat);
 }
 
 TemporaryRef<PathBuilder>
 DrawTargetCG::CreatePathBuilder(FillRule aFillRule) const
 {
   RefPtr<PathBuilderCG> pb = new PathBuilderCG(aFillRule);
   return pb;
 }
 
 void*
 DrawTargetCG::GetNativeSurface(NativeSurfaceType aType)
 {
-  if (aType == NATIVE_SURFACE_CGCONTEXT) {
+  if (aType == NATIVE_SURFACE_CGCONTEXT && GetContextType(mCg) == CG_CONTEXT_TYPE_BITMAP ||
+      aType == NATIVE_SURFACE_CGCONTEXT_ACCELERATED && GetContextType(mCg) == CG_CONTEXT_TYPE_IOSURFACE) {
     return mCg;
   } else {
     return NULL;
   }
 }
 
 void
 DrawTargetCG::Mask(const Pattern &aSource,
--- a/gfx/2d/DrawTargetCG.h
+++ b/gfx/2d/DrawTargetCG.h
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <ApplicationServices/ApplicationServices.h>
 
 #include "2D.h"
 #include "Rect.h"
 #include "PathCG.h"
 #include "SourceSurfaceCG.h"
+#include "GLDefs.h"
 
 namespace mozilla {
 namespace gfx {
 
 static inline CGAffineTransform
 GfxMatrixToCGAffineTransform(Matrix m)
 {
   CGAffineTransform t;
@@ -82,37 +83,37 @@ SetStrokeOptions(CGContextRef cg, const 
 
 
 class DrawTargetCG : public DrawTarget
 {
 public:
   DrawTargetCG();
   virtual ~DrawTargetCG();
 
-  virtual BackendType GetType() const { return BACKEND_COREGRAPHICS; }
+  virtual BackendType GetType() const;
   virtual TemporaryRef<SourceSurface> Snapshot();
 
   virtual void DrawSurface(SourceSurface *aSurface,
                            const Rect &aDest,
                            const Rect &aSource,
                            const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(),
                            const DrawOptions &aOptions = DrawOptions());
 
   virtual void FillRect(const Rect &aRect,
                         const Pattern &aPattern,
                         const DrawOptions &aOptions = DrawOptions());
 
 
   //XXX: why do we take a reference to SurfaceFormat?
-  bool Init(const IntSize &aSize, SurfaceFormat&);
-  bool Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat);
+  bool Init(BackendType aType, const IntSize &aSize, SurfaceFormat&);
+  bool Init(BackendType aType, unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat);
   bool Init(CGContextRef cgContext, const IntSize &aSize);
 
-
-  virtual void Flush() {}
+  // Flush if using IOSurface context
+  virtual void Flush();
 
   virtual void DrawSurfaceWithShadow(SourceSurface *, const Point &, const Color &, const Point &, Float, CompositionOp);
   virtual void ClearRect(const Rect &);
   virtual void CopySurface(SourceSurface *, const IntRect&, const IntPoint&);
   virtual void StrokeRect(const Rect &, const Pattern &, const StrokeOptions&, const DrawOptions&);
   virtual void StrokeLine(const Point &, const Point &, const Pattern &, const StrokeOptions &, const DrawOptions &);
   virtual void Stroke(const Path *, const Pattern &, const StrokeOptions &, const DrawOptions &);
   virtual void Fill(const Path *, const Pattern &, const DrawOptions &);
@@ -145,25 +146,27 @@ public:
   }
 private:
   void MarkChanged();
 
   IntSize mSize;
   CGColorSpaceRef mColorSpace;
   CGContextRef mCg;
 
+  GLuint mIOSurfaceTexture;
+
   /**
    * A pointer to the image buffer if the buffer is owned by this class (set to
    * NULL otherwise).
    * The data is not considered owned by DrawTargetCG if the DrawTarget was 
    * created for a pre-existing buffer or if the buffer's lifetime is managed
    * by CoreGraphics.
    * Data owned by DrawTargetCG will be deallocated in the destructor. 
    */
   void *mData;
 
   SurfaceFormat mFormat;
 
-  RefPtr<SourceSurfaceCGBitmapContext> mSnapshot;
+  RefPtr<SourceSurfaceCGContext> mSnapshot;
 };
 
 }
 }
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -168,20 +168,21 @@ Factory::CreateDrawTarget(BackendType aB
       newTarget = new DrawTargetD2D();
       if (newTarget->Init(aSize, aFormat)) {
         return newTarget;
       }
       break;
     }
 #elif defined XP_MACOSX
   case BACKEND_COREGRAPHICS:
+  case BACKEND_COREGRAPHICS_ACCELERATED:
     {
       RefPtr<DrawTargetCG> newTarget;
       newTarget = new DrawTargetCG();
-      if (newTarget->Init(aSize, aFormat)) {
+      if (newTarget->Init(aBackend, aSize, aFormat)) {
         return newTarget;
       }
       break;
     }
 #endif
 #ifdef USE_SKIA
   case BACKEND_SKIA:
     {
@@ -219,17 +220,17 @@ Factory::CreateDrawTargetForData(Backend
       newTarget->Init(aData, aSize, aStride, aFormat);
       return newTarget;
     }
 #endif
 #ifdef XP_MACOSX
   case BACKEND_COREGRAPHICS:
     {
       RefPtr<DrawTargetCG> newTarget = new DrawTargetCG();
-      if (newTarget->Init(aData, aSize, aStride, aFormat))
+      if (newTarget->Init(aBackend, aData, aSize, aStride, aFormat))
         return newTarget;
       break;
     }
 #endif
   default:
     gfxDebug() << "Invalid draw target type specified.";
     return NULL;
   }
rename from gfx/thebes/nsIOSurface.h
rename to gfx/2d/MacIOSurface.h
--- a/gfx/thebes/nsIOSurface.h
+++ b/gfx/2d/MacIOSurface.h
@@ -1,47 +1,58 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 // vim:set ts=2 sts=2 sw=2 et cin:
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef nsIOSurface_h__
-#define nsIOSurface_h__
+#ifndef MacIOSurface_h__
+#define MacIOSurface_h__
 #ifdef XP_MACOSX
 
 #import <OpenGL/OpenGL.h>
+#include "2D.h"
+#include "mozilla/RefPtr.h"
 
 class gfxASurface;
 struct _CGLContextObject;
 
 typedef _CGLContextObject* CGLContextObj;
+typedef struct CGContext* CGContextRef;
+typedef struct CGImage* CGImageRef;
 typedef uint32_t IOSurfaceID;
 
-class THEBES_API nsIOSurface {
-    NS_INLINE_DECL_REFCOUNTING(nsIOSurface)
+class MacIOSurface : public mozilla::RefCounted<MacIOSurface> {
 public:
-  static already_AddRefed<nsIOSurface> CreateIOSurface(int aWidth, int aHeight);
-  static void ReleaseIOSurface(nsIOSurface *aIOSurface);
-  static already_AddRefed<nsIOSurface> LookupSurface(IOSurfaceID aSurfaceID);
+  typedef mozilla::gfx::SourceSurface SourceSurface;
 
-  nsIOSurface(const void *aIOSurfacePtr) : mIOSurfacePtr(aIOSurfacePtr) {}
-  ~nsIOSurface();
+  static mozilla::TemporaryRef<MacIOSurface> CreateIOSurface(int aWidth, int aHeight);
+  static void ReleaseIOSurface(MacIOSurface *aIOSurface);
+  static mozilla::TemporaryRef<MacIOSurface> LookupSurface(IOSurfaceID aSurfaceID);
+
+  MacIOSurface(const void *aIOSurfacePtr) : mIOSurfacePtr(aIOSurfacePtr) {}
+  ~MacIOSurface();
   IOSurfaceID GetIOSurfaceID();
   void *GetBaseAddress();
   size_t GetWidth();
   size_t GetHeight();
   size_t GetBytesPerRow();
   void Lock();
   void Unlock();
   // We would like to forward declare NSOpenGLContext, but it is an @interface
   // and this file is also used from c++, so we use a void *.
   CGLError CGLTexImageIOSurface2D(void *ctxt,
                                   GLenum internalFormat, GLenum format,
                                   GLenum type, GLuint plane);
-  already_AddRefed<gfxASurface> GetAsSurface();
+  mozilla::TemporaryRef<SourceSurface> GetAsSurface();
+  CGContextRef CreateIOSurfaceContext();
+
+  // FIXME This doesn't really belong here
+  static CGImageRef CreateImageFromIOSurfaceContext(CGContextRef aContext);
+  static mozilla::TemporaryRef<MacIOSurface> IOSurfaceContextGetSurface(CGContextRef aContext);
+
 private:
   friend class nsCARenderer;
   const void* mIOSurfacePtr;
 };
 
 #endif
 #endif
--- a/gfx/2d/Makefile.in
+++ b/gfx/2d/Makefile.in
@@ -47,16 +47,25 @@ CPPSRCS	= \
         $(NULL)
 
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 CPPSRCS	+= \
 	   SourceSurfaceCG.cpp \
 	   DrawTargetCG.cpp \
 	   PathCG.cpp \
 	   $(NULL)
+
+CMMSRCS = \
+	   QuartzSupport.mm \
+	   $(NULL)
+
+EXPORTS_mozilla/gfx	+= \
+	   QuartzSupport.h \
+	   MacIOSurface.h \
+	   $(NULL)
 endif
 
 DEFINES += -DMOZ_GFX -DUSE_CAIRO -DGFX2D_INTERNAL
 
 ifdef MOZ_ENABLE_SKIA
 CPPSRCS	+= \
         SourceSurfaceSkia.cpp \
         DrawTargetSkia.cpp \
--- a/gfx/2d/PathCG.h
+++ b/gfx/2d/PathCG.h
@@ -66,16 +66,18 @@ public:
   PathCG(CGMutablePathRef aPath, FillRule aFillRule)
     : mPath(aPath)
     , mFillRule(aFillRule)
   {
     CGPathRetain(mPath);
   }
   virtual ~PathCG() { CGPathRelease(mPath); }
 
+  // Paths will always return BACKEND_COREGRAPHICS, but note that they
+  // are compatible with BACKEND_COREGRAPHICS_ACCELERATED backend.
   virtual BackendType GetBackendType() const { return BACKEND_COREGRAPHICS; }
 
   virtual TemporaryRef<PathBuilder> CopyToBuilder(FillRule aFillRule = FILL_WINDING) const;
   virtual TemporaryRef<PathBuilder> TransformedCopyToBuilder(const Matrix &aTransform,
                                                              FillRule aFillRule = FILL_WINDING) const;
 
   virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const;
   virtual Rect GetBounds(const Matrix &aTransform = Matrix()) const;
new file mode 100644
--- /dev/null
+++ b/gfx/2d/QuartzSupport.h
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:set ts=2 sts=2 sw=2 et cin:
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsCoreAnimationSupport_h__
+#define nsCoreAnimationSupport_h__
+#ifdef XP_MACOSX
+
+#import <OpenGL/OpenGL.h>
+#import "ApplicationServices/ApplicationServices.h"
+#include "gfxTypes.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/gfx/MacIOSurface.h"
+
+// Get the system color space.
+CGColorSpaceRef THEBES_API CreateSystemColorSpace();
+
+// Manages a CARenderer
+struct _CGLPBufferObject;
+struct _CGLContextObject;
+
+enum AllowOfflineRendererEnum { ALLOW_OFFLINE_RENDERER, DISALLOW_OFFLINE_RENDERER };
+
+class nsCARenderer : public mozilla::RefCounted<nsCARenderer> {
+public:
+  nsCARenderer() : mCARenderer(nsnull), mFBOTexture(0), mOpenGLContext(nsnull),
+                   mCGImage(nsnull), mCGData(nsnull), mIOSurface(nsnull), mFBO(0),
+                   mIOTexture(0),
+                   mUnsupportedWidth(UINT32_MAX), mUnsupportedHeight(UINT32_MAX),
+                   mAllowOfflineRenderer(DISALLOW_OFFLINE_RENDERER) {}
+  ~nsCARenderer();
+  nsresult SetupRenderer(void* aCALayer, int aWidth, int aHeight,
+                         AllowOfflineRendererEnum aAllowOfflineRenderer);
+  nsresult Render(int aWidth, int aHeight, CGImageRef *aOutCAImage);
+  bool isInit() { return mCARenderer != nsnull; }
+  /*
+   * Render the CALayer to an IOSurface. If no IOSurface
+   * is attached then an internal pixel buffer will be
+   * used.
+   */
+  void AttachIOSurface(mozilla::RefPtr<MacIOSurface> aSurface);
+  IOSurfaceID GetIOSurfaceID();
+  static nsresult DrawSurfaceToCGContext(CGContextRef aContext,
+                                         MacIOSurface *surf,
+                                         CGColorSpaceRef aColorSpace,
+                                         int aX, int aY,
+                                         size_t aWidth, size_t aHeight);
+
+  // Remove & Add the layer without destroying
+  // the renderer for fast back buffer swapping.
+  void DettachCALayer();
+  void AttachCALayer(void *aCALayer);
+#ifdef DEBUG
+  static void SaveToDisk(MacIOSurface *surf);
+#endif
+private:
+  void SetBounds(int aWidth, int aHeight);
+  void SetViewport(int aWidth, int aHeight);
+  void Destroy();
+
+  void *mCARenderer;
+  GLuint                    mFBOTexture;
+  _CGLContextObject        *mOpenGLContext;
+  CGImageRef                mCGImage;
+  void                     *mCGData;
+  mozilla::RefPtr<MacIOSurface> mIOSurface;
+  uint32_t                  mFBO;
+  uint32_t                  mIOTexture;
+  uint32_t                  mUnsupportedWidth;
+  uint32_t                  mUnsupportedHeight;
+  AllowOfflineRendererEnum  mAllowOfflineRenderer;
+};
+
+enum CGContextType {
+  CG_CONTEXT_TYPE_UNKNOWN = 0,
+  // These are found by inspection, it's possible they could be changed
+  CG_CONTEXT_TYPE_BITMAP = 4,
+  CG_CONTEXT_TYPE_IOSURFACE = 8
+};
+
+CGContextType GetContextType(CGContextRef ref);
+
+#endif // XP_MACOSX
+#endif // nsCoreAnimationSupport_h__
+
rename from gfx/thebes/nsCoreAnimationSupport.mm
rename to gfx/2d/QuartzSupport.mm
--- a/gfx/thebes/nsCoreAnimationSupport.mm
+++ b/gfx/2d/QuartzSupport.mm
@@ -1,26 +1,30 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 // vim:set ts=2 sts=2 sw=2 et cin:
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsCoreAnimationSupport.h"
+#include "QuartzSupport.h"
 #include "nsDebug.h"
 
 #import <QuartzCore/QuartzCore.h>
 #import <AppKit/NSOpenGL.h>
 #include <dlfcn.h>
 
 #define IOSURFACE_FRAMEWORK_PATH \
   "/System/Library/Frameworks/IOSurface.framework/IOSurface"
 #define OPENGL_FRAMEWORK_PATH \
   "/System/Library/Frameworks/OpenGL.framework/OpenGL"
+#define COREGRAPHICS_FRAMEWORK_PATH \
+  "/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/CoreGraphics"
 
+using mozilla::RefPtr;
+using mozilla::TemporaryRef;
 
 // IOSurface signatures
 typedef CFTypeRef IOSurfacePtr;
 typedef IOSurfacePtr (*IOSurfaceCreateFunc) (CFDictionaryRef properties);
 typedef IOSurfacePtr (*IOSurfaceLookupFunc) (uint32_t io_surface_id);
 typedef IOSurfaceID (*IOSurfaceGetIDFunc) (CFTypeRef io_surface);
 typedef IOReturn (*IOSurfaceLockFunc) (CFTypeRef io_surface, 
                                        uint32_t options, 
@@ -32,39 +36,51 @@ typedef void* (*IOSurfaceGetBaseAddressF
 typedef size_t (*IOSurfaceGetWidthFunc) (IOSurfacePtr io_surface);
 typedef size_t (*IOSurfaceGetHeightFunc) (IOSurfacePtr io_surface);
 typedef size_t (*IOSurfaceGetBytesPerRowFunc) (IOSurfacePtr io_surface);
 typedef CGLError (*CGLTexImageIOSurface2DFunc) (CGLContextObj ctxt,
                              GLenum target, GLenum internalFormat,
                              GLsizei width, GLsizei height,
                              GLenum format, GLenum type,
                              IOSurfacePtr ioSurface, GLuint plane);
+typedef CGContextRef (*IOSurfaceContextCreateFunc)(CFTypeRef io_surface,
+                             unsigned width, unsigned height,
+                             unsigned bitsPerComponent, unsigned bytes,
+                             CGColorSpaceRef colorSpace, CGBitmapInfo bitmapInfo);
+typedef CGImageRef (*IOSurfaceContextCreateImageFunc)(CGContextRef ref);
+typedef IOSurfacePtr (*IOSurfaceContextGetSurfaceFunc)(CGContextRef ref);
 
 #define GET_CONST(const_name) \
   ((CFStringRef*) dlsym(sIOSurfaceFramework, const_name))
 #define GET_IOSYM(dest,sym_name) \
   (typeof(dest)) dlsym(sIOSurfaceFramework, sym_name)
 #define GET_CGLSYM(dest,sym_name) \
   (typeof(dest)) dlsym(sOpenGLFramework, sym_name)
+#define GET_CGSYM(dest,sym_name) \
+  (typeof(dest)) dlsym(sCoreGraphicsFramework, sym_name)
 
-class nsIOSurfaceLib: public nsIOSurface {
+class MacIOSurfaceLib: public MacIOSurface {
 public:
   static void                        *sIOSurfaceFramework;
   static void                        *sOpenGLFramework;
+  static void                        *sCoreGraphicsFramework;
   static bool                         isLoaded;
   static IOSurfaceCreateFunc          sCreate;
   static IOSurfaceGetIDFunc           sGetID;
   static IOSurfaceLookupFunc          sLookup;
   static IOSurfaceGetBaseAddressFunc  sGetBaseAddress;
   static IOSurfaceLockFunc            sLock;
   static IOSurfaceUnlockFunc          sUnlock;
   static IOSurfaceGetWidthFunc        sWidth;
   static IOSurfaceGetHeightFunc       sHeight;
   static IOSurfaceGetBytesPerRowFunc  sBytesPerRow;
   static CGLTexImageIOSurface2DFunc   sTexImage;
+  static IOSurfaceContextCreateFunc   sIOSurfaceContextCreate;
+  static IOSurfaceContextCreateImageFunc  sIOSurfaceContextCreateImage;
+  static IOSurfaceContextGetSurfaceFunc   sIOSurfaceContextGetSurface;
   static CFStringRef                  kPropWidth;
   static CFStringRef                  kPropHeight;
   static CFStringRef                  kPropBytesPerElem;
   static CFStringRef                  kPropBytesPerRow;
   static CFStringRef                  kPropIsGlobal;
 
   static bool isInit();
   static CFStringRef GetIOConst(const char* symbole);
@@ -79,129 +95,170 @@ public:
                                     uint32_t options, uint32_t *seed);
   static IOReturn     IOSurfaceUnlock(IOSurfacePtr aIOSurfacePtr, 
                                       uint32_t options, uint32_t *seed);
   static CGLError     CGLTexImageIOSurface2D(CGLContextObj ctxt,
                              GLenum target, GLenum internalFormat,
                              GLsizei width, GLsizei height,
                              GLenum format, GLenum type,
                              IOSurfacePtr ioSurface, GLuint plane);
+  static CGContextRef IOSurfaceContextCreate(IOSurfacePtr aIOSurfacePtr,
+                             unsigned aWidth, unsigned aHeight,
+                             unsigned aBitsPerCompoent, unsigned aBytes,
+                             CGColorSpaceRef aColorSpace, CGBitmapInfo bitmapInfo);
+  static CGImageRef   IOSurfaceContextCreateImage(CGContextRef ref);
+  static IOSurfacePtr IOSurfaceContextGetSurface(CGContextRef ref);
+  static unsigned int (*sCGContextGetTypePtr) (CGContextRef);
   static void LoadLibrary();
   static void CloseLibrary();
 
   // Static deconstructor
   static class LibraryUnloader {
   public:
     ~LibraryUnloader() {
       CloseLibrary();
     }
   } sLibraryUnloader;
 };
 
-nsIOSurfaceLib::LibraryUnloader nsIOSurfaceLib::sLibraryUnloader;
-bool                          nsIOSurfaceLib::isLoaded = false;
-void*                         nsIOSurfaceLib::sIOSurfaceFramework;
-void*                         nsIOSurfaceLib::sOpenGLFramework;
-IOSurfaceCreateFunc           nsIOSurfaceLib::sCreate;
-IOSurfaceGetIDFunc            nsIOSurfaceLib::sGetID;
-IOSurfaceLookupFunc           nsIOSurfaceLib::sLookup;
-IOSurfaceGetBaseAddressFunc   nsIOSurfaceLib::sGetBaseAddress;
-IOSurfaceGetHeightFunc        nsIOSurfaceLib::sWidth;
-IOSurfaceGetWidthFunc         nsIOSurfaceLib::sHeight;
-IOSurfaceGetBytesPerRowFunc   nsIOSurfaceLib::sBytesPerRow;
-IOSurfaceLockFunc             nsIOSurfaceLib::sLock;
-IOSurfaceUnlockFunc           nsIOSurfaceLib::sUnlock;
-CGLTexImageIOSurface2DFunc    nsIOSurfaceLib::sTexImage;
-CFStringRef                   nsIOSurfaceLib::kPropWidth;
-CFStringRef                   nsIOSurfaceLib::kPropHeight;
-CFStringRef                   nsIOSurfaceLib::kPropBytesPerElem;
-CFStringRef                   nsIOSurfaceLib::kPropBytesPerRow;
-CFStringRef                   nsIOSurfaceLib::kPropIsGlobal;
+MacIOSurfaceLib::LibraryUnloader MacIOSurfaceLib::sLibraryUnloader;
+bool                          MacIOSurfaceLib::isLoaded = false;
+void*                         MacIOSurfaceLib::sIOSurfaceFramework;
+void*                         MacIOSurfaceLib::sOpenGLFramework;
+void*                         MacIOSurfaceLib::sCoreGraphicsFramework;
+IOSurfaceCreateFunc           MacIOSurfaceLib::sCreate;
+IOSurfaceGetIDFunc            MacIOSurfaceLib::sGetID;
+IOSurfaceLookupFunc           MacIOSurfaceLib::sLookup;
+IOSurfaceGetBaseAddressFunc   MacIOSurfaceLib::sGetBaseAddress;
+IOSurfaceGetHeightFunc        MacIOSurfaceLib::sWidth;
+IOSurfaceGetWidthFunc         MacIOSurfaceLib::sHeight;
+IOSurfaceGetBytesPerRowFunc   MacIOSurfaceLib::sBytesPerRow;
+IOSurfaceLockFunc             MacIOSurfaceLib::sLock;
+IOSurfaceUnlockFunc           MacIOSurfaceLib::sUnlock;
+CGLTexImageIOSurface2DFunc    MacIOSurfaceLib::sTexImage;
+IOSurfaceContextCreateFunc    MacIOSurfaceLib::sIOSurfaceContextCreate;
+IOSurfaceContextCreateImageFunc   MacIOSurfaceLib::sIOSurfaceContextCreateImage;
+IOSurfaceContextGetSurfaceFunc    MacIOSurfaceLib::sIOSurfaceContextGetSurface;
+unsigned int                  (*MacIOSurfaceLib::sCGContextGetTypePtr) (CGContextRef) = NULL;
 
-bool nsIOSurfaceLib::isInit() {
+CFStringRef                   MacIOSurfaceLib::kPropWidth;
+CFStringRef                   MacIOSurfaceLib::kPropHeight;
+CFStringRef                   MacIOSurfaceLib::kPropBytesPerElem;
+CFStringRef                   MacIOSurfaceLib::kPropBytesPerRow;
+CFStringRef                   MacIOSurfaceLib::kPropIsGlobal;
+
+bool MacIOSurfaceLib::isInit() {
   // Guard against trying to reload the library
   // if it is not available.
   if (!isLoaded)
     LoadLibrary();
   if (!sIOSurfaceFramework) {
-    NS_ERROR("nsIOSurfaceLib failed to initialize");
+    NS_ERROR("MacIOSurfaceLib failed to initialize");
   }
   return sIOSurfaceFramework;
 }
 
-IOSurfacePtr nsIOSurfaceLib::IOSurfaceCreate(CFDictionaryRef properties) {
+IOSurfacePtr MacIOSurfaceLib::IOSurfaceCreate(CFDictionaryRef properties) {
   return sCreate(properties);
 }
 
-IOSurfacePtr nsIOSurfaceLib::IOSurfaceLookup(IOSurfaceID aIOSurfaceID) {
+IOSurfacePtr MacIOSurfaceLib::IOSurfaceLookup(IOSurfaceID aIOSurfaceID) {
   return sLookup(aIOSurfaceID);
 }
 
-IOSurfaceID nsIOSurfaceLib::IOSurfaceGetID(IOSurfacePtr aIOSurfacePtr) {
+IOSurfaceID MacIOSurfaceLib::IOSurfaceGetID(IOSurfacePtr aIOSurfacePtr) {
   return sGetID(aIOSurfacePtr);
 }
 
-void* nsIOSurfaceLib::IOSurfaceGetBaseAddress(IOSurfacePtr aIOSurfacePtr) {
+void* MacIOSurfaceLib::IOSurfaceGetBaseAddress(IOSurfacePtr aIOSurfacePtr) {
   return sGetBaseAddress(aIOSurfacePtr);
 }
 
-size_t nsIOSurfaceLib::IOSurfaceGetWidth(IOSurfacePtr aIOSurfacePtr) {
+size_t MacIOSurfaceLib::IOSurfaceGetWidth(IOSurfacePtr aIOSurfacePtr) {
   return sWidth(aIOSurfacePtr);
 }
 
-size_t nsIOSurfaceLib::IOSurfaceGetHeight(IOSurfacePtr aIOSurfacePtr) {
+size_t MacIOSurfaceLib::IOSurfaceGetHeight(IOSurfacePtr aIOSurfacePtr) {
   return sHeight(aIOSurfacePtr);
 }
 
-size_t nsIOSurfaceLib::IOSurfaceGetBytesPerRow(IOSurfacePtr aIOSurfacePtr) {
+size_t MacIOSurfaceLib::IOSurfaceGetBytesPerRow(IOSurfacePtr aIOSurfacePtr) {
   return sBytesPerRow(aIOSurfacePtr);
 }
 
-IOReturn nsIOSurfaceLib::IOSurfaceLock(IOSurfacePtr aIOSurfacePtr, 
+IOReturn MacIOSurfaceLib::IOSurfaceLock(IOSurfacePtr aIOSurfacePtr, 
                                        uint32_t options, uint32_t *seed) {
   return sLock(aIOSurfacePtr, options, seed);
 }
 
-IOReturn nsIOSurfaceLib::IOSurfaceUnlock(IOSurfacePtr aIOSurfacePtr, 
+IOReturn MacIOSurfaceLib::IOSurfaceUnlock(IOSurfacePtr aIOSurfacePtr, 
                                          uint32_t options, uint32_t *seed) {
   return sUnlock(aIOSurfacePtr, options, seed);
 }
 
-CGLError nsIOSurfaceLib::CGLTexImageIOSurface2D(CGLContextObj ctxt,
+CGLError MacIOSurfaceLib::CGLTexImageIOSurface2D(CGLContextObj ctxt,
                              GLenum target, GLenum internalFormat,
                              GLsizei width, GLsizei height,
                              GLenum format, GLenum type,
                              IOSurfacePtr ioSurface, GLuint plane) {
   return sTexImage(ctxt, target, internalFormat, width, height,
                    format, type, ioSurface, plane);
 }
 
-CFStringRef nsIOSurfaceLib::GetIOConst(const char* symbole) {
+CGContextRef MacIOSurfaceLib::IOSurfaceContextCreate(IOSurfacePtr aIOSurfacePtr,
+                             unsigned aWidth, unsigned aHeight,
+                             unsigned aBitsPerComponent, unsigned aBytes,
+                             CGColorSpaceRef aColorSpace, CGBitmapInfo bitmapInfo) {
+  if (!sIOSurfaceContextCreate)
+    return NULL;
+  return sIOSurfaceContextCreate(aIOSurfacePtr, aWidth, aHeight, aBitsPerComponent, aBytes, aColorSpace, bitmapInfo);
+}
+
+CGImageRef MacIOSurfaceLib::IOSurfaceContextCreateImage(CGContextRef aContext) {
+  if (!sIOSurfaceContextCreateImage)
+    return NULL;
+  return sIOSurfaceContextCreateImage(aContext);
+}
+
+IOSurfacePtr MacIOSurfaceLib::IOSurfaceContextGetSurface(CGContextRef aContext) {
+  if (!sIOSurfaceContextGetSurface)
+    return NULL;
+  return sIOSurfaceContextGetSurface(aContext);
+}
+
+CFStringRef MacIOSurfaceLib::GetIOConst(const char* symbole) {
   CFStringRef *address = (CFStringRef*)dlsym(sIOSurfaceFramework, symbole);
   if (!address)
     return nullptr;
 
   return *address;
 }
 
-void nsIOSurfaceLib::LoadLibrary() {
+void MacIOSurfaceLib::LoadLibrary() {
   if (isLoaded) {
     return;
   } 
   isLoaded = true;
-  sIOSurfaceFramework = dlopen(IOSURFACE_FRAMEWORK_PATH, 
+  sIOSurfaceFramework = dlopen(IOSURFACE_FRAMEWORK_PATH,
                             RTLD_LAZY | RTLD_LOCAL);
-  sOpenGLFramework = dlopen(OPENGL_FRAMEWORK_PATH, 
+  sOpenGLFramework = dlopen(OPENGL_FRAMEWORK_PATH,
+                            RTLD_LAZY | RTLD_LOCAL);
+
+  sCoreGraphicsFramework = dlopen(COREGRAPHICS_FRAMEWORK_PATH,
                             RTLD_LAZY | RTLD_LOCAL);
-  if (!sIOSurfaceFramework) {
-    return;
-  }
-  if (!sOpenGLFramework) {
-    dlclose(sIOSurfaceFramework);
-    sIOSurfaceFramework = nullptr;
+  if (!sIOSurfaceFramework || !sOpenGLFramework || !sCoreGraphicsFramework) {
+    if (sIOSurfaceFramework)
+      dlclose(sIOSurfaceFramework);
+    if (sOpenGLFramework)
+      dlclose(sOpenGLFramework);
+    if (sCoreGraphicsFramework)
+      dlclose(sCoreGraphicsFramework);
+    sIOSurfaceFramework = nsnull;
+    sOpenGLFramework = nsnull;
+    sCoreGraphicsFramework = nsnull;
     return;
   }
 
   kPropWidth = GetIOConst("kIOSurfaceWidth");
   kPropHeight = GetIOConst("kIOSurfaceHeight");
   kPropBytesPerElem = GetIOConst("kIOSurfaceBytesPerElement");
   kPropBytesPerRow = GetIOConst("kIOSurfaceBytesPerRow");
   kPropIsGlobal = GetIOConst("kIOSurfaceIsGlobal");
@@ -210,192 +267,208 @@ void nsIOSurfaceLib::LoadLibrary() {
   sWidth = GET_IOSYM(sWidth, "IOSurfaceGetWidth");
   sHeight = GET_IOSYM(sHeight, "IOSurfaceGetHeight");
   sBytesPerRow = GET_IOSYM(sBytesPerRow, "IOSurfaceGetBytesPerRow");
   sLookup = GET_IOSYM(sLookup, "IOSurfaceLookup");
   sLock = GET_IOSYM(sLock, "IOSurfaceLock");
   sUnlock = GET_IOSYM(sUnlock, "IOSurfaceUnlock");
   sGetBaseAddress = GET_IOSYM(sGetBaseAddress, "IOSurfaceGetBaseAddress");
   sTexImage = GET_CGLSYM(sTexImage, "CGLTexImageIOSurface2D");
+  sCGContextGetTypePtr = (unsigned int (*)(CGContext*))dlsym(RTLD_DEFAULT, "CGContextGetType");
+
+  // Optional symbols
+  sIOSurfaceContextCreate = GET_CGSYM(sIOSurfaceContextCreate, "CGIOSurfaceContextCreate");
+  sIOSurfaceContextCreateImage = GET_CGSYM(sIOSurfaceContextCreateImage, "CGIOSurfaceContextCreateImage");
+  sIOSurfaceContextGetSurface = GET_CGSYM(sIOSurfaceContextGetSurface, "CGIOSurfaceContextGetSurface");
 
   if (!sCreate || !sGetID || !sLookup || !sTexImage || !sGetBaseAddress ||
       !kPropWidth || !kPropHeight || !kPropBytesPerElem || !kPropIsGlobal ||
       !sLock || !sUnlock || !sWidth || !sHeight || !kPropBytesPerRow ||
       !sBytesPerRow) {
     CloseLibrary();
   }
 }
 
-void nsIOSurfaceLib::CloseLibrary() {
+void MacIOSurfaceLib::CloseLibrary() {
   if (sIOSurfaceFramework) {
     dlclose(sIOSurfaceFramework);
   }
   if (sOpenGLFramework) {
     dlclose(sOpenGLFramework);
   }
   sIOSurfaceFramework = nullptr;
   sOpenGLFramework = nullptr;
 }
 
-nsIOSurface::~nsIOSurface() {
+MacIOSurface::~MacIOSurface() {
   CFRelease(mIOSurfacePtr);
 }
 
-already_AddRefed<nsIOSurface> nsIOSurface::CreateIOSurface(int aWidth, int aHeight) { 
-  if (!nsIOSurfaceLib::isInit())
+TemporaryRef<MacIOSurface> MacIOSurface::CreateIOSurface(int aWidth, int aHeight) {
+  if (!MacIOSurfaceLib::isInit())
     return nullptr;
 
   CFMutableDictionaryRef props = ::CFDictionaryCreateMutable(
                       kCFAllocatorDefault, 4,
                       &kCFTypeDictionaryKeyCallBacks,
                       &kCFTypeDictionaryValueCallBacks);
   if (!props)
     return nullptr;
 
   int32_t bytesPerElem = 4;
   CFNumberRef cfWidth = ::CFNumberCreate(NULL, kCFNumberSInt32Type, &aWidth);
   CFNumberRef cfHeight = ::CFNumberCreate(NULL, kCFNumberSInt32Type, &aHeight);
   CFNumberRef cfBytesPerElem = ::CFNumberCreate(NULL, kCFNumberSInt32Type, &bytesPerElem);
-  ::CFDictionaryAddValue(props, nsIOSurfaceLib::kPropWidth,
+  ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropWidth,
                                 cfWidth);
   ::CFRelease(cfWidth);
-  ::CFDictionaryAddValue(props, nsIOSurfaceLib::kPropHeight,
+  ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropHeight,
                                 cfHeight);
   ::CFRelease(cfHeight);
-  ::CFDictionaryAddValue(props, nsIOSurfaceLib::kPropBytesPerElem, 
+  ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropBytesPerElem, 
                                 cfBytesPerElem);
   ::CFRelease(cfBytesPerElem);
-  ::CFDictionaryAddValue(props, nsIOSurfaceLib::kPropIsGlobal, 
+  ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropIsGlobal, 
                                 kCFBooleanTrue);
 
-  IOSurfacePtr surfaceRef = nsIOSurfaceLib::IOSurfaceCreate(props);
+  IOSurfacePtr surfaceRef = MacIOSurfaceLib::IOSurfaceCreate(props);
   ::CFRelease(props);
 
   if (!surfaceRef)
     return nullptr;
 
-  nsRefPtr<nsIOSurface> ioSurface = new nsIOSurface(surfaceRef);
+  RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef);
   if (!ioSurface) {
     ::CFRelease(surfaceRef);
     return nullptr;
   }
 
   return ioSurface.forget();
 }
 
-already_AddRefed<nsIOSurface> nsIOSurface::LookupSurface(IOSurfaceID aIOSurfaceID) { 
-  if (!nsIOSurfaceLib::isInit())
+TemporaryRef<MacIOSurface> MacIOSurface::LookupSurface(IOSurfaceID aIOSurfaceID) { 
+  if (!MacIOSurfaceLib::isInit())
     return nullptr;
 
-  IOSurfacePtr surfaceRef = nsIOSurfaceLib::IOSurfaceLookup(aIOSurfaceID);
+  IOSurfacePtr surfaceRef = MacIOSurfaceLib::IOSurfaceLookup(aIOSurfaceID);
   if (!surfaceRef)
     return nullptr;
 
-  nsRefPtr<nsIOSurface> ioSurface = new nsIOSurface(surfaceRef);
+  RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef);
   if (!ioSurface) {
     ::CFRelease(surfaceRef);
     return nullptr;
   }
   return ioSurface.forget();
 }
 
-IOSurfaceID nsIOSurface::GetIOSurfaceID() { 
-  return nsIOSurfaceLib::IOSurfaceGetID(mIOSurfacePtr);
+IOSurfaceID MacIOSurface::GetIOSurfaceID() { 
+  return MacIOSurfaceLib::IOSurfaceGetID(mIOSurfacePtr);
 }
 
-void* nsIOSurface::GetBaseAddress() { 
-  return nsIOSurfaceLib::IOSurfaceGetBaseAddress(mIOSurfacePtr);
+void* MacIOSurface::GetBaseAddress() { 
+  return MacIOSurfaceLib::IOSurfaceGetBaseAddress(mIOSurfacePtr);
 }
 
-size_t nsIOSurface::GetWidth() { 
-  return nsIOSurfaceLib::IOSurfaceGetWidth(mIOSurfacePtr);
+size_t MacIOSurface::GetWidth() { 
+  return MacIOSurfaceLib::IOSurfaceGetWidth(mIOSurfacePtr);
 }
 
-size_t nsIOSurface::GetHeight() { 
-  return nsIOSurfaceLib::IOSurfaceGetHeight(mIOSurfacePtr);
+size_t MacIOSurface::GetHeight() { 
+  return MacIOSurfaceLib::IOSurfaceGetHeight(mIOSurfacePtr);
 }
 
-size_t nsIOSurface::GetBytesPerRow() { 
-  return nsIOSurfaceLib::IOSurfaceGetBytesPerRow(mIOSurfacePtr);
+size_t MacIOSurface::GetBytesPerRow() { 
+  return MacIOSurfaceLib::IOSurfaceGetBytesPerRow(mIOSurfacePtr);
 }
 
 #define READ_ONLY 0x1
-void nsIOSurface::Lock() {
-  nsIOSurfaceLib::IOSurfaceLock(mIOSurfacePtr, READ_ONLY, NULL);
+void MacIOSurface::Lock() {
+  MacIOSurfaceLib::IOSurfaceLock(mIOSurfacePtr, READ_ONLY, NULL);
+}
+
+void MacIOSurface::Unlock() {
+  MacIOSurfaceLib::IOSurfaceUnlock(mIOSurfacePtr, READ_ONLY, NULL);
 }
 
-void nsIOSurface::Unlock() {
-  nsIOSurfaceLib::IOSurfaceUnlock(mIOSurfacePtr, READ_ONLY, NULL);
-}
+#include "SourceSurfaceRawData.h"
+using mozilla::gfx::SourceSurface;
+using mozilla::gfx::SourceSurfaceRawData;
+using mozilla::gfx::IntSize;
 
-#include "gfxImageSurface.h"
-
-already_AddRefed<gfxASurface>
-nsIOSurface::GetAsSurface() {
+TemporaryRef<SourceSurface>
+MacIOSurface::GetAsSurface() {
   Lock();
   size_t bytesPerRow = GetBytesPerRow();
   size_t ioWidth = GetWidth();
   size_t ioHeight = GetHeight();
 
   unsigned char* ioData = (unsigned char*)GetBaseAddress();
-
-  nsRefPtr<gfxImageSurface> imgSurface =
-    new gfxImageSurface(gfxIntSize(ioWidth, ioHeight), gfxASurface::ImageFormatARGB32);
-
-  for (int i = 0; i < ioHeight; i++) {
-    memcpy(imgSurface->Data() + i * imgSurface->Stride(),
+  unsigned char* dataCpy = (unsigned char*)malloc(bytesPerRow*ioHeight);
+  for (size_t i = 0; i < ioHeight; i++) {
+    memcpy(dataCpy + i * bytesPerRow,
            ioData + i * bytesPerRow, ioWidth * 4);
   }
 
   Unlock();
 
-  return imgSurface.forget();
+  RefPtr<SourceSurfaceRawData> surf = new SourceSurfaceRawData();
+  surf->InitWrappingData(dataCpy, IntSize(ioWidth, ioHeight), bytesPerRow, mozilla::gfx::FORMAT_B8G8R8A8, true);
+
+  return surf.forget();
 }
 
 CGLError 
-nsIOSurface::CGLTexImageIOSurface2D(void *c,
+MacIOSurface::CGLTexImageIOSurface2D(void *c,
                                     GLenum internalFormat, GLenum format, 
                                     GLenum type, GLuint plane)
 {
   NSOpenGLContext *ctxt = static_cast<NSOpenGLContext*>(c);
-  return nsIOSurfaceLib::CGLTexImageIOSurface2D((CGLContextObj)[ctxt CGLContextObj],
+  return MacIOSurfaceLib::CGLTexImageIOSurface2D((CGLContextObj)[ctxt CGLContextObj],
                                                 GL_TEXTURE_RECTANGLE_ARB,
                                                 internalFormat,
                                                 GetWidth(), GetHeight(),
                                                 format, type,
                                                 mIOSurfacePtr, plane);
 }
 
-nsCARenderer::~nsCARenderer() {
-  Destroy();
-}
-
 CGColorSpaceRef CreateSystemColorSpace() {
     CMProfileRef system_profile = nullptr;
     CGColorSpaceRef cspace = nullptr;
 
     if (::CMGetSystemProfile(&system_profile) == noErr) {
       // Create a colorspace with the systems profile
       cspace = ::CGColorSpaceCreateWithPlatformColorSpace(system_profile);
       ::CMCloseProfile(system_profile);
     } else {
       // Default to generic
       cspace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
     }
 
     return cspace;
 }
 
+CGContextRef MacIOSurface::CreateIOSurfaceContext() {
+  CGContextRef ref = MacIOSurfaceLib::IOSurfaceContextCreate(mIOSurfacePtr, GetWidth(), GetHeight(),
+                                                8, 32, CreateSystemColorSpace(), 0x2002);
+  return ref;
+}
+
+nsCARenderer::~nsCARenderer() {
+  Destroy();
+}
+
 void cgdata_release_callback(void *aCGData, const void *data, size_t size) {
   if (aCGData) {
     free(aCGData);
   }
 }
 
 void nsCARenderer::Destroy() {
+  printf("Destroy\n");
   if (mCARenderer) {
     CARenderer* caRenderer = (CARenderer*)mCARenderer;
     // Bug 556453:
     // Explicitly remove the layer from the renderer
     // otherwise it does not always happen right away.
     caRenderer.layer = nullptr;
     [caRenderer release];
   }
@@ -425,19 +498,21 @@ void nsCARenderer::Destroy() {
     ::CGImageRelease(mCGImage);
   }
   // mCGData is deallocated by cgdata_release_callback
 
   mCARenderer = nil;
   mFBOTexture = 0;
   mOpenGLContext = nullptr;
   mCGImage = nullptr;
+  printf("Destroy: set null\n");
   mIOSurface = nullptr;
   mFBO = 0;
   mIOTexture = 0;
+  printf("Destroy: cleanup\n");
 }
 
 nsresult nsCARenderer::SetupRenderer(void *aCALayer, int aWidth, int aHeight,
                                      AllowOfflineRendererEnum aAllowOfflineRenderer) {
   mAllowOfflineRenderer = aAllowOfflineRenderer;
 
   if (aWidth == 0 || aHeight == 0)
     return NS_ERROR_FAILURE;
@@ -536,17 +611,17 @@ nsresult nsCARenderer::SetupRenderer(voi
   ::CGLSetCurrentContext(mOpenGLContext);
 
   if (mIOSurface) {
     // Create the IOSurface mapped texture.
     ::glGenTextures(1, &mIOTexture);
     ::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mIOTexture);
     ::glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     ::glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    nsIOSurfaceLib::CGLTexImageIOSurface2D(mOpenGLContext, GL_TEXTURE_RECTANGLE_ARB,
+    MacIOSurfaceLib::CGLTexImageIOSurface2D(mOpenGLContext, GL_TEXTURE_RECTANGLE_ARB,
                                            GL_RGBA, aWidth, aHeight,
                                            GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
                                            mIOSurface->mIOSurfacePtr, 0);
     ::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
   } else {
     ::glGenTextures(1, &mFBOTexture);
     ::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mFBOTexture);
     ::glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -630,17 +705,18 @@ void nsCARenderer::SetViewport(int aWidt
   ::glLoadIdentity();
   ::glOrtho (0.0, aWidth, 0.0, aHeight, -1, 1);
 
   // Render upside down to speed up CGContextDrawImage
   ::glTranslatef(0.0f, aHeight, 0.0);
   ::glScalef(1.0, -1.0, 1.0);
 }
 
-void nsCARenderer::AttachIOSurface(nsRefPtr<nsIOSurface> aSurface) {
+void nsCARenderer::AttachIOSurface(RefPtr<MacIOSurface> aSurface) {
+  printf("*****Attach*****\n\n\n\n\n");
   if (mIOSurface &&
       aSurface->GetIOSurfaceID() == mIOSurface->GetIOSurfaceID()) {
     // This object isn't needed since we already have a
     // handle to the same io surface.
     aSurface = nullptr;
     return;
   }
 
@@ -650,17 +726,17 @@ void nsCARenderer::AttachIOSurface(nsRef
   if (mCARenderer) {
     CARenderer* caRenderer = (CARenderer*)mCARenderer;
     int width = caRenderer.bounds.size.width;
     int height = caRenderer.bounds.size.height;
 
     CGLContextObj oldContext = ::CGLGetCurrentContext();
     ::CGLSetCurrentContext(mOpenGLContext);
     ::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mIOTexture);
-    nsIOSurfaceLib::CGLTexImageIOSurface2D(mOpenGLContext, GL_TEXTURE_RECTANGLE_ARB,
+    MacIOSurfaceLib::CGLTexImageIOSurface2D(mOpenGLContext, GL_TEXTURE_RECTANGLE_ARB,
                                            GL_RGBA, mIOSurface->GetWidth(), mIOSurface->GetHeight(),
                                            GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
                                            mIOSurface->mIOSurfacePtr, 0);
     ::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
 
     // Rebind the FBO to make it live
     ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
 
@@ -765,17 +841,17 @@ nsresult nsCARenderer::Render(int aWidth
   if (oldContext) {
     ::CGLSetCurrentContext(oldContext);
   }
 
   return NS_OK;
 }
 
 nsresult nsCARenderer::DrawSurfaceToCGContext(CGContextRef aContext, 
-                                              nsIOSurface *surf, 
+                                              MacIOSurface *surf, 
                                               CGColorSpaceRef aColorSpace,
                                               int aX, int aY,
                                               size_t aWidth, size_t aHeight) {
   surf->Lock();
   size_t bytesPerRow = surf->GetBytesPerRow();
   size_t ioWidth = surf->GetWidth();
   size_t ioHeight = surf->GetHeight();
 
@@ -840,17 +916,17 @@ void nsCARenderer::AttachCALayer(void *a
 
   CALayer* caLayer = (CALayer*)aCALayer;
   caRenderer.layer = caLayer;
 }
 
 #ifdef DEBUG
 
 int sSaveToDiskSequence = 0;
-void nsCARenderer::SaveToDisk(nsIOSurface *surf) {
+void nsCARenderer::SaveToDisk(MacIOSurface *surf) {
   surf->Lock();
   size_t bytesPerRow = surf->GetBytesPerRow();
   size_t ioWidth = surf->GetWidth();
   size_t ioHeight = surf->GetHeight();
   void* ioData = surf->GetBaseAddress();
   CGDataProviderRef dataProvider = ::CGDataProviderCreateWithData(ioData,
                                       ioData, ioHeight*(bytesPerRow)*4, 
                                       NULL); //No release callback 
@@ -895,8 +971,51 @@ void nsCARenderer::SaveToDisk(nsIOSurfac
   surf->Unlock();
 
   return;
 
 }
 
 #endif
 
+CGImageRef MacIOSurface::CreateImageFromIOSurfaceContext(CGContextRef aContext) {
+  if (!MacIOSurfaceLib::isInit())
+    return nsnull;
+
+  return MacIOSurfaceLib::IOSurfaceContextCreateImage(aContext);
+}
+
+TemporaryRef<MacIOSurface> MacIOSurface::IOSurfaceContextGetSurface(CGContextRef aContext) {
+  if (!MacIOSurfaceLib::isInit())
+    return nsnull;
+
+  IOSurfacePtr surfaceRef = MacIOSurfaceLib::IOSurfaceContextGetSurface(aContext);
+  if (!surfaceRef)
+    return nsnull;
+
+  // Retain the IOSurface because MacIOSurface will release it
+  CFRetain(surfaceRef);
+
+  RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef);
+  if (!ioSurface) {
+    ::CFRelease(surfaceRef);
+    return nsnull;
+  }
+  return ioSurface.forget();
+}
+
+
+CGContextType GetContextType(CGContextRef ref)
+{
+  if (!MacIOSurfaceLib::isInit() || !MacIOSurfaceLib::sCGContextGetTypePtr)
+    return CG_CONTEXT_TYPE_UNKNOWN;
+
+  unsigned int type = MacIOSurfaceLib::sCGContextGetTypePtr(ref);
+  if (type == CG_CONTEXT_TYPE_BITMAP) {
+    return CG_CONTEXT_TYPE_BITMAP;
+  } else if (type == CG_CONTEXT_TYPE_IOSURFACE) {
+    return CG_CONTEXT_TYPE_IOSURFACE;
+  } else {
+    return CG_CONTEXT_TYPE_UNKNOWN;
+  }
+}
+
+
--- a/gfx/2d/ScaledFontMac.cpp
+++ b/gfx/2d/ScaledFontMac.cpp
@@ -51,17 +51,17 @@ SkTypeface* ScaledFontMac::GetSkTypeface
 // ATSUGlyphGetCubicPaths
 // we've used this in cairo sucessfully for some time.
 // Note: cairo dlsyms it. We could do that but maybe it's
 // safe just to use?
 
 TemporaryRef<Path>
 ScaledFontMac::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget)
 {
-  if (aTarget->GetType() == BACKEND_COREGRAPHICS) {
+  if (aTarget->GetType() == BACKEND_COREGRAPHICS || aTarget->GetType() == BACKEND_COREGRAPHICS_ACCELERATED) {
       CGMutablePathRef path = CGPathCreateMutable();
 
       for (unsigned int i = 0; i < aBuffer.mNumGlyphs; i++) {
           // XXX: we could probably fold both of these transforms together to avoid extra work
           CGAffineTransform flip = CGAffineTransformMakeScale(1, -1);
           CGPathRef glyphPath = ::CGFontGetGlyphPath(mFont, &flip, 0, aBuffer.mGlyphs[i].mIndex);
 
           CGAffineTransform matrix = CGAffineTransformMake(mSize, 0, 0, mSize,
--- a/gfx/2d/SourceSurfaceCG.cpp
+++ b/gfx/2d/SourceSurfaceCG.cpp
@@ -1,16 +1,18 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "SourceSurfaceCG.h"
 #include "DrawTargetCG.h"
 
+#include "QuartzSupport.h"
+
 namespace mozilla {
 namespace gfx {
 
 
 SourceSurfaceCG::~SourceSurfaceCG()
 {
   CGImageRelease(mImage);
 }
@@ -280,28 +282,30 @@ DataSourceSurfaceCG::GetData()
   // we need read-write for DataSourceSurfaces
   return (unsigned char*)mData;
 }
 
 SourceSurfaceCGBitmapContext::SourceSurfaceCGBitmapContext(DrawTargetCG *aDrawTarget)
 {
   mDrawTarget = aDrawTarget;
   mCg = (CGContextRef)aDrawTarget->GetNativeSurface(NATIVE_SURFACE_CGCONTEXT);
+  if (!mCg)
+    abort();
 
   mSize.width = CGBitmapContextGetWidth(mCg);
   mSize.height = CGBitmapContextGetHeight(mCg);
   mStride = CGBitmapContextGetBytesPerRow(mCg);
   mData = CGBitmapContextGetData(mCg);
 
   mImage = NULL;
 }
 
 void SourceSurfaceCGBitmapContext::EnsureImage() const
 {
-  // Instaed of using CGBitmapContextCreateImage we create
+  // Instead of using CGBitmapContextCreateImage we create
   // a CGImage around the data associated with the CGBitmapContext
   // we do this to avoid the vm_copy that CGBitmapContextCreateImage.
   // vm_copy tends to cause all sorts of unexpected performance problems
   // because of the mm tricks that vm_copy does. Using a regular
   // memcpy when the bitmap context is modified gives us more predictable
   // performance characteristics.
   if (!mImage) {
       //XXX: we should avoid creating this colorspace everytime
@@ -321,16 +325,18 @@ void SourceSurfaceCGBitmapContext::Ensur
           // to the CGDataProviderCreateWithData
           info = NULL;
       } else {
           // otherwise we transfer ownership to
           // the dataProvider
           info = mData;
       }
 
+      if (!mData) abort();
+
       dataProvider = CGDataProviderCreateWithData (info,
                                                    mData,
                                                    mSize.height * mStride,
                                                    releaseCallback);
 
       mImage = CGImageCreate (mSize.width, mSize.height,
                               bitsPerComponent,
                               bitsPerPixel,
@@ -384,10 +390,107 @@ SourceSurfaceCGBitmapContext::~SourceSur
   if (!mImage && !mCg) {
     // neither mImage or mCg owns the data
     free(mData);
   }
   if (mImage)
     CGImageRelease(mImage);
 }
 
+SourceSurfaceCGIOSurfaceContext::SourceSurfaceCGIOSurfaceContext(DrawTargetCG *aDrawTarget)
+{
+  CGContextRef cg = (CGContextRef)aDrawTarget->GetNativeSurface(NATIVE_SURFACE_CGCONTEXT_ACCELERATED);
+
+  RefPtr<MacIOSurface> surf = MacIOSurface::IOSurfaceContextGetSurface(cg);
+
+  mSize.width = surf->GetWidth();
+  mSize.height = surf->GetHeight();
+
+  // TODO use CreateImageFromIOSurfaceContext instead of reading back the surface
+  //mImage = MacIOSurface::CreateImageFromIOSurfaceContext(cg);
+  mImage = NULL;
+
+  aDrawTarget->Flush();
+  surf->Lock();
+  size_t bytesPerRow = surf->GetBytesPerRow();
+  size_t ioHeight = surf->GetHeight();
+  void* ioData = surf->GetBaseAddress();
+  // XXX If the width is much less then the stride maybe
+  //     we should repack the image?
+  mData = malloc(ioHeight*bytesPerRow);
+  memcpy(mData, ioData, ioHeight*(bytesPerRow));
+  mStride = bytesPerRow;
+  surf->Unlock();
+}
+
+void SourceSurfaceCGIOSurfaceContext::EnsureImage() const
+{
+  // TODO Use CreateImageFromIOSurfaceContext and remove this
+
+  // Instead of using CGBitmapContextCreateImage we create
+  // a CGImage around the data associated with the CGBitmapContext
+  // we do this to avoid the vm_copy that CGBitmapContextCreateImage.
+  // vm_copy tends to cause all sorts of unexpected performance problems
+  // because of the mm tricks that vm_copy does. Using a regular
+  // memcpy when the bitmap context is modified gives us more predictable
+  // performance characteristics.
+  if (!mImage) {
+      //XXX: we should avoid creating this colorspace everytime
+      CGColorSpaceRef colorSpace = NULL;
+      CGBitmapInfo bitinfo = 0;
+      CGDataProviderRef dataProvider = NULL;
+      int bitsPerComponent = 8;
+      int bitsPerPixel = 32;
+
+      colorSpace = CGColorSpaceCreateDeviceRGB();
+      bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
+
+      void *info = mData;
+
+      dataProvider = CGDataProviderCreateWithData (info,
+                                                   mData,
+                                                   mSize.height * mStride,
+                                                   releaseCallback);
+
+      mImage = CGImageCreate (mSize.width, mSize.height,
+                              bitsPerComponent,
+                              bitsPerPixel,
+                              mStride,
+                              colorSpace,
+                              bitinfo,
+                              dataProvider,
+                              NULL,
+                              true,
+                              kCGRenderingIntentDefault);
+
+      CGDataProviderRelease(dataProvider);
+      CGColorSpaceRelease (colorSpace);
+  }
+
+}
+
+IntSize
+SourceSurfaceCGIOSurfaceContext::GetSize() const
+{
+  return mSize;
+}
+
+void
+SourceSurfaceCGIOSurfaceContext::DrawTargetWillChange()
+{
+}
+
+SourceSurfaceCGIOSurfaceContext::~SourceSurfaceCGIOSurfaceContext()
+{
+  if (mImage)
+    CGImageRelease(mImage);
+  else
+    free(mData);
+}
+
+unsigned char*
+SourceSurfaceCGIOSurfaceContext::GetData()
+{
+  return (unsigned char*)mData;
+}
+
 }
 }
--- a/gfx/2d/SourceSurfaceCG.h
+++ b/gfx/2d/SourceSurfaceCG.h
@@ -4,16 +4,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #pragma once
 
 #include <ApplicationServices/ApplicationServices.h>
 
 #include "2D.h"
 
+class MacIOSurface;
+
 namespace mozilla {
 namespace gfx {
 
 class DrawTargetCG;
 
 class SourceSurfaceCG : public SourceSurface
 {
 public:
@@ -70,17 +72,24 @@ private:
   CGImageRef mImage;
   //XXX: we don't need to store mData we can just get it from the CGContext
   void *mData;
   /* It might be better to just use the bitmap info from the CGImageRef to
    * deduce the format to save space in SourceSurfaceCG,
    * for now we just store it in mFormat */
 };
 
-class SourceSurfaceCGBitmapContext : public DataSourceSurface
+class SourceSurfaceCGContext : public DataSourceSurface
+{
+public:
+  virtual void DrawTargetWillChange() = 0;
+  virtual CGImageRef GetImage() = 0;
+};
+
+class SourceSurfaceCGBitmapContext : public SourceSurfaceCGContext
 {
 public:
   SourceSurfaceCGBitmapContext(DrawTargetCG *);
   ~SourceSurfaceCGBitmapContext();
 
   virtual SurfaceType GetType() const { return SURFACE_COREGRAPHICS_CGCONTEXT; }
   virtual IntSize GetSize() const;
   virtual SurfaceFormat GetFormat() const { return FORMAT_B8G8R8A8; }
@@ -89,17 +98,17 @@ public:
 
   virtual unsigned char *GetData() { return static_cast<unsigned char*>(mData); }
 
   virtual int32_t Stride() { return mStride; }
 
 private:
   //XXX: do the other backends friend their DrawTarget?
   friend class DrawTargetCG;
-  void DrawTargetWillChange();
+  virtual void DrawTargetWillChange();
   void EnsureImage() const;
 
   // We hold a weak reference to these two objects.
   // The cycle is broken by DrawTargetWillChange
   DrawTargetCG *mDrawTarget;
   CGContextRef mCg;
 
   mutable CGImageRef mImage;
@@ -107,11 +116,42 @@ private:
   // mData can be owned by three different things:
   // mImage, mCg or SourceSurfaceCGBitmapContext
   void *mData;
 
   int32_t mStride;
   IntSize mSize;
 };
 
+class SourceSurfaceCGIOSurfaceContext : public SourceSurfaceCGContext
+{
+public:
+  SourceSurfaceCGIOSurfaceContext(DrawTargetCG *);
+  ~SourceSurfaceCGIOSurfaceContext();
+
+  virtual SurfaceType GetType() const { return SURFACE_COREGRAPHICS_CGCONTEXT; }
+  virtual IntSize GetSize() const;
+  virtual SurfaceFormat GetFormat() const { return FORMAT_B8G8R8A8; }
+
+  CGImageRef GetImage() { EnsureImage(); return mImage; }
+
+  virtual unsigned char *GetData();
+
+  virtual int32_t Stride() { return mStride; }
+
+private:
+  //XXX: do the other backends friend their DrawTarget?
+  friend class DrawTargetCG;
+  virtual void DrawTargetWillChange();
+  void EnsureImage() const;
+
+  mutable CGImageRef mImage;
+  MacIOSurface* mIOSurface;
+
+  void *mData;
+  int32_t mStride;
+
+  IntSize mSize;
+};
+
 
 }
 }
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -36,16 +36,17 @@ enum SurfaceFormat
   FORMAT_A8
 };
 
 enum BackendType
 {
   BACKEND_NONE = 0,
   BACKEND_DIRECT2D,
   BACKEND_COREGRAPHICS,
+  BACKEND_COREGRAPHICS_ACCELERATED,
   BACKEND_CAIRO,
   BACKEND_SKIA
 };
 
 enum FontType
 {
   FONT_DWRITE,
   FONT_GDI,
@@ -54,17 +55,18 @@ enum FontType
   FONT_CAIRO,
   FONT_COREGRAPHICS
 };
 
 enum NativeSurfaceType
 {
   NATIVE_SURFACE_D3D10_TEXTURE,
   NATIVE_SURFACE_CAIRO_SURFACE,
-  NATIVE_SURFACE_CGCONTEXT
+  NATIVE_SURFACE_CGCONTEXT,
+  NATIVE_SURFACE_CGCONTEXT_ACCELERATED
 };
 
 enum NativeFontType
 {
   NATIVE_FONT_DWRITE_FONT_FACE,
   NATIVE_FONT_GDI_FONT_FACE,
   NATIVE_FONT_MAC_FONT_FACE,
   NATIVE_FONT_SKIA_FONT_FACE,
--- a/gfx/layers/ImageLayers.cpp
+++ b/gfx/layers/ImageLayers.cpp
@@ -9,28 +9,30 @@
 #include "SharedTextureImage.h"
 #include "gfxImageSurface.h"
 #include "gfxSharedImageSurface.h"
 #include "yuv_convert.h"
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "mozilla/layers/ImageContainerChild.h"
 
 #ifdef XP_MACOSX
-#include "nsCoreAnimationSupport.h"
+#include "mozilla/gfx/QuartzSupport.h"
 #endif
 
 #ifdef XP_WIN
 #include "gfxD2DSurface.h"
 #include "gfxWindowsPlatform.h"
 #include <d3d10_1.h>
 
 #include "d3d10/ImageLayerD3D10.h"
 #endif
 
 using namespace mozilla::ipc;
+using mozilla::gfx::DataSourceSurface;
+using mozilla::gfx::SourceSurface;
 
 namespace mozilla {
 namespace layers {
 
 already_AddRefed<Image>
 ImageFactory::CreateImage(const Image::Format *aFormats,
                           PRUint32 aNumFormats,
                           const gfxIntSize &,
@@ -489,24 +491,41 @@ PlanarYCbCrImage::GetAsSurface()
 
   return imageSurface.forget().get();
 }
 
 #ifdef XP_MACOSX
 void
 MacIOSurfaceImage::SetData(const Data& aData)
 {
-  mIOSurface = nsIOSurface::LookupSurface(aData.mIOSurface->GetIOSurfaceID());
+  mIOSurface = MacIOSurface::LookupSurface(aData.mIOSurface->GetIOSurfaceID());
   mSize = gfxIntSize(mIOSurface->GetWidth(), mIOSurface->GetHeight());
 }
 
 already_AddRefed<gfxASurface>
 MacIOSurfaceImage::GetAsSurface()
 {
-  return mIOSurface->GetAsSurface();
+  mIOSurface->Lock();
+  size_t bytesPerRow = mIOSurface->GetBytesPerRow();
+  size_t ioWidth = mIOSurface->GetWidth();
+  size_t ioHeight = mIOSurface->GetHeight();
+
+  unsigned char* ioData = (unsigned char*)mIOSurface->GetBaseAddress();
+
+  nsRefPtr<gfxImageSurface> imgSurface =
+    new gfxImageSurface(gfxIntSize(ioWidth, ioHeight), gfxASurface::ImageFormatARGB32);
+
+  for (int i = 0; i < ioHeight; i++) {
+    memcpy(imgSurface->Data() + i * imgSurface->Stride(),
+           ioData + i * bytesPerRow, ioWidth * 4);
+  }
+
+  mIOSurface->Unlock();
+
+  return imgSurface.forget();
 }
 
 void
 MacIOSurfaceImage::Update(ImageContainer* aContainer)
 {
   if (mUpdateCallback) {
     mUpdateCallback(aContainer, mPluginInstanceOwner);
   }
--- a/gfx/layers/ImageLayers.h
+++ b/gfx/layers/ImageLayers.h
@@ -13,17 +13,17 @@
 #include "nsThreadUtils.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/mozalloc.h"
 #include "mozilla/Mutex.h"
 #include "gfxPlatform.h"
 
 #ifdef XP_MACOSX
-#include "nsIOSurface.h"
+#include "mozilla/gfx/MacIOSurface.h"
 #endif
 #ifdef XP_WIN
 struct ID3D10Texture2D;
 struct ID3D10Device;
 struct ID3D10ShaderResourceView;
 
 typedef void* HANDLE;
 #endif
@@ -217,17 +217,17 @@ public:
  * be able to create images from any thread, to facilitate video playback
  * without involving the main thread, for example.
  * Different layer managers can implement child classes of this making it
  * possible to create layer manager specific images.
  * This class is not meant to be used directly but rather can be set on an
  * image container. This is usually done by the layer system internally and
  * not explicitly by users. For PlanarYCbCr or Cairo images the default
  * implementation will creates images whose data lives in system memory, for
- * MacIOSurfaces the default implementation will be a simple nsIOSurface
+ * MacIOSurfaces the default implementation will be a simple MacIOSurface
  * wrapper.
  */
 
 class THEBES_API ImageFactory
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageFactory)
 protected:
   friend class ImageContainer;
@@ -868,17 +868,17 @@ public:
   nsCountedRef<nsMainThreadSurfaceRef> mSurface;
   gfxIntSize mSize;
 };
 
 #ifdef XP_MACOSX
 class THEBES_API MacIOSurfaceImage : public Image {
 public:
   struct Data {
-    nsIOSurface* mIOSurface;
+    MacIOSurface* mIOSurface;
   };
 
   MacIOSurfaceImage()
     : Image(NULL, MAC_IO_SURFACE)
     , mSize(0, 0)
     , mPluginInstanceOwner(NULL)
     , mUpdateCallback(NULL)
     , mDestroyCallback(NULL)
@@ -916,28 +916,28 @@ public:
     mDestroyCallback = aCallback;
   }
 
   virtual gfxIntSize GetSize()
   {
     return mSize;
   }
 
-  nsIOSurface* GetIOSurface()
+  MacIOSurface* GetIOSurface()
   {
     return mIOSurface;
   }
 
   void Update(ImageContainer* aContainer);
 
   virtual already_AddRefed<gfxASurface> GetAsSurface();
 
 private:
   gfxIntSize mSize;
-  nsRefPtr<nsIOSurface> mIOSurface;
+  RefPtr<MacIOSurface> mIOSurface;
   void* mPluginInstanceOwner;
   UpdateSurfaceCallback mUpdateCallback;
   DestroyCallback mDestroyCallback;
 };
 #endif
 
 #ifdef MOZ_WIDGET_GONK
 /**
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -12,16 +12,17 @@
 #include "ImageLayers.h"
 #include "Layers.h"
 #include "gfxPlatform.h"
 #include "ReadbackLayer.h"
 #include "gfxUtils.h"
 #include "nsPrintfCString.h"
 #include "mozilla/Util.h"
 #include "LayerSorter.h"
+#include "AnimationCommon.h"
 
 using namespace mozilla::layers;
 using namespace mozilla::gfx;
 
 typedef FrameMetrics::ViewID ViewID;
 const ViewID FrameMetrics::NULL_SCROLL_ID = 0;
 const ViewID FrameMetrics::ROOT_SCROLL_ID = 1;
 const ViewID FrameMetrics::START_SCROLL_ID = 2;
@@ -215,16 +216,255 @@ LayerManager::CreateAsynchronousImageCon
 {
   nsRefPtr<ImageContainer> container = new ImageContainer(ImageContainer::ENABLE_ASYNC);
   return container.forget();
 }
 
 //--------------------------------------------------
 // Layer
 
+Layer::Layer(LayerManager* aManager, void* aImplData) :
+  mManager(aManager),
+  mParent(nullptr),
+  mNextSibling(nullptr),
+  mPrevSibling(nullptr),
+  mImplData(aImplData),
+  mMaskLayer(nullptr),
+  mXScale(1.0f),
+  mYScale(1.0f),
+  mOpacity(1.0),
+  mContentFlags(0),
+  mUseClipRect(false),
+  mUseTileSourceRect(false),
+  mIsFixedPosition(false),
+  mDebugColorIndex(0)
+{}
+
+Layer::~Layer()
+{}
+
+void
+Layer::AddAnimation(const Animation& aAnimation)
+{
+  if (!AsShadowableLayer() || !AsShadowableLayer()->HasShadow())
+    return;
+
+  MOZ_ASSERT(aAnimation.segments().Length() >= 1);
+
+  mAnimations.AppendElement(aAnimation);
+  Mutated();
+}
+
+void
+Layer::ClearAnimations()
+{
+  mAnimations.Clear();
+  mAnimationData.Clear();
+  Mutated();
+}
+
+static nsCSSValueList*
+CreateCSSValueList(const InfallibleTArray<TransformFunction>& aFunctions)
+{
+  nsAutoPtr<nsCSSValueList> result;
+  nsCSSValueList** resultTail = getter_Transfers(result);
+  for (PRUint32 i = 0; i < aFunctions.Length(); i++) {
+    nsRefPtr<nsCSSValue::Array> arr;
+    switch (aFunctions[i].type()) {
+      case TransformFunction::TRotationX:
+      {
+        float theta = aFunctions[i].get_RotationX().radians();
+        arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotatex, resultTail);
+        arr->Item(1).SetFloatValue(theta, eCSSUnit_Radian);
+        break;
+      }
+      case TransformFunction::TRotationY:
+      {
+        float theta = aFunctions[i].get_RotationY().radians();
+        arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotatey, resultTail);
+        arr->Item(1).SetFloatValue(theta, eCSSUnit_Radian);
+        break;
+      }
+      case TransformFunction::TRotationZ:
+      {
+        float theta = aFunctions[i].get_RotationZ().radians();
+        arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotatez, resultTail);
+        arr->Item(1).SetFloatValue(theta, eCSSUnit_Radian);
+        break;
+      }
+      case TransformFunction::TRotation:
+      {
+        float theta = aFunctions[i].get_Rotation().radians();
+        arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotate, resultTail);
+        arr->Item(1).SetFloatValue(theta, eCSSUnit_Radian);
+        break;
+      }
+      case TransformFunction::TRotation3D:
+      {
+        float x = aFunctions[i].get_Rotation3D().x();
+        float y = aFunctions[i].get_Rotation3D().y();
+        float z = aFunctions[i].get_Rotation3D().z();
+        float theta = aFunctions[i].get_Rotation3D().radians();
+        arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotate3d, resultTail);
+        arr->Item(1).SetFloatValue(x, eCSSUnit_Number);
+        arr->Item(2).SetFloatValue(y, eCSSUnit_Number);
+        arr->Item(3).SetFloatValue(z, eCSSUnit_Number);
+        arr->Item(4).SetFloatValue(theta, eCSSUnit_Radian);
+        break;
+      }
+      case TransformFunction::TScale:
+      {
+        arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_scale3d, resultTail);
+        arr->Item(1).SetFloatValue(aFunctions[i].get_Scale().x(), eCSSUnit_Number);
+        arr->Item(2).SetFloatValue(aFunctions[i].get_Scale().y(), eCSSUnit_Number);
+        arr->Item(3).SetFloatValue(aFunctions[i].get_Scale().z(), eCSSUnit_Number);
+        break;
+      }
+      case TransformFunction::TTranslation:
+      {
+        arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_translate3d, resultTail);
+        arr->Item(1).SetFloatValue(aFunctions[i].get_Translation().x(), eCSSUnit_Pixel);
+        arr->Item(2).SetFloatValue(aFunctions[i].get_Translation().y(), eCSSUnit_Pixel);
+        arr->Item(3).SetFloatValue(aFunctions[i].get_Translation().z(), eCSSUnit_Pixel);
+        break;
+      }
+      case TransformFunction::TSkewX:
+      {
+        float x = aFunctions[i].get_SkewX().x();
+        arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_skewx, resultTail);
+        arr->Item(1).SetFloatValue(x, eCSSUnit_Number);
+        break;
+      }
+      case TransformFunction::TSkewY:
+      {
+        float y = aFunctions[i].get_SkewY().y();
+        arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_skewy, resultTail);
+        arr->Item(1).SetFloatValue(y, eCSSUnit_Number);
+        break;
+      }
+      case TransformFunction::TTransformMatrix:
+      {
+        arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_matrix3d, resultTail);
+        const gfx3DMatrix& matrix = aFunctions[i].get_TransformMatrix().value();
+        arr->Item(1).SetFloatValue(matrix._11, eCSSUnit_Number);
+        arr->Item(2).SetFloatValue(matrix._12, eCSSUnit_Number);
+        arr->Item(3).SetFloatValue(matrix._13, eCSSUnit_Number);
+        arr->Item(4).SetFloatValue(matrix._14, eCSSUnit_Number);
+        arr->Item(5).SetFloatValue(matrix._21, eCSSUnit_Number);
+        arr->Item(6).SetFloatValue(matrix._22, eCSSUnit_Number);
+        arr->Item(7).SetFloatValue(matrix._23, eCSSUnit_Number);
+        arr->Item(8).SetFloatValue(matrix._24, eCSSUnit_Number);
+        arr->Item(9).SetFloatValue(matrix._31, eCSSUnit_Number);
+        arr->Item(10).SetFloatValue(matrix._32, eCSSUnit_Number);
+        arr->Item(11).SetFloatValue(matrix._33, eCSSUnit_Number);
+        arr->Item(12).SetFloatValue(matrix._34, eCSSUnit_Number);
+        arr->Item(13).SetFloatValue(matrix._41, eCSSUnit_Number);
+        arr->Item(14).SetFloatValue(matrix._42, eCSSUnit_Number);
+        arr->Item(15).SetFloatValue(matrix._43, eCSSUnit_Number);
+        arr->Item(16).SetFloatValue(matrix._44, eCSSUnit_Number);
+        break;
+      }
+      case TransformFunction::TPerspective:
+      {
+        float perspective = aFunctions[i].get_Perspective().value();
+        arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_perspective, resultTail);
+        arr->Item(1).SetFloatValue(perspective, eCSSUnit_Pixel);
+        break;
+      }
+      default:
+        NS_ASSERTION(false, "All functions should be implemented?");
+    }
+  }
+  return result.forget();
+}
+
+void
+Layer::SetAnimations(const AnimationArray& aAnimations)
+{
+  mAnimations = aAnimations;
+  mAnimationData.Clear();
+  for (PRUint32 i = 0; i < mAnimations.Length(); i++) {
+    AnimData data;
+    InfallibleTArray<css::ComputedTimingFunction*>* functions =
+      &data.mFunctions;
+    nsTArray<AnimationSegment> segments = mAnimations.ElementAt(i).segments();
+    for (PRUint32 j = 0; j < segments.Length(); j++) {
+      TimingFunction tf = segments.ElementAt(j).sampleFn();
+      css::ComputedTimingFunction* ctf = new css::ComputedTimingFunction();
+      switch (tf.type()) {
+        case TimingFunction::TCubicBezierFunction: {
+          CubicBezierFunction cbf = tf.get_CubicBezierFunction();
+          ctf->Init(nsTimingFunction(cbf.x1(), cbf.y1(), cbf.x2(), cbf.y2()));
+          break;
+        }
+        default: {
+          NS_ASSERTION(tf.type() == TimingFunction::TStepFunction,
+                       "Function must be bezier or step");
+          StepFunction sf = tf.get_StepFunction();
+          nsTimingFunction::Type type = sf.type() == 1 ? nsTimingFunction::StepStart
+                                                       : nsTimingFunction::StepEnd;
+          ctf->Init(nsTimingFunction(type, sf.steps()));
+          break;
+        }
+      }
+      functions->AppendElement(ctf);
+    }
+
+    // Precompute the nsStyleAnimation::Values that we need if this is a transform
+    // animation.
+    InfallibleTArray<nsStyleAnimation::Value>* startValues =
+      &data.mStartValues;
+    InfallibleTArray<nsStyleAnimation::Value>* endValues =
+      &data.mEndValues;
+    for (PRUint32 j = 0; j < mAnimations[i].segments().Length(); j++) {
+      const AnimationSegment& segment = mAnimations[i].segments()[j];
+      if (segment.endState().type() == Animatable::TArrayOfTransformFunction) {
+        const InfallibleTArray<TransformFunction>& startFunctions =
+          segment.startState().get_ArrayOfTransformFunction();
+        nsStyleAnimation::Value startValue;
+        nsCSSValueList* startList;
+        if (startFunctions.Length() > 0) {
+          startList = CreateCSSValueList(startFunctions);
+        } else {
+          startList = new nsCSSValueList();
+          startList->mValue.SetNoneValue();
+        }
+        startValue.SetAndAdoptCSSValueListValue(startList, nsStyleAnimation::eUnit_Transform);
+        startValues->AppendElement(startValue);
+
+        const InfallibleTArray<TransformFunction>& endFunctions =
+          segment.endState().get_ArrayOfTransformFunction();
+        nsStyleAnimation::Value endValue;
+        nsCSSValueList* endList;
+        if (endFunctions.Length() > 0) {
+          endList = CreateCSSValueList(endFunctions);
+        } else {
+          endList = new nsCSSValueList();
+          endList->mValue.SetNoneValue();
+        }
+        endValue.SetAndAdoptCSSValueListValue(endList, nsStyleAnimation::eUnit_Transform);
+        endValues->AppendElement(endValue);
+      } else {
+        NS_ASSERTION(segment.endState().type() == Animatable::TOpacity,
+                     "Unknown Animatable type");
+        nsStyleAnimation::Value startValue;
+        startValue.SetFloatValue(segment.startState().get_Opacity().value());
+        startValues->AppendElement(startValue);
+
+        nsStyleAnimation::Value endValue;
+        endValue.SetFloatValue(segment.endState().get_Opacity().value());
+        endValues->AppendElement(endValue);
+      }
+    }
+    mAnimationData.AppendElement(data);
+  }
+
+  Mutated();
+}
+
 bool
 Layer::CanUseOpaqueSurface()
 {
   // If the visible content in the layer is opaque, there is no need
   // for an alpha channel.
   if (GetContentFlags() & CONTENT_OPAQUE)
     return true;
   // Also, if this layer is the bottommost layer in a container which
@@ -299,17 +539,17 @@ Layer::SnapTransform(const gfx3DMatrix& 
       *aResidualTransform = matrix2D * snappedMatrixInverse;
     }
   } else {
     result = aTransform;
   }
   return result;
 }
 
-nsIntRect 
+nsIntRect
 Layer::CalculateScissorRect(const nsIntRect& aCurrentScissorRect,
                             const gfxMatrix* aWorldTransform)
 {
   ContainerLayer* container = GetParent();
   NS_ASSERTION(container, "This can't be called on the root!");
 
   // Establish initial clip rect: it's either the one passed in, or
   // if the parent has an intermediate surface, it's the extents of that surface.
@@ -376,23 +616,31 @@ Layer::GetLocalTransform()
   if (ShadowLayer* shadow = AsShadowLayer())
     transform = shadow->GetShadowTransform();
   else
     transform = mTransform;
   transform.Scale(mXScale, mYScale, 1);
   return transform;
 }
 
+const float
+Layer::GetLocalOpacity()
+{
+   if (ShadowLayer* shadow = AsShadowLayer())
+    return shadow->GetShadowOpacity();
+  return mOpacity;
+}
+
 float
 Layer::GetEffectiveOpacity()
 {
-  float opacity = GetOpacity();
+  float opacity = GetLocalOpacity();
   for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface();
        c = c->GetParent()) {
-    opacity *= c->GetOpacity();
+    opacity *= c->GetLocalOpacity();
   }
   return opacity;
 }
 
 void
 Layer::ComputeEffectiveTransformForMaskLayer(const gfx3DMatrix& aTransformToSurface)
 {
   if (mMaskLayer) {
@@ -797,34 +1045,34 @@ ReadbackLayer::PrintInfo(nsACString& aTo
 
 //--------------------------------------------------
 // LayerManager
 
 void
 LayerManager::Dump(FILE* aFile, const char* aPrefix)
 {
   FILE* file = FILEOrDefault(aFile);
- 
+
   fprintf(file, "<ul><li><a ");
 #ifdef MOZ_DUMP_PAINTING
   WriteSnapshotLinkToDumpFile(this, file);
 #endif
   fprintf(file, ">");
   DumpSelf(file, aPrefix);
 #ifdef MOZ_DUMP_PAINTING
   fprintf(file, "</a>");
 #endif
 
   nsCAutoString pfx(aPrefix);
   pfx += "  ";
   if (!GetRoot()) {
     fprintf(file, "%s(null)</li></ul>", pfx.get());
     return;
   }
- 
+
   fprintf(file, "<ul>");
   GetRoot()->Dump(file, pfx.get());
   fprintf(file, "</ul></li></ul>");
 }
 
 void
 LayerManager::DumpSelf(FILE* aFile, const char* aPrefix)
 {
@@ -948,10 +1196,10 @@ LayerManager::PrintInfo(nsACString& aTo,
 
 /*static*/ void LayerManager::InitLog() {}
 /*static*/ bool LayerManager::IsLogEnabled() { return false; }
 
 #endif // MOZ_LAYERS_HAVE_LOG
 
 PRLogModuleInfo* LayerManager::sLog;
 
-} // namespace layers 
+} // namespace layers
 } // namespace mozilla
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -13,16 +13,17 @@
 #include "nsRect.h"
 #include "nsISupportsImpl.h"
 #include "nsAutoPtr.h"
 #include "gfx3DMatrix.h"
 #include "gfxColor.h"
 #include "gfxPattern.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
+#include "nsStyleAnimation.h"
 #include "LayersTypes.h"
 #include "FrameMetrics.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/TimeStamp.h"
 
 #if defined(DEBUG) || defined(PR_LOGGING)
 #  include <stdio.h>            // FILE
 #  include "prlog.h"
@@ -39,18 +40,24 @@ struct PRLogModuleInfo;
 class gfxContext;
 class nsPaintEvent;
 
 namespace mozilla {
 namespace gl {
 class GLContext;
 }
 
+namespace css {
+class ComputedTimingFunction;
+}
+
 namespace layers {
 
+class Animation;
+class CommonLayerAttributes;
 class Layer;
 class ThebesLayer;
 class ContainerLayer;
 class ImageLayer;
 class ColorLayer;
 class ImageContainer;
 class CanvasLayer;
 class ReadbackLayer;
@@ -457,16 +464,23 @@ protected:
   static PRLogModuleInfo* sLog;
   uint64_t mId;
 private:
   TimeStamp mLastFrameTime;
   nsTArray<float> mFrameTimes;
 };
 
 class ThebesLayer;
+typedef InfallibleTArray<Animation> AnimationArray;
+
+struct AnimData {
+  InfallibleTArray<nsStyleAnimation::Value> mStartValues;
+  InfallibleTArray<nsStyleAnimation::Value> mEndValues;
+  InfallibleTArray<mozilla::css::ComputedTimingFunction*> mFunctions;
+};
 
 /**
  * A Layer represents anything that can be rendered onto a destination
  * surface.
  */
 class THEBES_API Layer {
   NS_INLINE_DECL_REFCOUNTING(Layer)  
 
@@ -478,17 +492,17 @@ public:
     TYPE_CONTAINER,
     TYPE_IMAGE,
     TYPE_READBACK,
     TYPE_REF,
     TYPE_SHADOW,
     TYPE_THEBES
   };
 
-  virtual ~Layer() {}
+  virtual ~Layer();
 
   /**
    * Returns the LayerManager this Layer belongs to. Note that the layer
    * manager might be in a destroyed state, at which point it's only
    * valid to set/get user data from it.
    */
   LayerManager* Manager() { return mManager; }
 
@@ -650,16 +664,24 @@ public:
   /**
    * CONSTRUCTION PHASE ONLY
    * A layer is "fixed position" when it draws content from a content
    * (not chrome) document, the topmost content document has a root scrollframe
    * with a displayport, but the layer does not move when that displayport scrolls.
    */
   void SetIsFixedPosition(bool aFixedPosition) { mIsFixedPosition = aFixedPosition; }
 
+  // Call AddAnimation to add an animation to this layer from layout code.
+  void AddAnimation(const Animation& aAnimation);
+  // ClearAnimations clears animations on this layer.
+  void ClearAnimations();
+  // This is only called when the layer tree is updated. Do not call this from
+  // layout code.  To add an animation to this layer, use AddAnimation.
+  void SetAnimations(const AnimationArray& aAnimations);
+
   /**
    * CONSTRUCTION PHASE ONLY
    * If a layer is "fixed position", this determines which point on the layer
    * is considered the "anchor" point, that is, the point which remains in the
    * same position when compositing the layer tree with a transformation
    * (such as when asynchronously scrolling and zooming).
    */
   void SetFixedPositionAnchor(const gfxPoint& aAnchor) { mAnchor = aAnchor; }
@@ -677,16 +699,18 @@ public:
   const gfx3DMatrix GetTransform();
   const gfx3DMatrix& GetBaseTransform() { return mTransform; }
   float GetXScale() { return mXScale; }
   float GetYScale() { return mYScale; }
   bool GetIsFixedPosition() { return mIsFixedPosition; }
   gfxPoint GetFixedPositionAnchor() { return mAnchor; }
   Layer* GetMaskLayer() { return mMaskLayer; }
 
+  AnimationArray& GetAnimations() { return mAnimations; }
+  InfallibleTArray<AnimData>& GetAnimationData() { return mAnimationData; }
   /**
    * DRAWING PHASE ONLY
    *
    * Write layer-subtype-specific attributes into aAttrs.  Used to
    * synchronize layer attributes to their shadows'.
    */
   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) { }
 
@@ -877,32 +901,17 @@ public:
   static bool IsLogEnabled() { return LayerManager::IsLogEnabled(); }
 
 #ifdef DEBUG
   void SetDebugColorIndex(PRUint32 aIndex) { mDebugColorIndex = aIndex; }
   PRUint32 GetDebugColorIndex() { return mDebugColorIndex; }
 #endif
 
 protected:
-  Layer(LayerManager* aManager, void* aImplData) :
-    mManager(aManager),
-    mParent(nullptr),
-    mNextSibling(nullptr),
-    mPrevSibling(nullptr),
-    mImplData(aImplData),
-    mMaskLayer(nullptr),
-    mXScale(1.0f),
-    mYScale(1.0f),
-    mOpacity(1.0),
-    mContentFlags(0),
-    mUseClipRect(false),
-    mUseTileSourceRect(false),
-    mIsFixedPosition(false),
-    mDebugColorIndex(0)
-    {}
+  Layer(LayerManager* aManager, void* aImplData);
 
   void Mutated() { mManager->Mutated(this); }
 
   // Print interesting information about this into aTo.  Internally
   // used to implement Dump*() and Log*().  If subclasses have
   // additional interesting properties, they should override this with
   // an implementation that first calls the base implementation then
   // appends additional info to aTo.
@@ -910,16 +919,22 @@ protected:
 
   /**
    * Returns the local transform for this layer: either mTransform or,
    * for shadow layers, GetShadowTransform()
    */
   const gfx3DMatrix GetLocalTransform();
 
   /**
+   * Returns the local opacity for this layer: either mOpacity or,
+   * for shadow layers, GetShadowOpacity()
+   */
+  const float GetLocalOpacity();
+
+  /**
    * Computes a tweaked version of aTransform that snaps a point or a rectangle
    * to pixel boundaries. Snapping is only performed if this layer's
    * layer manager has enabled snapping (which is the default).
    * @param aSnapRect a rectangle whose edges should be snapped to pixel
    * boundaries in the destination surface. If the rectangle is empty,
    * then the snapping process should preserve the scale factors of the
    * transform matrix
    * @param aResidualTransform a transform to apply before mEffectiveTransform
@@ -936,16 +951,18 @@ protected:
   void* mImplData;
   nsRefPtr<Layer> mMaskLayer;
   gfx::UserData mUserData;
   nsIntRegion mVisibleRegion;
   gfx3DMatrix mTransform;
   float mXScale;
   float mYScale;
   gfx3DMatrix mEffectiveTransform;
+  AnimationArray mAnimations;
+  InfallibleTArray<AnimData> mAnimationData;
   float mOpacity;
   nsIntRect mClipRect;
   nsIntRect mTileSourceRect;
   PRUint32 mContentFlags;
   bool mUseClipRect;
   bool mUseTileSourceRect;
   bool mIsFixedPosition;
   gfxPoint mAnchor;
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -27,26 +27,28 @@ ifdef MOZ_DEBUG
 DEFINES += -DD3D_DEBUG_INFO
 endif
 
 EXPORTS = \
         BasicLayers.h \
         BasicTiledThebesLayer.h \
         BasicImplData.h \
         FrameMetrics.h \
+        CompositorParent.h \
         ImageLayers.h \
         Layers.h \
         LayersTypes.h \
         LayerManagerOGLShaders.h \
         LayerManagerOGL.h \
         LayerManagerOGLProgram.h \
+        LayerSorter.h \
         ReadbackLayer.h \
-        LayerSorter.h \
+        ShadowLayersManager.h \
+        SharedTextureImage.h \
         TexturePoolOGL.h \
-        SharedTextureImage.h \
         $(NULL)
 
 CPPSRCS = \
         BasicImages.cpp \
         BasicLayerManager.cpp \
         BasicCanvasLayer.cpp \
         BasicColorLayer.cpp \
         BasicContainerLayer.cpp \
--- a/gfx/layers/basic/BasicCanvasLayer.cpp
+++ b/gfx/layers/basic/BasicCanvasLayer.cpp
@@ -112,16 +112,18 @@ BasicCanvasLayer::Initialize(const Data&
   mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
 }
 
 void
 BasicCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer)
 {
   if (mDrawTarget) {
     mDrawTarget->Flush();
+    // TODO Fix me before turning accelerated quartz canvas by default
+    //mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
   }
 
   if (!mGLContext && aDestSurface) {
     nsRefPtr<gfxContext> tmpCtx = new gfxContext(aDestSurface);
     tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
     BasicCanvasLayer::PaintWithOpacity(tmpCtx, 1.0f, aMaskLayer);
     return;
   }
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -741,18 +741,18 @@ BasicLayerManager::PaintLayer(gfxContext
       const IntRect& targetOpaqueRect = dt->GetOpaqueRect();
 
       // Try to annotate currentSurface with a region of pixels that have been
       // (or will be) painted opaque, if no such region is currently set.
       if (targetOpaqueRect.IsEmpty() && visibleRegion.GetNumRects() == 1 &&
           (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
           !transform.HasNonAxisAlignedTransform()) {
 
-        Rect opaqueRect = dt->GetTransform().TransformBounds(
-          Rect(bounds.x, bounds.y, bounds.width, bounds.height));
+        gfx::Rect opaqueRect = dt->GetTransform().TransformBounds(
+          gfx::Rect(bounds.x, bounds.y, bounds.width, bounds.height));
         opaqueRect.RoundIn();
         IntRect intOpaqueRect;
         if (opaqueRect.ToIntRect(&intOpaqueRect)) {
           aTarget->GetDrawTarget()->SetOpaqueRect(intOpaqueRect);
           pushedTargetOpaqueRect = true;
         }
       }
     }
--- a/gfx/layers/basic/BasicThebesLayer.cpp
+++ b/gfx/layers/basic/BasicThebesLayer.cpp
@@ -55,17 +55,17 @@ SetAntialiasingFlags(Layer* aLayer, gfxC
   if (!aTarget->IsCairo()) {
     RefPtr<DrawTarget> dt = aTarget->GetDrawTarget();
 
     if (dt->GetFormat() != FORMAT_B8G8R8A8) {
       return;
     }
 
     const nsIntRect& bounds = aLayer->GetVisibleRegion().GetBounds();
-    Rect transformedBounds = dt->GetTransform().TransformBounds(Rect(Float(bounds.x), Float(bounds.y),
+    gfx::Rect transformedBounds = dt->GetTransform().TransformBounds(gfx::Rect(Float(bounds.x), Float(bounds.y),
                                                                      Float(bounds.width), Float(bounds.height)));
     transformedBounds.RoundOut();
     IntRect intTransformedBounds;
     transformedBounds.ToIntRect(&intTransformedBounds);
     dt->SetPermitSubpixelAA(!(aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA) ||
                             dt->GetOpaqueRect().Contains(intTransformedBounds));
   } else {
     nsRefPtr<gfxASurface> surface = aTarget->CurrentSurface();
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -16,16 +16,25 @@
 #include "AsyncPanZoomController.h"
 #include "BasicLayers.h"
 #include "CompositorParent.h"
 #include "LayerManagerOGL.h"
 #include "nsGkAtoms.h"
 #include "nsIWidget.h"
 #include "RenderTrace.h"
 #include "ShadowLayersParent.h"
+#include "BasicLayers.h"
+#include "LayerManagerOGL.h"
+#include "nsIWidget.h"
+#include "nsGkAtoms.h"
+#include "RenderTrace.h"
+#include "nsStyleAnimation.h"
+#include "nsDisplayList.h"
+#include "AnimationCommon.h"
+#include "nsAnimationManager.h"
 
 using namespace base;
 using namespace mozilla::ipc;
 using namespace std;
 
 namespace mozilla {
 namespace layers {
 
@@ -426,25 +435,25 @@ CompositorParent::Composite()
   mCurrentCompositeTask = NULL;
 
   mLastCompose = TimeStamp::Now();
 
   if (mPaused || !mLayerManager || !mLayerManager->GetRoot()) {
     return;
   }
 
-  Layer* aLayer = mLayerManager->GetRoot();
-  AutoResolveRefLayers resolve(aLayer);
+  Layer* layer = mLayerManager->GetRoot();
+  AutoResolveRefLayers resolve(layer);
 
   bool requestNextFrame = TransformShadowTree(mLastCompose);
   if (requestNextFrame) {
     ScheduleComposition();
   }
 
-  RenderTraceLayers(aLayer, "0000");
+  RenderTraceLayers(layer, "0000");
 
   if (LAYERS_OPENGL == mLayerManager->GetBackendType() &&
       !mTargetConfig.naturalBounds().IsEmpty()) {
     LayerManagerOGL* lm = static_cast<LayerManagerOGL*>(mLayerManager.get());
     lm->SetWorldTransform(
       ComputeGLTransformForRotation(mTargetConfig.naturalBounds(),
                                     mTargetConfig.rotation()));
   }
@@ -538,23 +547,131 @@ static void
 SetShadowProperties(Layer* aLayer)
 {
   // FIXME: Bug 717688 -- Do these updates in ShadowLayersParent::RecvUpdate.
   ShadowLayer* shadow = aLayer->AsShadowLayer();
   // Set the shadow's base transform to the layer's base transform.
   shadow->SetShadowTransform(aLayer->GetBaseTransform());
   shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
   shadow->SetShadowClipRect(aLayer->GetClipRect());
+  shadow->SetShadowOpacity(aLayer->GetOpacity());
 
   for (Layer* child = aLayer->GetFirstChild();
       child; child = child->GetNextSibling()) {
     SetShadowProperties(child);
   }
 }
 
+// SampleValue should eventually take the CSS property as an argument.  This
+// will be needed if we ever animate two values with the same type but different
+// interpolation rules.
+static void
+SampleValue(float aPortion, Animation& aAnimation, nsStyleAnimation::Value& aStart,
+            nsStyleAnimation::Value& aEnd, Animatable* aValue)
+{
+  nsStyleAnimation::Value interpolatedValue;
+  NS_ASSERTION(aStart.GetUnit() == aEnd.GetUnit() ||
+               aStart.GetUnit() == nsStyleAnimation::eUnit_None ||
+               aEnd.GetUnit() == nsStyleAnimation::eUnit_None, "Must have same unit");
+  if (aStart.GetUnit() == nsStyleAnimation::eUnit_Transform ||
+      aEnd.GetUnit() == nsStyleAnimation::eUnit_Transform) {
+    nsStyleAnimation::Interpolate(eCSSProperty_transform, aStart, aEnd,
+                                  aPortion, interpolatedValue);
+    nsCSSValueList* interpolatedList = interpolatedValue.GetCSSValueListValue();
+
+    TransformData& data = aAnimation.data().get_TransformData();
+    gfx3DMatrix transform =
+      nsDisplayTransform::GetResultingTransformMatrix(nullptr, data.origin(), nsDeviceContext::AppUnitsPerCSSPixel(),
+                                                      &data.bounds(), interpolatedList, &data.mozOrigin(),
+                                                      &data.perspectiveOrigin(), &data.perspective());
+
+    InfallibleTArray<TransformFunction>* functions = new InfallibleTArray<TransformFunction>();
+    functions->AppendElement(TransformMatrix(transform));
+    *aValue = *functions;
+    return;
+  }
+
+  NS_ASSERTION(aStart.GetUnit() == nsStyleAnimation::eUnit_Float, "Should be opacity");
+  nsStyleAnimation::Interpolate(eCSSProperty_opacity, aStart, aEnd,
+                                aPortion, interpolatedValue);
+  *aValue = interpolatedValue.GetFloatValue();
+}
+
+static bool
+SampleAnimations(Layer* aLayer, TimeStamp aPoint)
+{
+  AnimationArray& animations = aLayer->GetAnimations();
+  InfallibleTArray<AnimData>& animationData = aLayer->GetAnimationData();
+
+  bool activeAnimations = false;
+
+  for (PRUint32 i = animations.Length(); i-- !=0; ) {
+    Animation& animation = animations[i];
+    AnimData& animData = animationData[i];
+
+    double numIterations = animation.numIterations() != -1 ?
+      animation.numIterations() : NS_IEEEPositiveInfinity();
+    double positionInIteration =
+      ElementAnimations::GetPositionInIteration(animation.startTime(),
+                                                aPoint,
+                                                animation.duration(),
+                                                numIterations,
+                                                animation.direction());
+
+    if (positionInIteration == -1) {
+        animations.RemoveElementAt(i);
+        animationData.RemoveElementAt(i);
+        continue;
+    }
+
+    NS_ABORT_IF_FALSE(0.0 <= positionInIteration &&
+                          positionInIteration <= 1.0,
+                        "position should be in [0-1]");
+
+    int segmentIndex = 0;
+    AnimationSegment* segment = animation.segments().Elements();
+    while (segment->endPortion() < positionInIteration) {
+      ++segment;
+      ++segmentIndex;
+    }
+
+    double positionInSegment = (positionInIteration - segment->startPortion()) /
+                                 (segment->endPortion() - segment->startPortion());
+
+    double portion = animData.mFunctions[segmentIndex]->GetValue(positionInSegment);
+
+    activeAnimations = true;
+
+    // interpolate the property
+    Animatable interpolatedValue;
+    SampleValue(portion, animation, animData.mStartValues[segmentIndex],
+                animData.mEndValues[segmentIndex], &interpolatedValue);
+    ShadowLayer* shadow = aLayer->AsShadowLayer();
+    switch (interpolatedValue.type()) {
+    case Animatable::TOpacity:
+      shadow->SetShadowOpacity(interpolatedValue.get_Opacity().value());
+      break;
+   case Animatable::TArrayOfTransformFunction: {
+      gfx3DMatrix matrix = interpolatedValue.get_ArrayOfTransformFunction()[0].get_TransformMatrix().value();
+      shadow->SetShadowTransform(matrix);
+      break;
+    }
+    default:
+      NS_WARNING("Unhandled animated property");
+    }
+  }
+
+  for (Layer* child = aLayer->GetFirstChild(); child;
+       child = child->GetNextSibling()) {
+    activeAnimations |= SampleAnimations(child, aPoint);
+  }
+
+  return activeAnimations;
+}
+
 bool
 CompositorParent::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFrame,
                                                    Layer *aLayer,
                                                    bool* aWantNextFrame)
 {
   bool appliedTransform = false;
   for (Layer* child = aLayer->GetFirstChild();
       child; child = child->GetNextSibling()) {
@@ -590,16 +707,20 @@ bool
 CompositorParent::TransformShadowTree(TimeStamp aCurrentFrame)
 {
   bool wantNextFrame = false;
   Layer* layer = GetPrimaryScrollableLayer();
   ShadowLayer* shadow = layer->AsShadowLayer();
   ContainerLayer* container = layer->AsContainerLayer();
   Layer* root = mLayerManager->GetRoot();
 
+  // NB: we must sample animations *before* sampling pan/zoom
+  // transforms.
+  wantNextFrame |= SampleAnimations(layer, mLastCompose);
+
   const FrameMetrics& metrics = container->GetFrameMetrics();
   // We must apply the resolution scale before a pan/zoom transform, so we call
   // GetTransform here.
   const gfx3DMatrix& rootTransform = root->GetTransform();
   const gfx3DMatrix& currentTransform = layer->GetTransform();
 
   // FIXME/bug 775437: unify this interface with the ~native-fennec
   // derived code
--- a/gfx/layers/ipc/PLayer.ipdl
+++ b/gfx/layers/ipc/PLayer.ipdl
@@ -9,17 +9,17 @@ include protocol PLayers;
 
 namespace mozilla {
 namespace layers {
 
 /**
  * PLayer represents a layer shared across thread contexts.
  */
 
-sync protocol PLayer {
+async protocol PLayer {
     manager PLayers;
 
     /**
      * OWNERSHIP MODEL
      *
      * Roughly speaking, the child side "actually owns" a Layer.  This
      * is because the parent side is the "shadow"; when the child
      * releases a Layer, the parent's shadow is no longer meaningful.
@@ -27,13 +27,13 @@ sync protocol PLayer {
      * To implement this model, the concrete PLayerParent keeps a
      * strong ref to its Layer, so the Layer's lifetime is bound to
      * the PLayerParent's.  Then, when the Layer's refcount hits 0 on
      * the child side, we send __delete__() from the child to parent.
      * The parent then releases its Layer, which results in the Layer
      * being deleted "soon" (usually immediately).
      */
 parent:
-    __delete__();
+    async __delete__();
 };
 
 } // layers
 } // mozilla
--- a/gfx/layers/ipc/PLayers.ipdl
+++ b/gfx/layers/ipc/PLayers.ipdl
@@ -9,16 +9,24 @@ include LayersSurfaces;
 using mozilla::ScreenRotation;
 include protocol PCompositor;
 include protocol PGrallocBuffer;
 include protocol PLayer;
 include protocol PRenderFrame;
 
 include "gfxipc/ShadowLayerUtils.h";
 include "mozilla/WidgetUtils.h";
+include "mozilla/TimeStamp.h";
+
+using gfxPoint3D;
+using nscoord;
+using nsRect;
+using nsPoint;
+using mozilla::TimeDuration;
+using mozilla::TimeStamp;
 
 /**
  * The layers protocol is spoken between thread contexts that manage
  * layer (sub)trees.  The protocol comprises atomically publishing
  * layer subtrees to a "shadow" thread context (which grafts the
  * subtree into its own tree), and atomically updating a published
  * subtree.  ("Atomic" in this sense is wrt painting.)
  */
@@ -37,45 +45,149 @@ struct OpCreateContainerLayer  { PLayer 
 struct OpCreateImageLayer      { PLayer layer; };
 struct OpCreateColorLayer      { PLayer layer; };
 struct OpCreateCanvasLayer     { PLayer layer; };
 struct OpCreateRefLayer        { PLayer layer; };
 
 struct ThebesBuffer {
   SurfaceDescriptor buffer;
   nsIntRect rect;
-  nsIntPoint rotation; 
+  nsIntPoint rotation;
 };
 union OptionalThebesBuffer { ThebesBuffer; null_t; };
 
 union CanvasSurface {
   SurfaceDescriptor;
   null_t;
 };
 
+struct CubicBezierFunction {
+  float x1;
+  float y1;
+  float x2;
+  float y2;
+};
+
+struct StepFunction {
+  int steps;
+  // 1 = nsTimingFunction::StepStart, 2 = nsTimingFunction::StepEnd
+  int type;
+};
+
+union TimingFunction {
+  CubicBezierFunction;
+  StepFunction;
+};
+
+struct Color { gfxRGBA value; };
+struct Opacity { float value; };
+struct Perspective { float value; };
+struct RotationX { float radians; };
+struct RotationY { float radians; };
+struct RotationZ { float radians; };
+struct Rotation { float radians; };
+struct Rotation3D {
+  float x;
+  float y;
+  float z;
+  float radians;
+};
+struct Scale {
+  float x;
+  float y;
+  float z;
+};
+struct SkewX { float x; };
+struct SkewY { float y; };
+struct TransformMatrix { gfx3DMatrix value; };
+struct Translation {
+  float x;
+  float y;
+  float z;
+};
+
+union TransformFunction {
+  Perspective;
+  RotationX;
+  RotationY;
+  RotationZ;
+  Rotation;
+  Rotation3D;
+  Scale;
+  SkewX;
+  SkewY;
+  Translation;
+  TransformMatrix;
+};
+
+union Animatable {
+  Color;
+  Opacity;
+  TransformFunction[];
+};
+
+struct AnimationSegment {
+  Animatable startState;
+  Animatable endState;
+  float startPortion;
+  float endPortion;
+  TimingFunction sampleFn;
+};
+
+// Transforms need extra information to correctly convert the list of transform
+// functions to a gfx3DMatrix that can be applied directly to the layer.
+struct TransformData {
+  nsPoint origin;
+  gfxPoint3D mozOrigin;
+  gfxPoint3D perspectiveOrigin;
+  nsRect bounds;
+  nscoord perspective;
+};
+
+union AnimationData {
+  null_t;
+  TransformData;
+};
+
+struct Animation {
+  TimeStamp startTime;
+  TimeDuration duration;
+  // For each frame, the interpolation point is computed based on the
+  // startTime, the direction, the duration, and the current time.
+  // The segments must uniquely cover the portion from 0.0 to 1.0
+  AnimationSegment[] segments;
+  // How many times to repeat the animation.  < 0 means "forever".
+  float numIterations;
+  // This uses the NS_STYLE_ANIMATION_DIRECTION_* constants.
+  int32_t direction;
+  AnimationData data;
+};
+
 // Change a layer's attributes
 struct CommonLayerAttributes {
   nsIntRegion visibleRegion;
+  TransformMatrix transform;
   float xScale;
   float yScale;
-  gfx3DMatrix transform;
   PRUint32 contentFlags;
-  float opacity;
+  Opacity opacity;
   bool useClipRect;
   nsIntRect clipRect;
   bool isFixedPosition;
   gfxPoint fixedPositionAnchor;
   nullable PLayer maskLayer;
-};
+  // Animated colors will only honored for ColorLayers.
+  Animation[] animations;
+ };
 
 struct ThebesLayerAttributes {
   nsIntRegion validRegion;
 };
 struct ContainerLayerAttributes{ FrameMetrics metrics; };
-struct ColorLayerAttributes    { gfxRGBA color; };
+struct ColorLayerAttributes    { Color color; };
 struct CanvasLayerAttributes   { GraphicsFilterType filter; };
 struct RefLayerAttributes      { int64_t id; };
 struct ImageLayerAttributes    {
   GraphicsFilterType filter;
   bool forceSingleTile;
 };
 
 union SpecificLayerAttributes {
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -309,16 +309,17 @@ ShadowLayerForwarder::EndTransaction(Inf
     common.isFixedPosition() = mutant->GetIsFixedPosition();
     common.fixedPositionAnchor() = mutant->GetFixedPositionAnchor();
     if (Layer* maskLayer = mutant->GetMaskLayer()) {
       common.maskLayerChild() = Shadow(maskLayer->AsShadowableLayer());
     } else {
       common.maskLayerChild() = NULL;
     }
     common.maskLayerParent() = NULL;
+    common.animations() = mutant->GetAnimations();
     attrs.specific() = null_t();
     mutant->FillSpecificAttributes(attrs.specific());
 
     mTxn->AddEdit(OpSetLayerAttributes(NULL, Shadow(shadow), attrs));
   }
 
   AutoInfallibleTArray<Edit, 10> cset;
   size_t nCsets = mTxn->mCset.size() + mTxn->mPaints.size();
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -518,46 +518,54 @@ public:
    *
    * They are analogous to the Layer interface.
    */
   void SetShadowVisibleRegion(const nsIntRegion& aRegion)
   {
     mShadowVisibleRegion = aRegion;
   }
 
+  void SetShadowOpacity(float aOpacity)
+  {
+    mShadowOpacity = aOpacity;
+  }
+
   void SetShadowClipRect(const nsIntRect* aRect)
   {
     mUseShadowClipRect = aRect != nullptr;
     if (aRect) {
       mShadowClipRect = *aRect;
     }
   }
 
   void SetShadowTransform(const gfx3DMatrix& aMatrix)
   {
     mShadowTransform = aMatrix;
   }
 
   // These getters can be used anytime.
+  float GetShadowOpacity() { return mShadowOpacity; }
   const nsIntRect* GetShadowClipRect() { return mUseShadowClipRect ? &mShadowClipRect : nullptr; }
   const nsIntRegion& GetShadowVisibleRegion() { return mShadowVisibleRegion; }
   const gfx3DMatrix& GetShadowTransform() { return mShadowTransform; }
 
   virtual TiledLayerComposer* AsTiledLayerComposer() { return NULL; }
 
 protected:
   ShadowLayer()
     : mAllocator(nullptr)
+    , mShadowOpacity(1.0f)
     , mUseShadowClipRect(false)
   {}
 
   ISurfaceDeAllocator* mAllocator;
   nsIntRegion mShadowVisibleRegion;
   gfx3DMatrix mShadowTransform;
   nsIntRect mShadowClipRect;
+  float mShadowOpacity;
   bool mUseShadowClipRect;
 };
 
 
 class ShadowThebesLayer : public ShadowLayer,
                           public ThebesLayer
 {
 public:
--- a/gfx/layers/ipc/ShadowLayersParent.cpp
+++ b/gfx/layers/ipc/ShadowLayersParent.cpp
@@ -209,30 +209,31 @@ ShadowLayersParent::RecvUpdate(const Inf
 
       const OpSetLayerAttributes& osla = edit.get_OpSetLayerAttributes();
       Layer* layer = AsShadowLayer(osla)->AsLayer();
       const LayerAttributes& attrs = osla.attrs();
 
       const CommonLayerAttributes& common = attrs.common();
       layer->SetVisibleRegion(common.visibleRegion());
       layer->SetContentFlags(common.contentFlags());
-      layer->SetOpacity(common.opacity());
+      layer->SetOpacity(common.opacity().value());
       layer->SetClipRect(common.useClipRect() ? &common.clipRect() : NULL);
-      layer->SetBaseTransform(common.transform());
+      layer->SetBaseTransform(common.transform().value());
       layer->SetScale(common.xScale(), common.yScale());
       static bool fixedPositionLayersEnabled = getenv("MOZ_ENABLE_FIXED_POSITION_LAYERS") != 0;
       if (fixedPositionLayersEnabled) {
         layer->SetIsFixedPosition(common.isFixedPosition());
         layer->SetFixedPositionAnchor(common.fixedPositionAnchor());
       }
       if (PLayerParent* maskLayer = common.maskLayerParent()) {
         layer->SetMaskLayer(cast(maskLayer)->AsLayer());
       } else {
         layer->SetMaskLayer(NULL);
       }
+      layer->SetAnimations(common.animations());
 
       typedef SpecificLayerAttributes Specific;
       const SpecificLayerAttributes& specific = attrs.specific();
       switch (specific.type()) {
       case Specific::Tnull_t:
         break;
 
       case Specific::TThebesLayerAttributes: {
@@ -253,17 +254,17 @@ ShadowLayersParent::RecvUpdate(const Inf
         static_cast<ContainerLayer*>(layer)->SetFrameMetrics(
           specific.get_ContainerLayerAttributes().metrics());
         break;
 
       case Specific::TColorLayerAttributes:
         MOZ_LAYERS_LOG(("[ParentSide]   color layer"));
 
         static_cast<ColorLayer*>(layer)->SetColor(
-          specific.get_ColorLayerAttributes().color());
+          specific.get_ColorLayerAttributes().color().value());
         break;
 
       case Specific::TCanvasLayerAttributes:
         MOZ_LAYERS_LOG(("[ParentSide]   canvas layer"));
 
         static_cast<CanvasLayer*>(layer)->SetFilter(
           specific.get_CanvasLayerAttributes().filter());
         break;
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -119,16 +119,53 @@ CanvasLayerOGL::Initialize(const Data& a
     MakeTextureIfNeeded(gl(), mTexture);
     // This should only ever occur with 2d canvas, WebGL can't already have a texture
     // of this size can it?
     NS_ABORT_IF_FALSE(mCanvasSurface || mDrawTarget, 
                       "Invalid texture size when WebGL surface already exists at that size?");
   }
 }
 
+#ifdef XP_MACOSX
+static GLuint
+MakeIOSurfaceTexture(void* aCGIOSurfaceContext, mozilla::gl::GLContext* aGL)
+{
+  GLuint ioSurfaceTexture;
+
+  aGL->fGenTextures(1, &ioSurfaceTexture);
+
+  aGL->fActiveTexture(LOCAL_GL_TEXTURE0);
+  aGL->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, ioSurfaceTexture);
+
+  aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
+  aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
+  aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
+  aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
+
+  RefPtr<MacIOSurface> ioSurface = MacIOSurface::IOSurfaceContextGetSurface((CGContextRef)aCGIOSurfaceContext);
+  void *nativeCtx = aGL->GetNativeData(GLContext::NativeGLContext);
+
+  ioSurface->CGLTexImageIOSurface2D(nativeCtx,
+                                    LOCAL_GL_RGBA, LOCAL_GL_BGRA,
+                                    LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV, 0);
+
+  aGL->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0);
+
+  return ioSurfaceTexture;
+}
+
+#else
+static GLuint
+MakeIOSurfaceTexture(void* aCGIOSurfaceContext, mozilla::gl::GLContext* aGL)
+{
+  NS_RUNTIMEABORT("Not implemented");
+  return 0;
+}
+#endif
+
 /**
  * Following UpdateSurface(), mTexture on context this->gl() should contain the data we want,
  * unless mDelayedUpdates is true because of a too-large surface.
  */
 void
 CanvasLayerOGL::UpdateSurface()
 {
   if (!mDirty)
@@ -198,17 +235,17 @@ CanvasLayerOGL::RenderLayer(int aPreviou
 
   // XXX We're going to need a different program depending on if
   // mGLBufferIsPremultiplied is TRUE or not.  The RGBLayerProgram
   // assumes that it's true.
 
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
 
   if (mTexture) {
-    gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
+    gl()->fBindTexture(mTextureTarget, mTexture);
   }
 
   ShaderProgramOGL *program = nullptr;
 
   bool useGLContext = mCanvasGLContext &&
     mCanvasGLContext->GetContextType() == gl()->GetContextType();
 
   nsIntRect drawRect = mBounds;
@@ -239,16 +276,20 @@ CanvasLayerOGL::RenderLayer(int aPreviou
   if (mPixmap && !mDelayedUpdates) {
     sGLXLibrary.BindTexImage(mPixmap);
   }
 #endif
 
   gl()->ApplyFilterToBoundTexture(mFilter);
 
   program->Activate();
+  if (mLayerProgram == gl::RGBARectLayerProgramType) {
+    // This is used by IOSurface that use 0,0...w,h coordinate rather then 0,0..1,1.
+    program->SetTexCoordMultiplier(mDrawTarget->GetSize().width, mDrawTarget->GetSize().height);
+  }
   program->SetLayerQuadRect(drawRect);
   program->SetLayerTransform(GetEffectiveTransform());
   program->SetLayerOpacity(GetEffectiveOpacity());
   program->SetRenderOffset(aOffset);
   program->SetTextureUnit(0);
   program->LoadMask(GetMaskLayer());
 
   if (gl()->CanUploadNonPowerOfTwo()) {
@@ -286,17 +327,17 @@ IsValidSharedTexDescriptor(const Surface
 ShadowCanvasLayerOGL::ShadowCanvasLayerOGL(LayerManagerOGL* aManager)
   : ShadowCanvasLayer(aManager, nullptr)
   , LayerOGL(aManager)
   , mNeedsYFlip(false)
   , mTexture(0)
 {
   mImplData = static_cast<LayerOGL*>(this);
 }
- 
+
 ShadowCanvasLayerOGL::~ShadowCanvasLayerOGL()
 {}
 
 void
 ShadowCanvasLayerOGL::Initialize(const Data& aData)
 {
   NS_RUNTIMEABORT("Incompatibe surface type");
 }
--- a/gfx/layers/opengl/CanvasLayerOGL.h
+++ b/gfx/layers/opengl/CanvasLayerOGL.h
@@ -21,16 +21,17 @@ class THEBES_API CanvasLayerOGL :
   public CanvasLayer,
   public LayerOGL
 {
 public:
   CanvasLayerOGL(LayerManagerOGL *aManager)
     : CanvasLayer(aManager, NULL),
       LayerOGL(aManager),
       mTexture(0),
+      mTextureTarget(LOCAL_GL_TEXTURE_2D),
       mDelayedUpdates(false)
 #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
       ,mPixmap(0)
 #endif
   { 
       mImplData = static_cast<LayerOGL*>(this);
   }
   ~CanvasLayerOGL() { Destroy(); }
@@ -49,16 +50,17 @@ protected:
   void UpdateSurface();
 
   nsRefPtr<gfxASurface> mCanvasSurface;
   nsRefPtr<GLContext> mCanvasGLContext;
   gl::ShaderProgramType mLayerProgram;
   RefPtr<gfx::DrawTarget> mDrawTarget;
 
   GLuint mTexture;
+  GLenum mTextureTarget;
 
   bool mDelayedUpdates;
   bool mGLBufferIsPremultiplied;
   bool mNeedsYFlip;
 #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
   GLXPixmap mPixmap;
 #endif
 
--- a/gfx/src/nsRect.h
+++ b/gfx/src/nsRect.h
@@ -194,16 +194,22 @@ struct NS_GFX nsRect :
   // Note: this can turn an empty rectangle into a non-empty rectangle
   inline nsIntRect ScaleToOutsidePixels(float aXScale, float aYScale,
                                         nscoord aAppUnitsPerPixel) const;
   // Note: this can turn an empty rectangle into a non-empty rectangle
   inline nsIntRect ToOutsidePixels(nscoord aAppUnitsPerPixel) const;
   inline nsIntRect ScaleToInsidePixels(float aXScale, float aYScale,
                                        nscoord aAppUnitsPerPixel) const;
   inline nsIntRect ToInsidePixels(nscoord aAppUnitsPerPixel) const;
+
+  // This is here only to keep IPDL-generated code happy. DO NOT USE.
+  bool operator==(const nsRect& aRect) const
+  {
+    return IsEqualEdges(aRect);
+  }
 };
 
 struct NS_GFX nsIntRect :
   public mozilla::gfx::BaseRect<PRInt32, nsIntRect, nsIntPoint, nsIntSize, nsIntMargin> {
   typedef mozilla::gfx::BaseRect<PRInt32, nsIntRect, nsIntPoint, nsIntSize, nsIntMargin> Super;
 
   // Constructors
   nsIntRect() : Super()
--- a/gfx/thebes/Makefile.in
+++ b/gfx/thebes/Makefile.in
@@ -42,18 +42,16 @@ EXPORTS	= \
 	gfxQuad.h \
 	gfxQuaternion.h \
 	gfxRect.h \
 	gfxSkipChars.h \
 	gfxTeeSurface.h \
 	gfxTypes.h \
 	gfxUtils.h \
 	gfxUserFontSet.h \
-	nsCoreAnimationSupport.h \
-	nsIOSurface.h \
 	nsSurfaceTexture.h \
 	gfxSharedImageSurface.h \
 	gfxReusableSurfaceWrapper.h \
 	$(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),android)
 EXPORTS += \
 	gfxAndroidPlatform.h \
@@ -326,17 +324,16 @@ CPPSRCS	+= \
 	gfxCoreTextShaper.cpp \
 	$(NULL)
 #CPPSRCS +=	gfxPDFSurface.cpp
 CPPSRCS +=      nsUnicodeRange.cpp
 CPPSRCS +=      gfxQuartzNativeDrawing.cpp
 
 CMMSRCS = \
 	gfxMacPlatformFontList.mm \
-	nsCoreAnimationSupport.mm \
 	$(NULL)
 
 endif
 
 CSRCS += woff.c
 
 DEFINES += -DIMPL_THEBES -DWOFF_MOZILLA_CLIENT -DHB_DONT_DEFINE_STDINT
 DEFINES += -DMOZ_OTS_REPORT_ERRORS
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -113,16 +113,18 @@ const PRUint32 kMaxLenPrefLangList = 32;
 typedef gfxASurface::gfxImageFormat gfxImageFormat;
 
 inline const char*
 GetBackendName(mozilla::gfx::BackendType aBackend)
 {
   switch (aBackend) {
       case mozilla::gfx::BACKEND_DIRECT2D:
         return "direct2d";
+      case mozilla::gfx::BACKEND_COREGRAPHICS_ACCELERATED:
+        return "quartz accelerated";
       case mozilla::gfx::BACKEND_COREGRAPHICS:
         return "quartz";
       case mozilla::gfx::BACKEND_CAIRO:
         return "cairo";
       case mozilla::gfx::BACKEND_SKIA:
         return "skia";
       case mozilla::gfx::BACKEND_NONE:
         return "none";
--- a/gfx/thebes/gfxPlatformMac.cpp
+++ b/gfx/thebes/gfxPlatformMac.cpp
@@ -374,32 +374,48 @@ gfxPlatformMac::ReadAntiAliasingThreshol
     }
 
     return threshold;
 }
 
 already_AddRefed<gfxASurface>
 gfxPlatformMac::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
 {
-  if (aTarget->GetType() == BACKEND_COREGRAPHICS) {
+  if (aTarget->GetType() == BACKEND_COREGRAPHICS_ACCELERATED) {
+    RefPtr<SourceSurface> source = aTarget->Snapshot();
+    RefPtr<DataSourceSurface> sourceData = source->GetDataSurface();
+    unsigned char* data = sourceData->GetData();
+    nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(data, ThebesIntSize(sourceData->GetSize()), sourceData->Stride(),
+                                                         gfxImageSurface::ImageFormatARGB32);
+    // We could fix this by telling gfxImageSurface it owns data.
+    nsRefPtr<gfxImageSurface> cpy = new gfxImageSurface(ThebesIntSize(sourceData->GetSize()), gfxImageSurface::ImageFormatARGB32);
+    cpy->CopyFrom(surf);
+    return cpy.forget();
+  } else if (aTarget->GetType() == BACKEND_COREGRAPHICS) {
     CGContextRef cg = static_cast<CGContextRef>(aTarget->GetNativeSurface(NATIVE_SURFACE_CGCONTEXT));
 
     //XXX: it would be nice to have an implicit conversion from IntSize to gfxIntSize
     IntSize intSize = aTarget->GetSize();
     gfxIntSize size(intSize.width, intSize.height);
 
     nsRefPtr<gfxASurface> surf =
       new gfxQuartzSurface(cg, size);
 
     return surf.forget();
   }
 
   return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
 }
 
+bool
+gfxPlatformMac::UseAcceleratedCanvas()
+{
+  // Lion or later is required
+  return false && OSXVersion() >= 0x1070 && Preferences::GetBool("gfx.canvas.azure.accelerated", false);
+}
 
 qcms_profile *
 gfxPlatformMac::GetPlatformCMSOutputProfile()
 {
     qcms_profile *profile = nullptr;
     CMProfileRef cmProfile;
     CMProfileLocation *location;
     UInt32 locationSize;
--- a/gfx/thebes/gfxPlatformMac.h
+++ b/gfx/thebes/gfxPlatformMac.h
@@ -67,19 +67,21 @@ public:
                          nsTArray<nsString>& aListOfFonts);
     nsresult UpdateFontList();
 
     virtual void GetCommonFallbackFonts(const PRUint32 aCh,
                                         PRInt32 aRunScript,
                                         nsTArray<const char*>& aFontList);
 
     // Returns the OS X version as returned from Gestalt(gestaltSystemVersion, ...)
-    // Ex: Mac OS X 10.4.x ==> 0x104x 
+    // Ex: Mac OS X 10.4.x ==> 0x104x
     PRInt32 OSXVersion();
 
+    bool UseAcceleratedCanvas();
+
     // lower threshold on font anti-aliasing
     PRUint32 GetAntiAliasingThreshold() { return mFontAntiAliasingThreshold; }
 
     virtual already_AddRefed<gfxASurface>
     GetThebesSurfaceForDrawTarget(mozilla::gfx::DrawTarget *aTarget);
 private:
     virtual qcms_profile* GetPlatformCMSOutputProfile();
     
deleted file mode 100644
--- a/gfx/thebes/nsCoreAnimationSupport.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-// vim:set ts=2 sts=2 sw=2 et cin:
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsCoreAnimationSupport_h__
-#define nsCoreAnimationSupport_h__
-#ifdef XP_MACOSX
-
-#import <OpenGL/OpenGL.h>
-#import "ApplicationServices/ApplicationServices.h"
-#include "nscore.h"
-#include "gfxTypes.h"
-#include "nsAutoPtr.h"
-#include "nsIOSurface.h"
-
-// Get the system color space.
-CGColorSpaceRef THEBES_API CreateSystemColorSpace();
-
-// Manages a CARenderer
-struct _CGLPBufferObject;
-struct _CGLContextObject;
-
-enum AllowOfflineRendererEnum { ALLOW_OFFLINE_RENDERER, DISALLOW_OFFLINE_RENDERER };
-
-class THEBES_API nsCARenderer {
-  NS_INLINE_DECL_REFCOUNTING(nsCARenderer)
-public:
-  nsCARenderer() : mCARenderer(nullptr), mFBOTexture(0), mOpenGLContext(nullptr),
-                   mCGImage(nullptr), mCGData(nullptr), mIOSurface(nullptr), mFBO(0),
-                   mIOTexture(0),
-                   mUnsupportedWidth(UINT32_MAX), mUnsupportedHeight(UINT32_MAX),
-                   mAllowOfflineRenderer(DISALLOW_OFFLINE_RENDERER) {}
-  ~nsCARenderer();
-  nsresult SetupRenderer(void* aCALayer, int aWidth, int aHeight,
-                         AllowOfflineRendererEnum aAllowOfflineRenderer);
-  nsresult Render(int aWidth, int aHeight, CGImageRef *aOutCAImage);
-  bool isInit() { return mCARenderer != nullptr; }
-  /*
-   * Render the CALayer to an IOSurface. If no IOSurface
-   * is attached then an internal pixel buffer will be
-   * used.
-   */
-  void AttachIOSurface(nsRefPtr<nsIOSurface> aSurface);
-  IOSurfaceID GetIOSurfaceID();
-  static nsresult DrawSurfaceToCGContext(CGContextRef aContext,
-                                         nsIOSurface *surf,
-                                         CGColorSpaceRef aColorSpace,
-                                         int aX, int aY,
-                                         size_t aWidth, size_t aHeight);
-
-  // Remove & Add the layer without destroying
-  // the renderer for fast back buffer swapping.
-  void DettachCALayer();
-  void AttachCALayer(void *aCALayer);
-#ifdef DEBUG
-  static void SaveToDisk(nsIOSurface *surf);
-#endif
-private:
-  void SetBounds(int aWidth, int aHeight);
-  void SetViewport(int aWidth, int aHeight);
-  void Destroy();
-
-  void *mCARenderer;
-  GLuint                    mFBOTexture;
-  _CGLContextObject        *mOpenGLContext;
-  CGImageRef                mCGImage;
-  void                     *mCGData;
-  nsRefPtr<nsIOSurface>     mIOSurface;
-  uint32_t                  mFBO;
-  uint32_t                  mIOTexture;
-  uint32_t                  mUnsupportedWidth;
-  uint32_t                  mUnsupportedHeight;
-  AllowOfflineRendererEnum  mAllowOfflineRenderer;
-};
-
-#endif // XP_MACOSX
-#endif // nsCoreAnimationSupport_h__
-
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -716,17 +716,17 @@ void
 NotifyAlarmFired()
 {
   if (sAlarmObserver) {
     sAlarmObserver->Notify(void_t());
   }
 }
 
 bool
-SetAlarm(long aSeconds, long aNanoseconds)
+SetAlarm(PRInt32 aSeconds, PRInt32 aNanoseconds)
 {
   // It's pointless to program an alarm nothing is going to observe ...
   MOZ_ASSERT(sAlarmObserver);
   RETURN_PROXY_IF_SANDBOXED(SetAlarm(aSeconds, aNanoseconds));
 }
 
 } // namespace hal
 } // namespace mozilla
--- a/hal/Hal.h
+++ b/hal/Hal.h
@@ -395,17 +395,17 @@ void NotifyAlarmFired();
  * real-time clock is changed; that is, this alarm respects changes to
  * the real-time clock.  Return true iff the alarm was programmed.
  *
  * The alarm can be reprogrammed at any time.
  *
  * This API is currently only allowed to be used from non-sandboxed
  * contexts.
  */
-bool SetAlarm(long aSeconds, long aNanoseconds);
+bool SetAlarm(PRInt32 aSeconds, PRInt32 aNanoseconds);
 
 } // namespace MOZ_HAL_NAMESPACE
 } // namespace mozilla
 
 #ifdef MOZ_DEFINED_HAL_NAMESPACE
 # undef MOZ_DEFINED_HAL_NAMESPACE
 # undef MOZ_HAL_NAMESPACE
 #endif
--- a/hal/fallback/FallbackAlarm.cpp
+++ b/hal/fallback/FallbackAlarm.cpp
@@ -14,15 +14,15 @@ EnableAlarm()
 }
 
 void
 DisableAlarm()
 {
 }
 
 bool
-SetAlarm(long aSeconds, long aNanoseconds)
+SetAlarm(PRInt32 aSeconds, PRInt32 aNanoseconds)
 {
   return false;
 }
 
 } // hal_impl
 } // namespace mozilla
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -773,17 +773,17 @@ DisableAlarm()
 
   // The cancel will interrupt the thread and destroy it, freeing the
   // data pointed at by sAlarmData.
   DebugOnly<int> err = pthread_kill(sAlarmFireWatcherThread, SIGUSR1);
   MOZ_ASSERT(!err);
 }
 
 bool
-SetAlarm(long aSeconds, long aNanoseconds)
+SetAlarm(PRInt32 aSeconds, PRInt32 aNanoseconds)
 {
   if (!sAlarmData) {
     HAL_LOG(("We should have enabled the alarm."));
     return false;
   }
 
   struct timespec ts;
   ts.tv_sec = aSeconds;
--- a/hal/sandbox/SandboxHal.cpp
+++ b/hal/sandbox/SandboxHal.cpp
@@ -269,17 +269,17 @@ EnableAlarm()
 
 void
 DisableAlarm()
 {
   NS_RUNTIMEABORT("Alarms can't be programmed from sandboxed contexts.  Yet.");
 }
 
 bool
-SetAlarm(long aSeconds, long aNanoseconds)
+SetAlarm(PRInt32 aSeconds, PRInt32 aNanoseconds)
 {
   NS_RUNTIMEABORT("Alarms can't be programmed from sandboxed contexts.  Yet.");
   return false;
 }
 
 class HalParent : public PHalParent
                 , public BatteryObserver
                 , public NetworkObserver
--- a/ipc/glue/IPCMessageUtils.h
+++ b/ipc/glue/IPCMessageUtils.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __IPC_GLUE_IPCMESSAGEUTILS_H__
 #define __IPC_GLUE_IPCMESSAGEUTILS_H__
 
 #include "chrome/common/ipc_message_utils.h"
 
+#include "mozilla/TimeStamp.h"
 #include "mozilla/Util.h"
 #include "mozilla/gfx/2D.h"
 
 #include "prtypes.h"
 #include "nsID.h"
 #include "nsMemory.h"
 #include "nsStringGlue.h"
 #include "nsTArray.h"
@@ -434,21 +435,38 @@ struct ParamTraits<gfxPoint>
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.x);
     WriteParam(aMsg, aParam.y);
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
-    if (ReadParam(aMsg, aIter, &aResult->x) &&
-        ReadParam(aMsg, aIter, &aResult->y))
-      return true;
+    return (ReadParam(aMsg, aIter, &aResult->x) &&
+            ReadParam(aMsg, aIter, &aResult->y));
+ }
+};
+
+template<>
+struct ParamTraits<gfxPoint3D>
+{
+  typedef gfxPoint3D paramType;
 
-    return false;
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.x);
+    WriteParam(aMsg, aParam.y);
+    WriteParam(aMsg, aParam.z);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    return (ReadParam(aMsg, aIter, &aResult->x) &&
+            ReadParam(aMsg, aIter, &aResult->y) &&
+            ReadParam(aMsg, aIter, &aResult->z));
   }
 };
 
 template<>
 struct ParamTraits<gfxSize>
 {
   typedef gfxSize paramType;
 
@@ -573,20 +591,38 @@ struct ParamTraits<mozilla::null_t>
   Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
     *aResult = paramType();
     return true;
   }
 };
 
 template<>
+struct ParamTraits<nsPoint>
+{
+  typedef nsPoint paramType;
+
+  static void Write(Message* msg, const paramType& param)
+  {
+    WriteParam(msg, param.x);
+    WriteParam(msg, param.y);
+  }
+
+  static bool Read(const Message* msg, void** iter, paramType* result)
+  {
+    return (ReadParam(msg, iter, &result->x) &&
+            ReadParam(msg, iter, &result->y));
+  }
+};
+
+template<>
 struct ParamTraits<nsIntPoint>
 {
   typedef nsIntPoint paramType;
-  
+
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.x);
     WriteParam(msg, param.y);
   }
 
   static bool Read(const Message* msg, void** iter, paramType* result)
   {
@@ -594,17 +630,17 @@ struct ParamTraits<nsIntPoint>
             ReadParam(msg, iter, &result->y));
   }
 };
 
 template<>
 struct ParamTraits<nsIntRect>
 {
   typedef nsIntRect paramType;
-  
+
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.x);
     WriteParam(msg, param.y);
     WriteParam(msg, param.width);
     WriteParam(msg, param.height);
   }
 
@@ -643,39 +679,39 @@ struct ParamTraits<nsIntRegion>
     return false;
   }
 };
 
 template<>
 struct ParamTraits<nsIntSize>
 {
   typedef nsIntSize paramType;
-  
+
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.width);
-    WriteParam(msg, param.height); 
+    WriteParam(msg, param.height);
   }
 
   static bool Read(const Message* msg, void** iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->width) &&
             ReadParam(msg, iter, &result->height));
   }
 };
 
 template<>
 struct ParamTraits<mozilla::gfx::Size>
 {
   typedef mozilla::gfx::Size paramType;
-  
+
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.width);
-    WriteParam(msg, param.height); 
+    WriteParam(msg, param.height);
   }
 
   static bool Read(const Message* msg, void** iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->width) &&
             ReadParam(msg, iter, &result->height));
   }
 };
@@ -701,17 +737,17 @@ struct ParamTraits<mozilla::gfx::Rect>
             ReadParam(msg, iter, &result->height));
   }
 };
 
 template<>
 struct ParamTraits<nsRect>
 {
   typedef nsRect paramType;
-  
+
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.x);
     WriteParam(msg, param.y);
     WriteParam(msg, param.width);
     WriteParam(msg, param.height);
   }
 
@@ -761,11 +797,39 @@ struct ParamTraits<nsID>
                               aParam.m1,
                               aParam.m2));
     for (unsigned int i = 0; i < mozilla::ArrayLength(aParam.m3); i++)
       aLog->append(StringPrintf(L"%2.2X", aParam.m3[i]));
     aLog->append(L"}");
   }
 };
 
+template<>
+struct ParamTraits<mozilla::TimeDuration>
+{
+  typedef mozilla::TimeDuration paramType;
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mValue);
+  }
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    return ReadParam(aMsg, aIter, &aResult->mValue);
+  };
+};
+
+template<>
+struct ParamTraits<mozilla::TimeStamp>
+{
+  typedef mozilla::TimeStamp paramType;
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mValue);
+  }
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    return ReadParam(aMsg, aIter, &aResult->mValue);
+  };
+};
+
 } /* namespace IPC */
 
 #endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -15,17 +15,17 @@
 #include "js/Utility.h"
 #include "vm/GlobalObject.h"
 #include "vm/Stack.h"
 
 #include "jsobjinlines.h"
 
 using namespace js;
 
-
+
 /*** OrderedHashTable ****************************************************************************/
 
 /*
  * Define two collection templates, js::OrderedHashMap and js::OrderedHashSet.
  * They are like js::HashMap and js::HashSet except that:
  *
  *   - Iterating over an Ordered hash table visits the entries in the order in
  *     which they were inserted. This means that unlike a HashMap, the behavior
@@ -789,26 +789,26 @@ GlobalObject::initMapIteratorProto(JSCon
 }
 
 MapIteratorObject *
 MapIteratorObject::create(JSContext *cx, HandleObject mapobj, ValueMap *data)
 {
     Rooted<GlobalObject *> global(cx, &mapobj->global());
     Rooted<JSObject*> proto(cx, global->getOrCreateMapIteratorPrototype(cx));
     if (!proto)
-        return false;
+        return NULL;
 
     ValueMap::Range *range = cx->new_<ValueMap::Range>(data->all());
     if (!range)
-        return false;
+        return NULL;
 
     JSObject *iterobj = NewObjectWithGivenProto(cx, &MapIteratorClass, proto, global);
     if (!iterobj) {
         cx->delete_(range);
-        return false;
+        return NULL;
     }
     iterobj->setSlot(TargetSlot, ObjectValue(*mapobj));
     iterobj->setSlot(RangeSlot, PrivateValue(range));
     return static_cast<MapIteratorObject *>(iterobj);
 }
 
 void
 MapIteratorObject::finalize(FreeOp *fop, JSObject *obj)
@@ -1234,26 +1234,26 @@ GlobalObject::initSetIteratorProto(JSCon
 }
 
 SetIteratorObject *
 SetIteratorObject::create(JSContext *cx, HandleObject setobj, ValueSet *data)
 {
     Rooted<GlobalObject *> global(cx, &setobj->global());
     Rooted<JSObject*> proto(cx, global->getOrCreateSetIteratorPrototype(cx));
     if (!proto)
-        return false;
+        return NULL;
 
     ValueSet::Range *range = cx->new_<ValueSet::Range>(data->all());
     if (!range)
-        return false;
+        return NULL;
 
     JSObject *iterobj = NewObjectWithGivenProto(cx, &SetIteratorClass, proto, global);
     if (!iterobj) {
         cx->delete_(range);
-        return false;
+        return NULL;
     }
     iterobj->setSlot(TargetSlot, ObjectValue(*setobj));
     iterobj->setSlot(RangeSlot, PrivateValue(range));
     return static_cast<SetIteratorObject *>(iterobj);
 }
 
 void
 SetIteratorObject::finalize(FreeOp *fop, JSObject *obj)
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1623,16 +1623,19 @@ Parser::functionDef(HandlePropertyName f
 
 #if JS_HAS_EXPR_CLOSURES
     if (bodyType == StatementListBody) {
 #endif
         MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_BODY);
         funbox->bufEnd = tokenStream.offsetOfToken(tokenStream.currentToken()) + 1;
 #if JS_HAS_EXPR_CLOSURES
     } else {
+        // We shouldn't call endOffset if the tokenizer got an error.
+        if (tokenStream.hadError())
+            return NULL;
         funbox->bufEnd = tokenStream.endOffset(tokenStream.currentToken());
         if (kind == Statement && !MatchOrInsertSemicolon(context, &tokenStream))
             return NULL;
     }
 #endif
     pn->pn_pos.end = tokenStream.currentToken().pos.end;
 
     /*
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -2146,29 +2146,36 @@ TokenStream::getTokenInternal()
      * still be equal to begin.lineno) so we revert end.index to be equal to
      * begin.index + 1 (as if it's a 1-char token) to avoid having inconsistent
      * begin/end positions.  end.index isn't used in error messages anyway.
      */
     flags |= TSF_DIRTYLINE;
     tp->pos.end.index = tp->pos.begin.index + 1;
     tp->type = TOK_ERROR;
     JS_ASSERT(IsTokenSane(tp));
+    onError();
+    return TOK_ERROR;
+}
+
+void
+TokenStream::onError()
+{
+    flags |= TSF_HAD_ERROR;
 #ifdef DEBUG
     /*
      * Poisoning userbuf on error establishes an invariant: once an erroneous
      * token has been seen, userbuf will not be consulted again.  This is true
      * because the parser will either (a) deal with the TOK_ERROR token by
      * aborting parsing immediately; or (b) if the TOK_ERROR token doesn't
      * match what it expected, it will unget the token, and the next getToken()
      * call will immediately return the just-gotten TOK_ERROR token again
      * without consulting userbuf, thanks to the lookahead buffer.
      */
     userbuf.poison();
 #endif
-    return TOK_ERROR;
 }
 
 JS_FRIEND_API(int)
 js_fgets(char *buf, int size, FILE *file)
 {
     int n, i, c;
     bool crflag;
 
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -384,16 +384,17 @@ enum TokenStreamFlags
     TSF_UNEXPECTED_EOF = 0x10,  /* unexpected end of input, i.e. TOK_EOF not at top-level. */
     TSF_KEYWORD_IS_NAME = 0x20, /* Ignore keywords and return TOK_NAME instead to the parser. */
     TSF_DIRTYLINE = 0x40,       /* non-whitespace since start of line */
     TSF_OWNFILENAME = 0x80,     /* ts->filename is malloc'd */
     TSF_XMLTAGMODE = 0x100,     /* scanning within an XML tag in E4X */
     TSF_XMLTEXTMODE = 0x200,    /* scanning XMLText terminal from E4X */
     TSF_XMLONLYMODE = 0x400,    /* don't scan {expr} within text/tag */
     TSF_OCTAL_CHAR = 0x800,     /* observed a octal character escape */
+    TSF_HAD_ERROR = 0x1000,     /* returned TOK_ERROR from getToken */
 
     /*
      * To handle the hard case of contiguous HTML comments, we want to clear the
      * TSF_DIRTYINPUT flag at the end of each such comment.  But we'd rather not
      * scan for --> within every //-style comment unless we have to.  So we set
      * TSF_IN_HTML_COMMENT when a <!-- is scanned as an HTML begin-comment, and
      * clear it (and TSF_DIRTYINPUT) when we scan --> either on a clean line, or
      * only if (ts->flags & TSF_IN_HTML_COMMENT), in a //-style comment.
@@ -404,17 +405,17 @@ enum TokenStreamFlags
      *      <!-- comment hiding hack #1
      *      code goes here
      *      // --> oops, markup for script-unaware browsers goes here!
      *    </script>
      *
      * It does not cope with malformed comment hiding hacks where --> is hidden
      * by C-style comments, or on a dirty line.  Such cases are already broken.
      */
-    TSF_IN_HTML_COMMENT = 0x1000
+    TSF_IN_HTML_COMMENT = 0x2000
 };
 
 struct Parser;
 
 struct CompileError {
     JSContext *cx;
     JSErrorReport report;
     char *message;
@@ -503,16 +504,17 @@ class TokenStream
     /* Note that the version and hasMoarXML can get out of sync via setMoarXML. */
     JSVersion versionNumber() const { return VersionNumber(version); }
     JSVersion versionWithFlags() const { return version; }
     // TokenStream::allowsXML() can be true even if Parser::allowsXML() is
     // false. Read the comment at Parser::allowsXML() to find out why.
     bool allowsXML() const { return allowXML && strictModeState() != StrictMode::STRICT; }
     bool hasMoarXML() const { return moarXML || VersionShouldParseXML(versionNumber()); }
     void setMoarXML(bool enabled) { moarXML = enabled; }
+    bool hadError() const { return !!(flags & TSF_HAD_ERROR); }
 
     bool isCurrentTokenEquality() const {
         return TokenKindIsEquality(currentToken().type);
     }
 
     bool isCurrentTokenRelational() const {
         return TokenKindIsRelational(currentToken().type);
     }
@@ -548,16 +550,17 @@ class TokenStream
     // General-purpose error reporters.  You should avoid calling these
     // directly, and instead use the more succinct alternatives (e.g.
     // reportError()) in TokenStream, Parser, and BytecodeEmitter.
     bool reportCompileErrorNumberVA(ParseNode *pn, unsigned flags, unsigned errorNumber,
                                     va_list args);
     bool reportStrictModeErrorNumberVA(ParseNode *pn, unsigned errorNumber, va_list args);
 
   private:
+    void onError();
     static JSAtom *atomize(JSContext *cx, CharBuffer &cb);
     bool putIdentInTokenbuf(const jschar *identStart);
 
     /*
      * Enables flags in the associated tokenstream for the object lifetime.
      * Useful for lexically-scoped flag toggles.
      */
     class Flagger {
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/function-tosource-exprbody-bug777834.js
@@ -0,0 +1,5 @@
+load(libdir + "asserts.js");
+
+assertThrowsInstanceOf(function () {
+    eval("function f()((l()))++2s");
+}, SyntaxError);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testMissingProperties.js
@@ -0,0 +1,49 @@
+function isnan(n) { return n !== n }
+
+function f(x) {
+    var sum = 0;
+    for (var i = 0; i < 100; ++i)
+        sum += x.x;
+    return sum;
+}
+var o = {};
+assertEq(isnan(f(o)), true);
+o.x = 1;
+assertEq(f(o), 100);
+var o = {a:1, b:2};
+assertEq(isnan(f(o)), true);
+o.x = 2;
+assertEq(f(o), 200);
+
+function g(x) {
+    var sum = 0;
+    for (var i = 0; i < 100; ++i)
+        sum += x.x;
+    return sum;
+}
+var o = {c:1, x:1};
+assertEq(g(o), 100);
+var o = {};
+assertEq(isnan(g(o)), true);
+
+function h(x) {
+    var sum = 0;
+    for (var i = 0; i < 100; ++i)
+        sum += x.x;
+    return sum;
+}
+
+var proto1 = {};
+var proto2 = Object.create(proto1);
+var o = Object.create(proto2);
+assertEq(isnan(f(o)), true);
+assertEq(isnan(g(o)), true);
+assertEq(isnan(h(o)), true);
+proto2.x = 2;
+assertEq(f(o), 200);
+assertEq(g(o), 200);
+assertEq(h(o), 200);
+var o = {}
+assertEq(isnan(f(o)), true);
+assertEq(isnan(g(o)), true);
+assertEq(isnan(h(o)), true);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testOverRecursed1.js
@@ -0,0 +1,6 @@
+// |jit-test| error:InternalError
+
+var a = [];
+var f = a.forEach.bind(a);
+a.push(f);
+f(f);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testOverRecursed2.js
@@ -0,0 +1,7 @@
+// |jit-test| error:InternalError
+
+var a = [];
+var sort = a.sort.bind(a);
+a.push(sort);
+a.push(sort);
+sort(sort);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testOverRecursed3.js
@@ -0,0 +1,6 @@
+// |jit-test| error:InternalError
+
+x = [];
+x.push(x);
+x.toString = x.sort;
+x.toString();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testOverRecursed4.js
@@ -0,0 +1,9 @@
+function tryItOut(code) {
+    f = eval("(function(){" + code + "})")
+    try {
+        f()
+    } catch (e) {}
+}
+tryItOut("x=7");
+tryItOut("\"use strict\";for(d in[x=arguments]){}");
+tryItOut("for(v in((Object.seal)(x)));x.length=Function")
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testOverRecursed5.js
@@ -0,0 +1,13 @@
+JSON.__proto__[1] = Uint8ClampedArray().buffer
+f = (function() {
+    function g(c) {
+        Object.freeze(c).__proto__ = c
+    }
+    for each(b in []) {
+        try {
+            g(b)
+        } catch (e) {}
+    }
+})
+f()
+f()
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testOverRecursed6.js
@@ -0,0 +1,3 @@
+// |jit-test| error:InternalError
+
+"" + {toString: Date.prototype.toJSON};
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -375,16 +375,18 @@ assertSameCompartment(JSContext *cx, con
 }
 
 #undef START_ASSERT_SAME_COMPARTMENT
 
 STATIC_PRECONDITION_ASSUME(ubound(args.argv_) >= argc)
 JS_ALWAYS_INLINE bool
 CallJSNative(JSContext *cx, Native native, const CallArgs &args)
 {
+    JS_CHECK_RECURSION(cx, return false);
+
 #ifdef DEBUG
     bool alreadyThrowing = cx->isExceptionPending();
 #endif
     assertSameCompartment(cx, args);
     bool ok = native(cx, args.length(), args.base());
     if (ok) {
         assertSameCompartment(cx, args.rval());
         JS_ASSERT_IF(!alreadyThrowing, !cx->isExceptionPending());
@@ -443,27 +445,31 @@ CallJSNativeConstructor(JSContext *cx, N
                  !args.rval().isPrimitive() && callee != &args.rval().toObject());
 
     return true;
 }
 
 JS_ALWAYS_INLINE bool
 CallJSPropertyOp(JSContext *cx, PropertyOp op, HandleObject receiver, HandleId id, MutableHandleValue vp)
 {
+    JS_CHECK_RECURSION(cx, return false);
+
     assertSameCompartment(cx, receiver, id, vp);
     JSBool ok = op(cx, receiver, id, vp);
     if (ok)
         assertSameCompartment(cx, vp);
     return ok;
 }
 
 JS_ALWAYS_INLINE bool
 CallJSPropertyOpSetter(JSContext *cx, StrictPropertyOp op, HandleObject obj, HandleId id,
                        JSBool strict, MutableHandleValue vp)
 {
+    JS_CHECK_RECURSION(cx, return false);
+
     assertSameCompartment(cx, obj, id, vp);
     return op(cx, obj, id, strict, vp);
 }
 
 inline bool
 CallSetter(JSContext *cx, HandleObject obj, HandleId id, StrictPropertyOp op, unsigned attrs,
            unsigned shortid, JSBool strict, MutableHandleValue vp)
 {
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -5040,16 +5040,18 @@ xml_deleteSpecial(JSContext *cx, HandleO
 }
 
 static JSString *
 xml_toString_helper(JSContext *cx, JSXML *xml);
 
 JSBool
 xml_convert(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue rval)
 {
+    JS_CHECK_RECURSION(cx, return false);
+
     JS_ASSERT(hint == JSTYPE_NUMBER || hint == JSTYPE_STRING || hint == JSTYPE_VOID);
     JS_ASSERT(obj->isXML());
 
     JS::Anchor<JSObject *> anch(obj);
     JSString *str = xml_toString_helper(cx, reinterpret_cast<JSXML *>(obj->getPrivate()));
     if (!str)
         return false;
     rval.setString(str);
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -645,18 +645,36 @@ struct GetPropHelper {
             return ic.disable(f, "non-native");
 
         RecompilationMonitor monitor(cx);
         if (!aobj->lookupProperty(cx, name, &holder, &prop))
             return ic.error(cx);
         if (monitor.recompiled())
             return Lookup_Uncacheable;
 
-        if (!prop)
-            return ic.disable(f, "lookup failed");
+        if (!prop) {
+            /*
+             * Just because we didn't find the property on the object doesn't
+             * mean it won't magically appear through various engine hacks:
+             */
+            if (obj->getClass()->getProperty && obj->getClass()->getProperty != JS_PropertyStub)
+                return Lookup_Uncacheable;
+
+#if JS_HAS_NO_SUCH_METHOD
+            /*
+             * The __noSuchMethod__ hook may substitute in a valid method.
+             * Since, if o.m is missing, o.m() will probably be an error,
+             * just mark all missing callprops as uncacheable.
+             */
+            if (*f.pc() == JSOP_CALLPROP)
+                return Lookup_Uncacheable;
+#endif
+
+            return Lookup_NoProperty;
+        }
         if (!IsCacheableProtoChain(obj, holder))
             return ic.disable(f, "non-native holder");
         shape = prop;
         return Lookup_Cacheable;
     }
 
     LookupStatus testForGet() {
         if (!shape->hasDefaultGetter()) {
@@ -1210,49 +1228,75 @@ class GetPropCompiler : public PICStubCo
 
         RegisterID holderReg = pic.objReg;
         if (obj != holder) {
             if (!GeneratePrototypeGuards(cx, shapeMismatches, masm, obj, holder,
                                          pic.objReg, pic.shapeReg)) {
                 return error();
             }
 
-            // Bake in the holder identity. Careful not to clobber |objReg|, since we can't remat it.
-            holderReg = pic.shapeReg;
-            masm.move(ImmPtr(holder), holderReg);
-            pic.shapeRegHasBaseShape = false;
-
-            // Guard on the holder's shape.
-            Jump j = masm.guardShape(holderReg, holder);
-            if (!shapeMismatches.append(j))
-                return error();
+            if (holder) {
+                // Bake in the holder identity. Careful not to clobber |objReg|, since we can't remat it.
+                holderReg = pic.shapeReg;
+                masm.move(ImmPtr(holder), holderReg);
+                pic.shapeRegHasBaseShape = false;
+
+                // Guard on the holder's shape.
+                Jump j = masm.guardShape(holderReg, holder);
+                if (!shapeMismatches.append(j))
+                    return error();
+            } else {
+                // Like when we add a property, we need to guard on the shape of
+                // everything on the prototype chain.
+                JSObject *proto = obj->getProto();
+                RegisterID lastReg = pic.objReg;
+                while (proto) {
+                    masm.loadPtr(Address(lastReg, JSObject::offsetOfType()), pic.shapeReg);
+                    masm.loadPtr(Address(pic.shapeReg, offsetof(types::TypeObject, proto)), pic.shapeReg);
+                    Jump protoGuard = masm.guardShape(pic.shapeReg, proto);
+                    if (!shapeMismatches.append(protoGuard))
+                        return error();
+
+                    proto = proto->getProto();
+                    lastReg = pic.shapeReg;
+                }
+            }
 
             pic.secondShapeGuard = masm.distanceOf(masm.label()) - masm.distanceOf(start);
         } else {
             pic.secondShapeGuard = 0;
         }
 
-        if (!shape->hasDefaultGetter()) {
+        if (shape && !shape->hasDefaultGetter()) {
             if (shape->hasGetterValue()) {
                 generateNativeGetterStub(masm, shape, start, shapeMismatches);
             } else {
                 jsid userid;
                 if (!shape->getUserId(cx, &userid))
                     return error();
                 generateGetterStub(masm, shape, userid, start, shapeMismatches);
             }
             if (setStubShapeOffset)
                 pic.getPropLabels().setStubShapeJump(masm, start, stubShapeJumpLabel);
             return Lookup_Cacheable;
         }
 
-        /* Load the value out of the object. */
-        masm.loadObjProp(holder, holderReg, shape, pic.shapeReg, pic.objReg);
+        /*
+         * A non-null 'shape' tells us where to find the property value in the
+         * holder object. A null shape means that the above checks guard the
+         * absence of the property, so the get-prop returns 'undefined'. A
+         * missing property guarantees a type barrier below so we don't have to
+         * check type information.
+         */
+        if (shape)
+            masm.loadObjProp(holder, holderReg, shape, pic.shapeReg, pic.objReg);
+        else
+            masm.loadValueAsComponents(UndefinedValue(), pic.shapeReg, pic.objReg);
+
         Jump done = masm.jump();
-
         pic.updatePCCounters(f, masm);
 
         PICLinker buffer(masm, pic);
         if (!buffer.init(cx))
             return error();
 
         if (!buffer.verifyRange(pic.lastCodeBlock(f.chunk())) ||
             !buffer.verifyRange(f.chunk())) {
@@ -1314,22 +1358,23 @@ class GetPropCompiler : public PICStubCo
     }
 
     LookupStatus update()
     {
         JS_ASSERT(pic.hit);
 
         GetPropHelper<GetPropCompiler> getprop(cx, obj, name, *this, f);
         LookupStatus status = getprop.lookupAndTest();
-        if (status != Lookup_Cacheable)
+        if (status != Lookup_Cacheable && status != Lookup_NoProperty)
             return status;
         if (hadGC())
             return Lookup_Uncacheable;
 
-        if (obj == getprop.holder &&
+        if (status == Lookup_Cacheable &&
+            obj == getprop.holder &&
             getprop.shape->hasDefaultGetter() &&
             !pic.inlinePathPatched) {
             return patchInline(getprop.holder, getprop.shape);
         }
 
         return generateStub(getprop.holder, getprop.shape);
     }
 };
@@ -2452,17 +2497,17 @@ ic::GetElement(VMFrame &f, ic::GetElemen
 
     MutableHandleValue res = MutableHandleValue::fromMarkedLocation(&f.regs.sp[-2]);
 
     if (!monitor.recompiled() && ic->shouldUpdate(f)) {
 #ifdef DEBUG
         f.regs.sp[-2] = MagicValue(JS_GENERIC_MAGIC);
 #endif
         LookupStatus status = ic->update(f, obj, idval_, id, res);
-        if (status != Lookup_Uncacheable) {
+        if (status != Lookup_Uncacheable && status != Lookup_NoProperty) {
             if (status == Lookup_Error)
                 THROW();
 
             // If the result can be cached, the value was already retrieved.
             JS_ASSERT(!f.regs.sp[-2].isMagic());
             return;
         }
     }
--- a/js/src/methodjit/PolyIC.h
+++ b/js/src/methodjit/PolyIC.h
@@ -26,17 +26,18 @@ namespace ic {
 
 /* Maximum number of stubs for a given callsite. */
 static const uint32_t MAX_PIC_STUBS = 16;
 static const uint32_t MAX_GETELEM_IC_STUBS = 17;
 
 enum LookupStatus {
     Lookup_Error = 0,
     Lookup_Uncacheable,
-    Lookup_Cacheable
+    Lookup_Cacheable,
+    Lookup_NoProperty
 };
 
 struct BaseIC : public MacroAssemblerTypedefs {
 
     // Address of inline fast-path.
     CodeLocationLabel fastPathStart;
 
     // Address to rejoin to the fast-path.
--- a/js/src/tests/ecma_5/extensions/strict-e4x-ban.js
+++ b/js/src/tests/ecma_5/extensions/strict-e4x-ban.js
@@ -1,9 +1,9 @@
-// |reftest| skip-if(!xulRuntime.shell)
+// |reftest| pref(javascript.options.xml.content,true) skip-if(!xulRuntime.shell)
 /*
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/licenses/publicdomain/
  */
 
 assertEq(testLenientAndStrict("var o = {m:function(){}}; o.function::m()",
                               parsesSuccessfully,
                               parseRaisesException(SyntaxError)),
--- a/js/src/tests/js1_8_5/extensions/clone-errors.js
+++ b/js/src/tests/js1_8_5/extensions/clone-errors.js
@@ -1,9 +1,9 @@
-// |reftest| skip-if(!xulRuntime.shell)
+// |reftest| pref(javascript.options.xml.content,true) skip-if(!xulRuntime.shell)
 // -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 // Any copyright is dedicated to the Public Domain.
 // http://creativecommons.org/licenses/publicdomain/
 
 function check(v) {
     try {
         serialize(v);
     } catch (exc) {
--- a/js/src/tests/js1_8_5/extensions/clone-object.js
+++ b/js/src/tests/js1_8_5/extensions/clone-object.js
@@ -1,9 +1,9 @@
-// |reftest| skip-if(!xulRuntime.shell)
+// |reftest| pref(javascript.options.xml.content,true) skip-if(!xulRuntime.shell)
 // -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 // Any copyright is dedicated to the Public Domain.
 // http://creativecommons.org/licenses/publicdomain/
 
 // Assert that cloning b does the right thing as far as we can tell.
 // Caveat: getters in b must produce the same value each time they're
 // called. We may call them several times.
 //
--- a/js/src/tests/js1_8_5/extensions/reflect-parse.js
+++ b/js/src/tests/js1_8_5/extensions/reflect-parse.js
@@ -1,9 +1,9 @@
-// |reftest| skip-if(!xulRuntime.shell)
+// |reftest| pref(javascript.options.xml.content,true) skip-if(!xulRuntime.shell)
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /*
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/licenses/publicdomain/
  */
 
 (function runtest(main) {
     try {
--- a/js/src/tests/js1_8_5/regress/regress-595230-1.js
+++ b/js/src/tests/js1_8_5/regress/regress-595230-1.js
@@ -1,9 +1,9 @@
-// |reftest| fails-if(!xulRuntime.shell)
+// |reftest| pref(javascript.options.xml.content,true) fails-if(!xulRuntime.shell)
 // Any copyright is dedicated to the Public Domain.
 // http://creativecommons.org/licenses/publicdomain/
 // Contributors: Gary Kwong <gary@rumblingedge.com>, Brendan Eich <brendan@mozilla.com>
 
 var box = evalcx('lazy');
 
 var src =
     'try {\n' +
--- a/js/src/tests/js1_8_5/regress/regress-600137.js
+++ b/js/src/tests/js1_8_5/regress/regress-600137.js
@@ -1,8 +1,9 @@
+// |reftest| pref(javascript.options.xml.content,true)
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /*
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/licenses/publicdomain/
  */
 
 if (typeof evalcx == 'function') {
     var src = 'try {\n' +
--- a/js/src/tests/js1_8_5/regress/regress-618576.js
+++ b/js/src/tests/js1_8_5/regress/regress-618576.js
@@ -1,9 +1,9 @@
-// |reftest| skip-if(!xulRuntime.shell) -- uses evalcx
+// |reftest| pref(javascript.options.xml.content,true) skip-if(!xulRuntime.shell) -- uses evalcx
 /*
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/licenses/publicdomain/
  * Contributors: Gary Kwong and Jason Orendorff
  */
 
 var x = <x/>;
 x.function::__proto__ = evalcx('');
--- a/js/src/tests/lib/manifest.py
+++ b/js/src/tests/lib/manifest.py
@@ -107,16 +107,17 @@ class NullXULInfoTester:
 
 def _parse_one(parts, xul_tester):
     script = None
     enable = True
     expect = True
     random = False
     slow = False
     debugMode = False
+    allowXml = False
 
     pos = 0
     while pos < len(parts):
         if parts[pos] == 'fails':
             expect = False
             pos += 1
         elif parts[pos] == 'skip':
             expect = enable = False
@@ -169,21 +170,24 @@ def _parse_one(parts, xul_tester):
         elif parts[pos] == 'slow':
             slow = True
             pos += 1
         elif parts[pos] == 'silentfail':
             # silentfails use tons of memory, and Darwin doesn't support ulimit.
             if xul_tester.test("xulRuntime.OS == 'Darwin'"):
                 expect = enable = False
             pos += 1
+        elif parts[pos] == 'pref(javascript.options.xml.content,true)':
+            allowXml = True
+            pos += 1
         else:
             print 'warning: invalid manifest line element "%s"'%parts[pos]
             pos += 1
 
-    return script, (enable, expect, random, slow, debugMode)
+    return script, (enable, expect, random, slow, debugMode, allowXml)
 
 def _map_prefixes_left(test_list):
     """
     Splits tests into a dictionary keyed on the first component of the test
     path, aggregating tests with a common base path into a list.
     """
     byprefix = {}
     for t in test_list:
@@ -277,16 +281,17 @@ def _parse_test_header(fullpath, testcas
     testcase.comment = matches.group(4)
 
     _, properties = _parse_one(testcase.terms.split(), xul_tester)
     testcase.enable = properties[0]
     testcase.expect = properties[1]
     testcase.random = properties[2]
     testcase.slow = properties[3]
     testcase.debugMode = properties[4]
+    testcase.allowXml = properties[5]
 
 def load(location, xul_tester, reldir = ''):
     """
     Locates all tests by walking the filesystem starting at |location|.
     Uses xul_tester to evaluate any test conditions in the test header.
     """
     # The list of tests that we are collecting.
     tests = []
@@ -314,13 +319,14 @@ def load(location, xul_tester, reldir = 
             continue
 
         # Parse the test header and load the test.
         testcase = TestCase(os.path.join(reldir, filename),
                             enable = True,
                             expect = True,
                             random = False,
                             slow = False,
-                            debugMode = False)
+                            debugMode = False,
+                            allowXml = False)
         _parse_test_header(fullpath, testcase, xul_tester)
         tests.append(testcase)
     return tests
 
--- a/js/src/tests/lib/tests.py
+++ b/js/src/tests/lib/tests.py
@@ -75,39 +75,43 @@ class Test(object):
         """Return the '-f shell.js' options needed to run a test with the given path."""
         if path == '':
             return [ '-f', 'shell.js' ]
         head, base = os.path.split(path)
         return Test.prefix_command(head) + [ '-f', os.path.join(path, 'shell.js') ]
 
     def get_command(self, js_cmd_prefix):
         dirname, filename = os.path.split(self.path)
-        cmd = js_cmd_prefix + Test.prefix_command(dirname)
+        cmd = js_cmd_prefix
+        if self.allowXml:
+            cmd = cmd + [ '-e', 'options("allow_xml")' ]
+        cmd = cmd + Test.prefix_command(dirname)
         if self.debugMode:
             cmd += [ '-d' ]
         # There is a test that requires the path to start with './'.
         cmd += [ '-f', './' + self.path ]
         return cmd
 
     def run(self, js_cmd_prefix, timeout=30.0):
         cmd = self.get_command(js_cmd_prefix)
         out, err, rc, dt, timed_out = run_cmd(cmd, timeout)
         return TestOutput(self, cmd, out, err, rc, dt, timed_out)
 
 class TestCase(Test):
     """A test case consisting of a test and an expected result."""
     js_cmd_prefix = None
 
-    def __init__(self, path, enable, expect, random, slow, debugMode):
+    def __init__(self, path, enable, expect, random, slow, debugMode, allowXml):
         Test.__init__(self, path)
         self.enable = enable     # bool: True => run test, False => don't run
         self.expect = expect     # bool: expected result, True => pass
         self.random = random     # bool: True => ignore output as 'random'
         self.slow = slow         # bool: True => test may run slowly
         self.debugMode = debugMode # bool: True => must be run in debug mode
+        self.allowXml = allowXml # bool: True => test requires JSOPTION_ALLOW_XML
 
         # The terms parsed to produce the above properties.
         self.terms = None
 
         # The tag between |...| in the test header.
         self.tag = None
 
         # Anything occuring after -- in the test header.
--- a/js/src/tests/shell.js
+++ b/js/src/tests/shell.js
@@ -602,24 +602,25 @@ function optionsInit() {
       options.initvalues[optionName] = '';
     }
   }
 }
 
 function optionsClear() {
        
   // turn off current settings
-  // except jit.
+  // except jit and allow_xml.
   var optionNames = options().split(',');
   for (var i = 0; i < optionNames.length; i++)
   {
     var optionName = optionNames[i];
     if (optionName &&
         optionName != "methodjit" &&
-        optionName != "methodjit_always")
+        optionName != "methodjit_always" &&
+        optionName != "allow_xml")
     {
       options(optionName);
     }
   }
 }
 
 function optionsPush()
 {
@@ -674,17 +675,16 @@ function optionsReset() {
   }
 
 }
 
 if (typeof options == 'function')
 {
   optionsInit();
   optionsClear();
-  options("allow_xml");
 }
 
 function getTestCaseResult(expected, actual)
 {
   if (typeof expected != typeof actual)
     return false;
   if (typeof expected != 'number')
     // Note that many tests depend on the use of '==' here, not '==='.
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -1248,17 +1248,18 @@ xpc_MorphSlimWrapper(JSContext *cx, nsIS
     nsWrapperCache *cache;
     CallQueryInterface(tomorph, &cache);
     if (!cache)
         return NS_OK;
 
     JSObject *obj = cache->GetWrapper();
     if (!obj || !IS_SLIM_WRAPPER(obj))
         return NS_OK;
-    return MorphSlimWrapper(cx, obj);
+    NS_ENSURE_STATE(MorphSlimWrapper(cx, obj));
+    return NS_OK;
 }
 
 static nsresult
 NativeInterface2JSObject(XPCLazyCallContext & lccx,
                          JSObject * aScope,
                          nsISupports *aCOMObj,
                          nsWrapperCache *aCache,
                          const nsIID * aIID,
@@ -1659,18 +1660,17 @@ MoveWrapper(XPCCallContext& ccx, XPCWrap
         // was in the same scope. This means that the new parent
         // simply hasn't been reparented yet, so reparent it first,
         // and then continue reparenting the wrapper itself.
 
         if (!IS_WN_WRAPPER_OBJECT(newParent)) {
             // The parent of wrapper is a slim wrapper, in this case
             // we need to morph the parent so that we can reparent it.
 
-            rv = MorphSlimWrapper(ccx, newParent);
-            NS_ENSURE_SUCCESS(rv, rv);
+            NS_ENSURE_STATE(MorphSlimWrapper(ccx, newParent));
         }
 
         XPCWrappedNative *parentWrapper =
             XPCWrappedNative::GetWrappedNativeOfJSObject(ccx, newParent);
 
         rv = MoveWrapper(ccx, parentWrapper, newScope, oldScope);
         NS_ENSURE_SUCCESS(rv, rv);
 
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -16,16 +16,19 @@
 #include "gfxUtils.h"
 #include "nsImageFrame.h"
 #include "nsRenderingContext.h"
 #include "MaskLayerImageCache.h"
 
 #include "mozilla/Preferences.h"
 #include "sampler.h"
 
+#include "nsAnimationManager.h"
+#include "nsTransitionManager.h"
+
 #ifdef DEBUG
 #include <stdio.h>
 #endif
 
 using namespace mozilla::layers;
 
 namespace mozilla {
 
@@ -623,17 +626,17 @@ FrameLayerBuilder::DisplayItemDataEntry:
 void
 FrameLayerBuilder::FlashPaint(gfxContext *aContext)
 {
   static bool sPaintFlashingEnabled;
   static bool sPaintFlashingPrefCached = false;
 
   if (!sPaintFlashingPrefCached) {
     sPaintFlashingPrefCached = true;
-    mozilla::Preferences::AddBoolVarCache(&sPaintFlashingEnabled, 
+    mozilla::Preferences::AddBoolVarCache(&sPaintFlashingEnabled,
                                           "nglayout.debug.paint_flashing");
   }
 
   if (sPaintFlashingEnabled) {
     float r = float(rand()) / RAND_MAX;
     float g = float(rand()) / RAND_MAX;
     float b = float(rand()) / RAND_MAX;
     aContext->SetColor(gfxRGBA(r, g, b, 0.2));
@@ -1230,17 +1233,17 @@ ContainerState::ThebesLayerData::UpdateC
       }
     }
     mCommonClipCount = clipCount;
     NS_ASSERTION(mItemClip.mRoundedClipRects.Length() >= PRUint32(mCommonClipCount),
                  "Inconsistent common clip count.");
   } else {
     // first item in the layer
     mCommonClipCount = aCurrentClip.mRoundedClipRects.Length();
-  } 
+  }
 }
 
 already_AddRefed<ImageContainer>
 ContainerState::ThebesLayerData::CanOptimizeImageLayer()
 {
   if (!mImage) {
     return nullptr;
   }
@@ -1252,17 +1255,17 @@ void
 ContainerState::PopThebesLayerData()
 {
   NS_ASSERTION(!mThebesLayerDataStack.IsEmpty(), "Can't pop");
 
   PRInt32 lastIndex = mThebesLayerDataStack.Length() - 1;
   ThebesLayerData* data = mThebesLayerDataStack[lastIndex];
 
   nsRefPtr<Layer> layer;
-  nsRefPtr<ImageContainer> imageContainer = data->CanOptimizeImageLayer(); 
+  nsRefPtr<ImageContainer> imageContainer = data->CanOptimizeImageLayer();
 
   if ((data->mIsSolidColorInVisibleRegion || imageContainer) &&
       data->mLayer->GetValidRegion().IsEmpty()) {
     NS_ASSERTION(!(data->mIsSolidColorInVisibleRegion && imageContainer),
                  "Can't be a solid color as well as an image!");
     if (imageContainer) {
       nsRefPtr<ImageLayer> imageLayer = CreateOrRecycleImageLayer();
       imageLayer->SetContainer(imageContainer);
@@ -1310,17 +1313,17 @@ ContainerState::PopThebesLayerData()
     layer = data->mLayer;
     imageContainer = nullptr;
   }
 
   gfxMatrix transform;
   if (!layer->GetTransform().Is2D(&transform)) {
     NS_ERROR("Only 2D transformations currently supported");
   }
-  
+
   // ImageLayers are already configured with a visible region
   if (!imageContainer) {
     NS_ASSERTION(!transform.HasNonIntegerTranslation(),
                  "Matrix not just an integer translation?");
     // Convert from relative to the container to relative to the
     // ThebesLayer itself.
     nsIntRegion rgn = data->mVisibleRegion;
     rgn.MoveBy(-nsIntPoint(PRInt32(transform.x0), PRInt32(transform.y0)));
@@ -1640,19 +1643,19 @@ PaintInactiveLayer(nsDisplayListBuilder*
   // This item has an inactive layer. Render it to a ThebesLayer
   // using a temporary BasicLayerManager.
   PRInt32 appUnitsPerDevPixel = AppUnitsPerDevPixel(aItem);
   nsIntRect itemVisibleRect =
     aItem->GetVisibleRect().ToOutsidePixels(appUnitsPerDevPixel);
 
   nsRefPtr<gfxContext> context = aContext;
 #ifdef MOZ_DUMP_PAINTING
-  nsRefPtr<gfxASurface> surf; 
+  nsRefPtr<gfxASurface> surf;
   if (gfxUtils::sDumpPainting) {
-    surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(itemVisibleRect.Size(), 
+    surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(itemVisibleRect.Size(),
                                                               gfxASurface::CONTENT_COLOR_ALPHA);
     surf->SetDeviceOffset(-itemVisibleRect.TopLeft());
     context = new gfxContext(surf);
   }
 #endif
 
   nsRefPtr<BasicLayerManager> tempManager = new BasicLayerManager();
   tempManager->SetUserData(&gLayerManagerLayerBuilder, new LayerManagerLayerBuilder(aLayerBuilder, false));
@@ -1675,17 +1678,17 @@ PaintInactiveLayer(nsDisplayListBuilder*
   } else {
     tempManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer, aBuilder);
   }
   aLayerBuilder->DidEndTransaction(tempManager);
  
 #ifdef MOZ_DUMP_PAINTING
   if (gfxUtils::sDumpPainting) {
     DumpPaintedImage(aItem, surf);
-  
+
     surf->SetDeviceOffset(gfxPoint(0, 0));
     aContext->SetSource(surf, itemVisibleRect.TopLeft());
     aContext->Rectangle(itemVisibleRect);
     aContext->Fill();
     aItem->SetPainted();
   }
 #endif
 }
@@ -2552,28 +2555,28 @@ FrameLayerBuilder::GetThebesLayerResolut
 #ifdef MOZ_DUMP_PAINTING
 static void DebugPaintItem(nsRenderingContext* aDest, nsDisplayItem *aItem, nsDisplayListBuilder* aBuilder)
 {
   bool snap;
   nsRect appUnitBounds = aItem->GetBounds(aBuilder, &snap);
   gfxRect bounds(appUnitBounds.x, appUnitBounds.y, appUnitBounds.width, appUnitBounds.height);
   bounds.ScaleInverse(aDest->AppUnitsPerDevPixel());
 
-  nsRefPtr<gfxASurface> surf = 
-    gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(bounds.width, bounds.height), 
+  nsRefPtr<gfxASurface> surf =
+    gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(bounds.width, bounds.height),
                                                        gfxASurface::CONTENT_COLOR_ALPHA);
   surf->SetDeviceOffset(-bounds.TopLeft());
   nsRefPtr<gfxContext> context = new gfxContext(surf);
   nsRefPtr<nsRenderingContext> ctx = new nsRenderingContext();
   ctx->Init(aDest->DeviceContext(), context);
 
   aItem->Paint(aBuilder, ctx);
   DumpPaintedImage(aItem, surf);
   aItem->SetPainted();
-    
+
   surf->SetDeviceOffset(gfxPoint(0, 0));
   aDest->ThebesContext()->SetSource(surf, bounds.TopLeft());
   aDest->ThebesContext()->Rectangle(bounds);
   aDest->ThebesContext()->Fill();
 }
 #endif
 
 /*
@@ -3025,17 +3028,17 @@ CalculateBounds(nsTArray<FrameLayerBuild
     bounds.UnionRect(bounds, aRects[i].mRect);
    }
  
   return nsLayoutUtils::RectToGfxRect(bounds, A2D);
 }
  
 void
 ContainerState::SetupMaskLayer(Layer *aLayer, const FrameLayerBuilder::Clip& aClip,
-                               PRUint32 aRoundedRectClipCount) 
+                               PRUint32 aRoundedRectClipCount)
 {
   // don't build an unnecessary mask
   nsIntRect layerBounds = aLayer->GetVisibleRegion().GetBounds();
   if (aClip.mRoundedClipRects.IsEmpty() ||
       aRoundedRectClipCount <= 0 ||
       layerBounds.IsEmpty()) {
     return;
   }
@@ -3051,17 +3054,17 @@ ContainerState::SetupMaskLayer(Layer *aL
   }
   newData.mScaleX = mParameters.mXScale;
   newData.mScaleY = mParameters.mYScale;
 
   if (*userData == newData) {
     aLayer->SetMaskLayer(maskLayer);
     return;
   }
- 
+
   // calculate a more precise bounding rect
   const PRInt32 A2D = mContainerFrame->PresContext()->AppUnitsPerDevPixel();
   gfxRect boundingRect = CalculateBounds(newData.mRoundedClipRects, A2D);
   boundingRect.Scale(mParameters.mXScale, mParameters.mYScale);
 
   PRUint32 maxSize = mManager->GetMaxTextureSize();
   NS_ASSERTION(maxSize > 0, "Invalid max texture size");
   nsIntSize surfaceSize(NS_MIN<PRInt32>(boundingRect.Width(), maxSize),
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -5,16 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
 /*
  * structures that represent things to be painted (ordered in z-order),
  * used during painting and hit testing
  */
 
+#include "mozilla/layers/PLayers.h"
+
 #include "nsDisplayList.h"
 
 #include "nsCSSRendering.h"
 #include "nsRenderingContext.h"
 #include "nsISelectionController.h"
 #include "nsIPresShell.h"
 #include "nsRegion.h"
 #include "nsFrameManager.h"
@@ -31,23 +33,388 @@
 #include "nsIInterfaceRequestorUtils.h"
 #include "BasicLayers.h"
 #include "nsBoxFrame.h"
 #include "nsViewportFrame.h"
 #include "nsSVGEffects.h"
 #include "nsSVGElement.h"
 #include "nsSVGClipPathFrame.h"
 #include "sampler.h"
+#include "nsAnimationManager.h"
+#include "nsTransitionManager.h"
+#include "nsIViewManager.h"
 
 #include "mozilla/StandardInteger.h"
 
 using namespace mozilla;
 using namespace mozilla::layers;
 typedef FrameMetrics::ViewID ViewID;
 
+static void AddTransformFunctions(nsCSSValueList* aList,
+                                  nsStyleContext* aContext,
+                                  nsPresContext* aPresContext,
+                                  nsRect& aBounds,
+                                  float aAppUnitsPerPixel,
+                                  InfallibleTArray<TransformFunction>& aFunctions)
+{
+  if (aList->mValue.GetUnit() == eCSSUnit_None) {
+    return;
+  }
+
+  for (const nsCSSValueList* curr = aList; curr; curr = curr->mNext) {
+    const nsCSSValue& currElem = curr->mValue;
+    NS_ASSERTION(currElem.GetUnit() == eCSSUnit_Function,
+                 "Stream should consist solely of functions!");
+    nsCSSValue::Array* array = currElem.GetArrayValue();
+    bool canStoreInRuleTree = true;
+    switch (nsStyleTransformMatrix::TransformFunctionOf(array)) {
+      case eCSSKeyword_rotatex:
+      {
+        double theta = array->Item(1).GetAngleValueInRadians();
+        aFunctions.AppendElement(RotationX(theta));
+        break;
+      }
+      case eCSSKeyword_rotatey:
+      {
+        double theta = array->Item(1).GetAngleValueInRadians();
+        aFunctions.AppendElement(RotationY(theta));
+        break;
+      }
+      case eCSSKeyword_rotatez:
+      {
+        double theta = array->Item(1).GetAngleValueInRadians();
+        aFunctions.AppendElement(RotationZ(theta));
+        break;
+      }
+      case eCSSKeyword_rotate:
+      {
+        double theta = array->Item(1).GetAngleValueInRadians();
+        aFunctions.AppendElement(Rotation(theta));
+        break;
+      }
+      case eCSSKeyword_rotate3d:
+      {
+        double x = array->Item(1).GetFloatValue();
+        double y = array->Item(2).GetFloatValue();
+        double z = array->Item(3).GetFloatValue();
+        double theta = array->Item(4).GetAngleValueInRadians();
+        aFunctions.AppendElement(Rotation3D(x, y, z, theta));
+        break;
+      }
+      case eCSSKeyword_scalex:
+      {
+        double x = array->Item(1).GetFloatValue();
+        aFunctions.AppendElement(Scale(x, 1, 1));
+        break;
+      }
+      case eCSSKeyword_scaley:
+      {
+        double y = array->Item(1).GetFloatValue();
+        aFunctions.AppendElement(Scale(1, y, 1));
+        break;
+      }
+      case eCSSKeyword_scalez:
+      {
+        double z = array->Item(1).GetFloatValue();
+        aFunctions.AppendElement(Scale(1, 1, z));
+        break;
+      }
+      case eCSSKeyword_scale:
+      {
+        double x = array->Item(1).GetFloatValue();
+        // scale(x) is shorthand for scale(x, x);
+        double y = array->Count() == 2 ? x : array->Item(2).GetFloatValue();
+        aFunctions.AppendElement(Scale(x, y, 1));
+        break;
+      }
+      case eCSSKeyword_scale3d:
+      {
+        double x = array->Item(1).GetFloatValue();
+        double y = array->Item(2).GetFloatValue();
+        double z = array->Item(3).GetFloatValue();
+        aFunctions.AppendElement(Scale(x, y, z));
+        break;
+      }
+      case eCSSKeyword_translatex:
+      {
+        double x = nsStyleTransformMatrix::ProcessTranslatePart(
+          array->Item(1), aContext, aPresContext, canStoreInRuleTree,
+          aBounds.Width(), aAppUnitsPerPixel);
+        aFunctions.AppendElement(Translation(x, 0, 0));
+        break;
+      }
+      case eCSSKeyword_translatey:
+      {
+        double y = nsStyleTransformMatrix::ProcessTranslatePart(
+          array->Item(1), aContext, aPresContext, canStoreInRuleTree,
+          aBounds.Height(), aAppUnitsPerPixel);
+        aFunctions.AppendElement(Translation(0, y, 0));
+        break;
+      }
+      case eCSSKeyword_translatez:
+      {
+        double z = nsStyleTransformMatrix::ProcessTranslatePart(
+          array->Item(1), aContext, aPresContext, canStoreInRuleTree,
+          0, aAppUnitsPerPixel);
+        aFunctions.AppendElement(Translation(0, 0, z));
+        break;
+      }
+      case eCSSKeyword_translate:
+      {
+        double x = nsStyleTransformMatrix::ProcessTranslatePart(
+          array->Item(1), aContext, aPresContext, canStoreInRuleTree,
+          aBounds.Width(), aAppUnitsPerPixel);
+        // translate(x) is shorthand for translate(x, 0)
+        double y = 0;
+        if (array->Count() == 3) {
+           y = nsStyleTransformMatrix::ProcessTranslatePart(
+            array->Item(2), aContext, aPresContext, canStoreInRuleTree,
+            aBounds.Height(), aAppUnitsPerPixel);
+        }
+        aFunctions.AppendElement(Translation(x, y, 0));
+        break;
+      }
+      case eCSSKeyword_translate3d:
+      {
+        double x = nsStyleTransformMatrix::ProcessTranslatePart(
+          array->Item(1), aContext, aPresContext, canStoreInRuleTree,
+          aBounds.Width(), aAppUnitsPerPixel);
+        double y = nsStyleTransformMatrix::ProcessTranslatePart(
+          array->Item(2), aContext, aPresContext, canStoreInRuleTree,
+          aBounds.Height(), aAppUnitsPerPixel);
+        double z = nsStyleTransformMatrix::ProcessTranslatePart(
+          array->Item(3), aContext, aPresContext, canStoreInRuleTree,
+          0, aAppUnitsPerPixel);
+
+        aFunctions.AppendElement(Translation(x, y, z));
+        break;
+      }
+      case eCSSKeyword_skewx:
+      {
+        double x = array->Item(1).GetFloatValue();
+        aFunctions.AppendElement(SkewX(x));
+        break;
+      }
+      case eCSSKeyword_skewy:
+      {
+        double y = array->Item(1).GetFloatValue();
+        aFunctions.AppendElement(SkewY(y));
+        break;
+      }
+      case eCSSKeyword_matrix:
+      {
+        gfx3DMatrix matrix;
+        matrix._11 = array->Item(1).GetFloatValue();
+        matrix._12 = array->Item(2).GetFloatValue();
+        matrix._13 = 0;
+        matrix._14 = array->Item(3).GetFloatValue();
+        matrix._21 = array->Item(4).GetFloatValue();
+        matrix._22 = array->Item(5).GetFloatValue();
+        matrix._23 = 0;
+        matrix._24 = array->Item(6).GetFloatValue();
+        matrix._31 = 0;
+        matrix._32 = 0;
+        matrix._33 = 1;
+        matrix._34 = 0;
+        matrix._41 = 0;
+        matrix._42 = 0;
+        matrix._43 = 0;
+        matrix._44 = 1;
+        aFunctions.AppendElement(TransformMatrix(matrix));
+        break;
+      }
+      case eCSSKeyword_matrix3d:
+      {
+        gfx3DMatrix matrix;
+        matrix._11 = array->Item(1).GetFloatValue();
+        matrix._12 = array->Item(2).GetFloatValue();
+        matrix._13 = array->Item(3).GetFloatValue();
+        matrix._14 = array->Item(4).GetFloatValue();
+        matrix._21 = array->Item(5).GetFloatValue();
+        matrix._22 = array->Item(6).GetFloatValue();
+        matrix._23 = array->Item(7).GetFloatValue();
+        matrix._24 = array->Item(8).GetFloatValue();
+        matrix._31 = array->Item(9).GetFloatValue();
+        matrix._32 = array->Item(10).GetFloatValue();
+        matrix._33 = array->Item(11).GetFloatValue();
+        matrix._34 = array->Item(12).GetFloatValue();
+        matrix._41 = array->Item(13).GetFloatValue();
+        matrix._42 = array->Item(14).GetFloatValue();
+        matrix._43 = array->Item(15).GetFloatValue();
+        matrix._44 = array->Item(16).GetFloatValue();
+        aFunctions.AppendElement(TransformMatrix(matrix));
+        break;
+      }
+      case eCSSKeyword_perspective:
+      {
+        aFunctions.AppendElement(Perspective(array->Item(1).GetFloatValue()));
+        break;
+      }
+      default:
+        NS_ERROR("Function not handled yet!");
+    }
+  }
+}
+
+static TimingFunction
+ToTimingFunction(css::ComputedTimingFunction& aCTF)
+{
+  if (aCTF.GetType() == nsTimingFunction::Function) {
+    const nsSMILKeySpline* spline = aCTF.GetFunction();
+    return TimingFunction(CubicBezierFunction(spline->X1(), spline->Y1(),
+                                              spline->X2(), spline->Y2()));
+  }
+
+  PRUint32 type = aCTF.GetType() == nsTimingFunction::StepStart ? 1 : 2;
+  return TimingFunction(StepFunction(aCTF.GetSteps(), type));
+}
+
+static void
+AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty,
+                         ElementAnimation* ea, Layer* aLayer,
+                         AnimationData& aData)
+{
+  NS_ASSERTION(aLayer->AsContainerLayer(), "Should only animate ContainerLayer");
+  nsStyleContext* styleContext = aFrame->GetStyleContext();
+  nsPresContext* presContext = aFrame->PresContext();
+  nsRect bounds = nsDisplayTransform::GetFrameBoundsForTransform(aFrame);
+  float scale = presContext->AppUnitsPerDevPixel();
+
+  float iterations = ea->mIterationCount != NS_IEEEPositiveInfinity()
+                     ? ea->mIterationCount : -1;
+  for (PRUint32 propIdx = 0; propIdx < ea->mProperties.Length(); propIdx++) {
+    AnimationProperty* property = &ea->mProperties[propIdx];
+    InfallibleTArray<AnimationSegment> segments;
+
+    if (aProperty != property->mProperty) {
+      continue;
+    }
+
+    for (PRUint32 segIdx = 0; segIdx < property->mSegments.Length(); segIdx++) {
+      AnimationPropertySegment* segment = &property->mSegments[segIdx];
+
+      if (aProperty == eCSSProperty_transform) {
+        nsCSSValueList* list = segment->mFromValue.GetCSSValueListValue();
+        InfallibleTArray<TransformFunction> fromFunctions;
+        AddTransformFunctions(list, styleContext,
+                              presContext, bounds,
+                              scale, fromFunctions);
+
+        list = segment->mToValue.GetCSSValueListValue();
+        InfallibleTArray<TransformFunction> toFunctions;
+        AddTransformFunctions(list, styleContext,
+                              presContext, bounds,
+                              scale, toFunctions);
+
+        segments.AppendElement(AnimationSegment(fromFunctions, toFunctions,
+                                                segment->mFromKey, segment->mToKey,
+                                                ToTimingFunction(segment->mTimingFunction)));
+      } else if (aProperty == eCSSProperty_opacity) {
+        segments.AppendElement(AnimationSegment(Opacity(segment->mFromValue.GetFloatValue()),
+                                                Opacity(segment->mToValue.GetFloatValue()),
+                                                segment->mFromKey,
+                                                segment->mToKey,
+                                                ToTimingFunction(segment->mTimingFunction)));
+      }
+    }
+
+    aLayer->AddAnimation(Animation(ea->mStartTime,
+                                   ea->mIterationDuration,
+                                   segments,
+                                   iterations,
+                                   ea->mDirection,
+                                   aData));
+  }
+}
+
+static void
+AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayItem* aItem,
+                                   nsCSSProperty aProperty)
+{
+  aLayer->ClearAnimations();
+
+  nsIFrame* frame = aItem->GetUnderlyingFrame();
+  nsIContent* aContent = frame->GetContent();
+  ElementTransitions* et =
+    nsTransitionManager::GetTransitionsForCompositor(aContent, aProperty);
+
+  ElementAnimations* ea =
+    nsAnimationManager::GetAnimationsForCompositor(aContent, aProperty);
+
+  if (!ea && !et) {
+    return;
+  }
+
+  mozilla::TimeStamp currentTime =
+    frame->PresContext()->RefreshDriver()->MostRecentRefresh();
+  AnimationData data;
+  if (aProperty == eCSSProperty_transform) {
+    nsRect bounds = nsDisplayTransform::GetFrameBoundsForTransform(frame);
+    float scale = nsDeviceContext::AppUnitsPerCSSPixel();
+    gfxPoint3D offsetToTransformOrigin =
+      nsDisplayTransform::GetDeltaToMozTransformOrigin(frame, scale, &bounds);
+    gfxPoint3D offsetToPerspectiveOrigin =
+      nsDisplayTransform::GetDeltaToMozPerspectiveOrigin(frame, scale);
+    nscoord perspective = 0.0;
+    nsStyleContext* parentStyleContext = frame->GetStyleContext()->GetParent();
+    if (parentStyleContext) {
+      const nsStyleDisplay* disp = parentStyleContext->GetStyleDisplay();
+      if (disp && disp->mChildPerspective.GetUnit() == eStyleUnit_Coord) {
+        perspective = disp->mChildPerspective.GetCoordValue();
+      }
+    }
+    nsPoint origin = aItem->ToReferenceFrame();
+
+    data = TransformData(origin, offsetToTransformOrigin,
+                         offsetToPerspectiveOrigin, bounds, perspective);
+  } else if (aProperty == eCSSProperty_opacity) {
+    data = null_t();
+  }
+
+  if (et) {
+    for (PRUint32 tranIdx = 0; tranIdx < et->mPropertyTransitions.Length(); tranIdx++) {
+      ElementPropertyTransition* pt = &et->mPropertyTransitions[tranIdx];
+      if (!pt->CanPerformOnCompositor(et->mElement, currentTime)) {
+         continue;
+       }
+
+      ElementAnimation anim;
+      anim.mIterationCount = 1;
+      anim.mDirection = NS_STYLE_ANIMATION_DIRECTION_NORMAL;
+      anim.mFillMode = NS_STYLE_ANIMATION_FILL_MODE_NONE;
+      anim.mStartTime = pt->mStartTime;
+      anim.mIterationDuration = pt->mDuration;
+
+      AnimationProperty& prop = *anim.mProperties.AppendElement();
+      prop.mProperty = pt->mProperty;
+
+      AnimationPropertySegment& segment = *prop.mSegments.AppendElement();
+      segment.mFromKey = 0;
+      segment.mToKey = 1;
+      segment.mFromValue = pt->mStartValue;
+      segment.mToValue = pt->mEndValue;
+      segment.mTimingFunction = pt->mTimingFunction;
+
+      AddAnimationsForProperty(frame, aProperty, &anim,
+                               aLayer, data);
+    }
+  }
+
+  if (ea) {
+    for (PRUint32 animIdx = 0; animIdx < ea->mAnimations.Length(); animIdx++) {
+      ElementAnimation* anim = &ea->mAnimations[animIdx];
+      if (!anim->CanPerformOnCompositor(ea->mElement, currentTime)) {
+        continue;
+      }
+      AddAnimationsForProperty(frame, aProperty, anim,
+                               aLayer, data);
+    }
+  }
+}
+
 nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
     Mode aMode, bool aBuildCaret)
     : mReferenceFrame(aReferenceFrame),
       mIgnoreScrollFrame(nullptr),
       mCurrentTableItem(nullptr),
       mFinalTransparentRegion(nullptr),
       mCachedOffsetFrame(aReferenceFrame),
       mCachedOffset(0, 0),
@@ -194,31 +561,33 @@ static void RecordFrameMetrics(nsIFrame*
   nsIScrollableFrame* scrollableFrame = nullptr;
   if (aScrollFrame)
     scrollableFrame = aScrollFrame->GetScrollTargetFrame();
 
   if (scrollableFrame) {
     nsRect contentBounds = scrollableFrame->GetScrollRange();
     contentBounds.width += scrollableFrame->GetScrollPortRect().width;
     contentBounds.height += scrollableFrame->GetScrollPortRect().height;
-    metrics.mCSSContentRect = gfx::Rect(nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.x),
-                                        nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.y),
-                                        nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.width),
-                                        nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.height));
+    metrics.mCSSContentRect =
+      mozilla::gfx::Rect(nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.x),
+                         nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.y),
+                         nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.width),
+                         nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.height));
     metrics.mContentRect = contentBounds.ScaleToNearestPixels(
       aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
     metrics.mViewportScrollOffset = scrollableFrame->GetScrollPosition().ScaleToNearestPixels(
       aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
   }
   else {
     nsRect contentBounds = aForFrame->GetRect();
-    metrics.mCSSContentRect = gfx::Rect(nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.x),
-                                        nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.y),
-                                        nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.width),
-                                        nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.height));
+    metrics.mCSSContentRect =
+      mozilla::gfx::Rect(nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.x),
+                         nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.y),
+                         nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.width),
+                         nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.height));
     metrics.mContentRect = contentBounds.ScaleToNearestPixels(
       aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
   }
 
   metrics.mScrollId = aScrollId;
 
   nsIPresShell* presShell = presContext->GetPresShell();
   metrics.mResolution = gfxSize(presShell->GetXResolution(), presShell->GetYResolution());
@@ -295,17 +664,17 @@ nsDisplayListBuilder::EnterPresShell(nsI
   state->mPresShell = aReferenceFrame->PresContext()->PresShell();
   state->mCaretFrame = nullptr;
   state->mFirstFrameMarkedForDisplay = mFramesMarkedForDisplay.Length();
 
   state->mPresShell->UpdateCanvasBackground();
 
   if (mIsPaintingToWindow) {
     mReferenceFrame->AddPaintedPresShell(state->mPresShell);
-    
+
     state->mPresShell->IncrementPaintCount();
   }
 
   bool buildCaret = mBuildCaret;
   if (mIgnoreSuppression || !state->mPresShell->IsPaintingSuppressed()) {
     if (state->mPresShell->IsPaintingSuppressed()) {
       mHadToIgnoreSuppression = true;
     }
@@ -358,17 +727,17 @@ nsDisplayListBuilder::MarkFramesForDispl
                                                const nsRect& aDirtyRect) {
   for (nsFrameList::Enumerator e(aFrames); !e.AtEnd(); e.Next()) {
     mFramesMarkedForDisplay.AppendElement(e.get());
     MarkOutOfFlowFrameForDisplay(aDirtyFrame, e.get(), aDirtyRect);
   }
 }
 
 void
-nsDisplayListBuilder::MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame, const nsRect& aDirtyRect) 
+nsDisplayListBuilder::MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame, const nsRect& aDirtyRect)
 {
   nsAutoTArray<nsIFrame::ChildList,4> childListArray;
   aDirtyFrame->GetChildLists(&childListArray);
   nsIFrame::ChildListArrayIterator lists(childListArray);
   for (; !lists.IsDone(); lists.Next()) {
     nsFrameList::Enumerator childFrames(lists.CurrentList());
     for (; !childFrames.AtEnd(); childFrames.Next()) {
       nsIFrame *child = childFrames.get();
@@ -759,34 +1128,34 @@ void nsDisplayList::HitTest(nsDisplayLis
     // so that recursive calls to HitTest have more buffer space.
     item = aState->mItemBuffer[i];
     aState->mItemBuffer.SetLength(i);
 
     bool snap;
     if (aRect.Intersects(item->GetBounds(aBuilder, &snap))) {
       nsAutoTArray<nsIFrame*, 16> outFrames;
       item->HitTest(aBuilder, aRect, aState, &outFrames);
-      
-      // For 3d transforms with preserve-3d we add hit frames into the temp list 
+
+      // For 3d transforms with preserve-3d we add hit frames into the temp list
       // so we can sort them later, otherwise we add them directly to the output list.
       nsTArray<nsIFrame*> *writeFrames = aOutFrames;
       if (item->GetType() == nsDisplayItem::TYPE_TRANSFORM &&
           item->GetUnderlyingFrame()->Preserves3D()) {
         if (outFrames.Length()) {
           nsDisplayTransform *transform = static_cast<nsDisplayTransform*>(item);
           nsPoint point = aRect.TopLeft();
           // A 1x1 rect means a point, otherwise use the center of the rect
           if (aRect.width != 1 || aRect.height != 1) {
             point = aRect.Center();
           }
           temp.AppendElement(FramesWithDepth(transform->GetHitDepthAtPoint(point)));
           writeFrames = &temp[temp.Length() - 1].mFrames;
         }
       } else {
-        // We may have just finished a run of consecutive preserve-3d transforms, 
+        // We may have just finished a run of consecutive preserve-3d transforms,
         // so flush these into the destination array before processing our frame list.
         FlushFramesArray(temp, aOutFrames);
       }
 
       for (PRUint32 j = 0; j < outFrames.Length(); j++) {
         nsIFrame *f = outFrames.ElementAt(j);
         // Handle the XUL 'mousethrough' feature and 'pointer-events'.
         if (!GetMouseThrough(f) &&
@@ -821,17 +1190,17 @@ static void Sort(nsDisplayList* aList, P
     }
     prev = item;
   }
   if (sorted) {
     aList->AppendToTop(&list1);
     aList->AppendToTop(&list2);
     return;
   }
-  
+
   Sort(&list1, half, aCmp, aClosure);
   Sort(&list2, aCount - half, aCmp, aClosure);
 
   for (i = 0; i < aCount; ++i) {
     if (list1.GetBottom() &&
         (!list2.GetBottom() ||
          aCmp(list1.GetBottom(), list2.GetBottom(), aClosure))) {
       aList->AppendToTop(list1.RemoveBottom());
@@ -885,17 +1254,17 @@ void nsDisplayList::ExplodeAnonymousChil
       nsDisplayItem* j;
       while ((j = list->RemoveBottom()) != nullptr) {
         tmp.AppendToTop(static_cast<nsDisplayWrapList*>(i)->
             WrapWithClone(aBuilder, j));
       }
       i->~nsDisplayItem();
     }
   }
-  
+
   AppendToTop(&tmp);
 }
 
 void nsDisplayList::SortByZOrder(nsDisplayListBuilder* aBuilder,
                                  nsIContent* aCommonAncestor) {
   Sort(aBuilder, IsZOrderLEQ, aCommonAncestor);
 }
 
@@ -1972,24 +2341,26 @@ nsRegion nsDisplayOpacity::GetOpaqueRegi
   return nsRegion();
 }
 
 // nsDisplayOpacity uses layers for rendering
 already_AddRefed<Layer>
 nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder,
                              LayerManager* aManager,
                              const ContainerParameters& aContainerParameters) {
-  nsRefPtr<Layer> layer = GetLayerBuilderForManager(aManager)->
+  nsRefPtr<Layer> container = GetLayerBuilderForManager(aManager)->
     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
                            aContainerParameters, nullptr);
-  if (!layer)
+  if (!container)
     return nullptr;
 
-  layer->SetOpacity(mFrame->GetStyleDisplay()->mOpacity);
-  return layer.forget();
+  container->SetOpacity(mFrame->GetStyleDisplay()->mOpacity);
+  AddAnimationsAndTransitionsToLayer(container, this, eCSSProperty_opacity);
+
+  return container.forget();
 }
 
 /**
  * This doesn't take into account layer scaling --- the layer may be
  * rendered at a higher (or lower) resolution, affecting the retained layer
  * size --- but this should be good enough.
  */
 static bool
@@ -2004,16 +2375,22 @@ IsItemTooSmallForActiveLayer(nsDisplayIt
 
 nsDisplayItem::LayerState
 nsDisplayOpacity::GetLayerState(nsDisplayListBuilder* aBuilder,
                                 LayerManager* aManager,
                                 const ContainerParameters& aParameters) {
   if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateOpacityLayer) &&
       !IsItemTooSmallForActiveLayer(this))
     return LAYER_ACTIVE;
+  if (mFrame->GetContent()) {
+    if (nsLayoutUtils::HasAnimationsForCompositor(mFrame->GetContent(),
+                                                  eCSSProperty_opacity)) {
+      return LAYER_ACTIVE;
+    }
+  }
   nsIFrame* activeScrolledRoot =
     nsLayoutUtils::GetActiveScrolledRootFor(mFrame, nullptr);
   return !ChildrenCanBeInactive(aBuilder, aManager, aParameters, mList, activeScrolledRoot)
       ? LAYER_ACTIVE : LAYER_INACTIVE;
 }
 
 bool
 nsDisplayOpacity::ComputeVisibility(nsDisplayListBuilder* aBuilder,
@@ -2355,17 +2732,17 @@ nsDisplayScrollInfoLayer::TryMerge(nsDis
 }
 
 bool
 nsDisplayScrollInfoLayer::ShouldFlattenAway(nsDisplayListBuilder* aBuilder)
 {
   // Layer metadata for a particular scroll frame needs to be unique. Only
   // one nsDisplayScrollLayer (with rendered content) or one
   // nsDisplayScrollInfoLayer (with only the metadata) should survive the
-  // visibility computation. 
+  // visibility computation.
   return RemoveScrollLayerCount() == 1;
 }
 
 nsDisplayClip::nsDisplayClip(nsDisplayListBuilder* aBuilder,
                              nsIFrame* aFrame, nsDisplayItem* aItem,
                              const nsRect& aRect)
    : nsDisplayWrapList(aBuilder, aFrame, aItem,
        aFrame == aItem->GetUnderlyingFrame() ? aItem->ToReferenceFrame() : aBuilder->ToReferenceFrame(aFrame)),
@@ -2638,17 +3015,17 @@ nsDisplayTransform::GetFrameBoundsForTra
 #else
 
 nsRect
 nsDisplayTransform::GetFrameBoundsForTransform(const nsIFrame* aFrame)
 {
   NS_PRECONDITION(aFrame, "Can't get the bounds of a nonexistent frame!");
 
   nsRect result;
-  
+
   if (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) {
     // TODO: SVG needs to define what percentage translations resolve against.
     return result;
   }
 
   /* Iterate through the continuation list, unioning together all the
    * bounding rects.
    */
@@ -2665,92 +3042,93 @@ nsDisplayTransform::GetFrameBoundsForTra
 
   return result;
 }
 
 #endif
 
 /* Returns the delta specified by the -moz-transform-origin property.
  * This is a positive delta, meaning that it indicates the direction to move
- * to get from (0, 0) of the frame to the transform origin.
+ * to get from (0, 0) of the frame to the transform origin.  This function is
+ * called off the main thread.
  */
-static
-gfxPoint3D GetDeltaToMozTransformOrigin(const nsIFrame* aFrame,
-                                        float aAppUnitsPerPixel,
-                                        const nsRect* aBoundsOverride)
+/* static */ gfxPoint3D
+nsDisplayTransform::GetDeltaToMozTransformOrigin(const nsIFrame* aFrame,
+                                                 float aAppUnitsPerPixel,
+                                                 const nsRect* aBoundsOverride)
 {
   NS_PRECONDITION(aFrame, "Can't get delta for a null frame!");
   NS_PRECONDITION(aFrame->IsTransformed(),
                   "Shouldn't get a delta for an untransformed frame!");
 
   /* For both of the coordinates, if the value of -moz-transform is a
    * percentage, it's relative to the size of the frame.  Otherwise, if it's
    * a distance, it's already computed for us!
    */
   const nsStyleDisplay* display = aFrame->GetStyleDisplay();
   nsRect boundingRect = (aBoundsOverride ? *aBoundsOverride :
                          nsDisplayTransform::GetFrameBoundsForTransform(aFrame));
 
   /* Allows us to access named variables by index. */
-  gfxPoint3D result;
-  gfxFloat* coords[3] = {&result.x, &result.y, &result.z};
+  float coords[3];
   const nscoord* dimensions[2] =
     {&boundingRect.width, &boundingRect.height};
 
   for (PRUint8 index = 0; index < 2; ++index) {
     /* If the -moz-transform-origin specifies a percentage, take the percentage
      * of the size of the box.
      */
     const nsStyleCoord &coord = display->mTransformOrigin[index];
     if (coord.GetUnit() == eStyleUnit_Calc) {
       const nsStyleCoord::Calc *calc = coord.GetCalcValue();
-      *coords[index] =
+      coords[index] =
         NSAppUnitsToFloatPixels(*dimensions[index], aAppUnitsPerPixel) *
           calc->mPercent +
         NSAppUnitsToFloatPixels(calc->mLength, aAppUnitsPerPixel);
     } else if (coord.GetUnit() == eStyleUnit_Percent) {
-      *coords[index] =
+      coords[index] =
         NSAppUnitsToFloatPixels(*dimensions[index], aAppUnitsPerPixel) *
         coord.GetPercentValue();
     } else {
       NS_ABORT_IF_FALSE(coord.GetUnit() == eStyleUnit_Coord, "unexpected unit");
-      *coords[index] =
+      coords[index] =
         NSAppUnitsToFloatPixels(coord.GetCoordValue(), aAppUnitsPerPixel);
     }
     if ((aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) &&
         coord.GetUnit() != eStyleUnit_Percent) {
       // <length> values represent offsets from the origin of the SVG element's
       // user space, not the top left of its bounds, so we must adjust for that:
       nscoord offset =
         (index == 0) ? aFrame->GetPosition().x : aFrame->GetPosition().y;
-      *coords[index] -= NSAppUnitsToFloatPixels(offset, aAppUnitsPerPixel);
+      coords[index] -= NSAppUnitsToFloatPixels(offset, aAppUnitsPerPixel);
     }
   }
 
-  *coords[2] = NSAppUnitsToFloatPixels(display->mTransformOrigin[2].GetCoordValue(),
-                                       aAppUnitsPerPixel);
+  coords[2] = NSAppUnitsToFloatPixels(display->mTransformOrigin[2].GetCoordValue(),
+                                      aAppUnitsPerPixel);
   /* Adjust based on the origin of the rectangle. */
-  result.x += NSAppUnitsToFloatPixels(boundingRect.x, aAppUnitsPerPixel);
-  result.y += NSAppUnitsToFloatPixels(boundingRect.y, aAppUnitsPerPixel);
-
-  return result;
+  coords[0] += NSAppUnitsToFloatPixels(boundingRect.x, aAppUnitsPerPixel);
+  coords[1] += NSAppUnitsToFloatPixels(boundingRect.y, aAppUnitsPerPixel);
+
+  return gfxPoint3D(coords[0], coords[1], coords[2]);
 }
 
 /* Returns the delta specified by the -moz-perspective-origin property.
  * This is a positive delta, meaning that it indicates the direction to move
- * to get from (0, 0) of the frame to the perspective origin.
+ * to get from (0, 0) of the frame to the perspective origin. This function is
+ * called off the main thread.
  */
-static
-gfxPoint3D GetDeltaToMozPerspectiveOrigin(const nsIFrame* aFrame,
-                                          float aAppUnitsPerPixel)
+/* static */ gfxPoint3D
+nsDisplayTransform::GetDeltaToMozPerspectiveOrigin(const nsIFrame* aFrame,
+                                                   float aAppUnitsPerPixel)
 {
   NS_PRECONDITION(aFrame, "Can't get delta for a null frame!");
   NS_PRECONDITION(aFrame->IsTransformed(),
                   "Shouldn't get a delta for an untransformed frame!");
-  NS_PRECONDITION(aFrame->GetParentStyleContextFrame(), 
+  NS_PRECONDITION(aFrame->GetParentStyleContextFrame(),
                   "Can't get delta without a style parent!");
 
   /* For both of the coordinates, if the value of -moz-perspective-origin is a
    * percentage, it's relative to the size of the frame.  Otherwise, if it's
    * a distance, it's already computed for us!
    */
 
   //TODO: Should this be using our bounds or the parent's bounds?
@@ -2798,107 +3176,125 @@ gfxPoint3D GetDeltaToMozPerspectiveOrigi
 }
 
 /* Wraps up the -moz-transform matrix in a change-of-basis matrix pair that
  * translates from local coordinate space to transform coordinate space, then
  * hands it back.
  */
 gfx3DMatrix
 nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
-                                                const nsPoint &aOrigin,
+                                                const nsPoint& aOrigin,
                                                 float aAppUnitsPerPixel,
                                                 const nsRect* aBoundsOverride,
+                                                const nsCSSValueList* aTransformOverride,
+                                                gfxPoint3D* aToMozOrigin,
+                                                gfxPoint3D* aToPerspectiveOrigin,
+                                                nscoord* aChildPerspective,
                                                 nsIFrame** aOutAncestor)
 {
-  NS_PRECONDITION(aFrame, "Cannot get transform matrix for a null frame!");
+  NS_PRECONDITION(aFrame || (aToMozOrigin && aBoundsOverride && aToPerspectiveOrigin &&
+                             aTransformOverride && aChildPerspective),
+                  "Should have frame or necessary infromation to construct matrix");
+
+  NS_PRECONDITION(!(aFrame && (aToMozOrigin || aToPerspectiveOrigin ||
+                             aTransformOverride || aChildPerspective)),
+                  "Should not have both frame and necessary infromation to construct matrix");
 
   if (aOutAncestor) {
       *aOutAncestor = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
   }
 
   /* Account for the -moz-transform-origin property by translating the
    * coordinate space to the new origin.
    */
   gfxPoint3D toMozOrigin =
-    GetDeltaToMozTransformOrigin(aFrame, aAppUnitsPerPixel, aBoundsOverride);
+    aFrame ? GetDeltaToMozTransformOrigin(aFrame, aAppUnitsPerPixel, aBoundsOverride) : *aToMozOrigin;
   gfxPoint3D newOrigin =
     gfxPoint3D(NSAppUnitsToFloatPixels(aOrigin.x, aAppUnitsPerPixel),
                NSAppUnitsToFloatPixels(aOrigin.y, aAppUnitsPerPixel),
                0.0f);
 
   /* Get the underlying transform matrix.  This requires us to get the
    * bounds of the frame.
    */
-  const nsStyleDisplay* disp = aFrame->GetStyleDisplay();
+  const nsStyleDisplay* disp = aFrame ? aFrame->GetStyleDisplay() : nullptr;
   nsRect bounds = (aBoundsOverride ? *aBoundsOverride :
                    nsDisplayTransform::GetFrameBoundsForTransform(aFrame));
 
   /* Get the matrix, then change its basis to factor in the origin. */
   bool dummy;
   gfx3DMatrix result;
   // Call IsSVGTransformed() regardless of the value of
   // disp->mSpecifiedTransform, since we still need any transformFromSVGParent.
   gfxMatrix svgTransform, transformFromSVGParent;
   bool hasSVGTransforms =
-    aFrame->IsSVGTransformed(&svgTransform, &transformFromSVGParent);
+    aFrame && aFrame->IsSVGTransformed(&svgTransform, &transformFromSVGParent);
   /* Transformed frames always have a transform, or are preserving 3d (and might still have perspective!) */
-  if (disp->mSpecifiedTransform) {
+  if (aTransformOverride) {
+    result = nsStyleTransformMatrix::ReadTransforms(aTransformOverride, nullptr, nullptr,
+                                                    dummy, bounds, aAppUnitsPerPixel);
+  } else if (disp->mSpecifiedTransform) {
     result = nsStyleTransformMatrix::ReadTransforms(disp->mSpecifiedTransform,
                                                     aFrame->GetStyleContext(),
                                                     aFrame->PresContext(),
                                                     dummy, bounds, aAppUnitsPerPixel);
   } else if (hasSVGTransforms) {
     // Correct the translation components for zoom:
     float pixelsPerCSSPx = aFrame->PresContext()->AppUnitsPerCSSPixel() /
                              aAppUnitsPerPixel;
     svgTransform.x0 *= pixelsPerCSSPx;
     svgTransform.y0 *= pixelsPerCSSPx;
     result = gfx3DMatrix::From2D(svgTransform);
-  } else {
-     NS_ASSERTION(aFrame->GetStyleDisplay()->mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
-                  aFrame->GetStyleDisplay()->mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN,
-                  "If we don't have a transform, then we must have another reason to have an nsDisplayTransform created");
   }
 
   if (hasSVGTransforms && !transformFromSVGParent.IsIdentity()) {
     // Correct the translation components for zoom:
     float pixelsPerCSSPx = aFrame->PresContext()->AppUnitsPerCSSPixel() /
                              aAppUnitsPerPixel;
     transformFromSVGParent.x0 *= pixelsPerCSSPx;
     transformFromSVGParent.y0 *= pixelsPerCSSPx;
     result = result * gfx3DMatrix::From2D(transformFromSVGParent);
   }
 
   const nsStyleDisplay* parentDisp = nullptr;
-  nsStyleContext* parentStyleContext = aFrame->GetStyleContext()->GetParent();
+  nsStyleContext* parentStyleContext = aFrame ? aFrame->GetStyleContext()->GetParent(): nullptr;
   if (parentStyleContext) {
     parentDisp = parentStyleContext->GetStyleDisplay();
   }
-  if (nsLayoutUtils::Are3DTransformsEnabled() &&
-      parentDisp && parentDisp->mChildPerspective.GetUnit() == eStyleUnit_Coord &&
-      parentDisp->mChildPerspective.GetCoordValue() > 0.0) {
+  nscoord perspectiveCoord = 0;
+  if (parentDisp && parentDisp->mChildPerspective.GetUnit() == eStyleUnit_Coord) {
+    perspectiveCoord = parentDisp->mChildPerspective.GetCoordValue();
+  }
+  if (aChildPerspective) {
+    perspectiveCoord = *aChildPerspective;
+  }
+
+  if (nsLayoutUtils::Are3DTransformsEnabled() && perspectiveCoord > 0.0) {
     gfx3DMatrix perspective;
     perspective._34 =
       -1.0 / NSAppUnitsToFloatPixels(parentDisp->mChildPerspective.GetCoordValue(),
                                      aAppUnitsPerPixel);
     /* At the point when perspective is applied, we have been translated to the transform origin.
      * The translation to the perspective origin is the difference between these values.
      */
-    gfxPoint3D toPerspectiveOrigin = GetDeltaToMozPerspectiveOrigin(aFrame, aAppUnitsPerPixel);
+    gfxPoint3D toPerspectiveOrigin = aFrame ? GetDeltaToMozPerspectiveOrigin(aFrame, aAppUnitsPerPixel) : *aToPerspectiveOrigin;
     result = result * nsLayoutUtils::ChangeMatrixBasis(toPerspectiveOrigin - toMozOrigin, perspective);
   }
 
-  if (aFrame->Preserves3D() && nsLayoutUtils::Are3DTransformsEnabled()) {
+  if (aFrame && aFrame->Preserves3D() && nsLayoutUtils::Are3DTransformsEnabled()) {
       // Include the transform set on our parent
       NS_ASSERTION(aFrame->GetParent() &&
                    aFrame->GetParent()->IsTransformed() &&
                    aFrame->GetParent()->Preserves3DChildren(),
                    "Preserve3D mismatch!");
-      gfx3DMatrix parent = GetResultingTransformMatrix(aFrame->GetParent(), aOrigin - aFrame->GetPosition(),
-                                                       aAppUnitsPerPixel, nullptr, aOutAncestor);
+      gfx3DMatrix parent =
+        GetResultingTransformMatrix(aFrame->GetParent(),
+                                    aOrigin - aFrame->GetPosition(),
+                                    aAppUnitsPerPixel, nullptr, nullptr, nullptr,
+                                    nullptr, nullptr, aOutAncestor);
       return nsLayoutUtils::ChangeMatrixBasis(newOrigin + toMozOrigin, result) * parent;
   }
 
   return nsLayoutUtils::ChangeMatrixBasis
     (newOrigin + toMozOrigin, result);
 }
 
 bool
@@ -2919,17 +3315,17 @@ nsDisplayTransform::ShouldPrerenderTrans
         return true;
       }
     }
   }
   return false;
 }
 
 /* If the matrix is singular, or a hidden backface is shown, the frame won't be visible or hit. */
-static bool IsFrameVisible(nsIFrame* aFrame, const gfx3DMatrix& aMatrix) 
+static bool IsFrameVisible(nsIFrame* aFrame, const gfx3DMatrix& aMatrix)
 {
   if (aMatrix.IsSingular()) {
     return false;
   }
   if (aFrame->GetStyleDisplay()->mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN &&
       aMatrix.IsBackfaceVisible()) {
     return false;
   }
@@ -2937,63 +3333,70 @@ static bool IsFrameVisible(nsIFrame* aFr
 }
 
 const gfx3DMatrix&
 nsDisplayTransform::GetTransform(float aAppUnitsPerPixel)
 {
   if (mTransform.IsIdentity() || mCachedAppUnitsPerPixel != aAppUnitsPerPixel) {
     mTransform =
       GetResultingTransformMatrix(mFrame, ToReferenceFrame(),
-                                  aAppUnitsPerPixel,
-                                  nullptr);
+                                  aAppUnitsPerPixel);
     mCachedAppUnitsPerPixel = aAppUnitsPerPixel;
   }
   return mTransform;
 }
 
 already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBuilder,
                                                        LayerManager *aManager,
                                                        const ContainerParameters& aContainerParameters)
 {
-  const gfx3DMatrix& newTransformMatrix = 
+  const gfx3DMatrix& newTransformMatrix =
     GetTransform(mFrame->PresContext()->AppUnitsPerDevPixel());
 
   if (!IsFrameVisible(mFrame, newTransformMatrix)) {
     return nullptr;
   }
 
   nsRefPtr<ContainerLayer> container = GetLayerBuilderForManager(aManager)->
     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, *mStoredList.GetList(),
                            aContainerParameters, &newTransformMatrix);
 
   // Add the preserve-3d flag for this layer, BuildContainerLayerFor clears all flags,
   // so we never need to explicitely unset this flag.
   if (mFrame->Preserves3D() || mFrame->Preserves3DChildren()) {
     container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_PRESERVE_3D);
   }
+
+  AddAnimationsAndTransitionsToLayer(container, this, eCSSProperty_transform);
   return container.forget();
 }
 
 nsDisplayItem::LayerState
 nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
                                   LayerManager* aManager,
                                   const ContainerParameters& aParameters) {
   // Here we check if the *post-transform* bounds of this item are big enough
   // to justify an active layer.
   if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateTransformLayer) &&
       !IsItemTooSmallForActiveLayer(this))
     return LAYER_ACTIVE;
   if (!GetTransform(mFrame->PresContext()->AppUnitsPerDevPixel()).Is2D() || mFrame->Preserves3D())
     return LAYER_ACTIVE;
+  if (mFrame->GetContent()) {
+    if (nsLayoutUtils::HasAnimationsForCompositor(mFrame->GetContent(),
+                                                  eCSSProperty_transform)) {
+      return LAYER_ACTIVE;
+    }
+  }
   nsIFrame* activeScrolledRoot =
     nsLayoutUtils::GetActiveScrolledRootFor(mFrame, nullptr);
-  return !mStoredList.ChildrenCanBeInactive(aBuilder, 
-                                            aManager, 
+  return !mStoredList.ChildrenCanBeInactive(aBuilder,
+                                            aManager,
                                             aParameters,
-                                            *mStoredList.GetList(), 
+                                            *mStoredList.GetList(),
                                             activeScrolledRoot)
       ? LAYER_ACTIVE : LAYER_INACTIVE;
 }
 
 bool nsDisplayTransform::ComputeVisibility(nsDisplayListBuilder *aBuilder,
                                              nsRegion *aVisibleRegion,
                                              const nsRect& aAllowVisibleRegionExpansion)
 {
@@ -3002,19 +3405,19 @@ bool nsDisplayTransform::ComputeVisibili
    * think that it's painting in its original rectangular coordinate space.
    * If we can't untransform, take the entire overflow rect */
   nsRect untransformedVisibleRect;
   float factor = nsPresContext::AppUnitsPerCSSPixel();
   if (ShouldPrerenderTransformedContent(aBuilder, mFrame) ||
       !UntransformRectMatrix(mVisibleRect,
                              GetTransform(factor),
                              factor,
-                             &untransformedVisibleRect)) 
+                             &untransformedVisibleRect))
   {
-    untransformedVisibleRect = mFrame->GetVisualOverflowRectRelativeToSelf() +  
+    untransformedVisibleRect = mFrame->GetVisualOverflowRectRelativeToSelf() +
                                aBuilder->ToReferenceFrame(mFrame);
   }
   nsRegion untransformedVisible = untransformedVisibleRect;
   // Call RecomputeVisiblity instead of ComputeVisibility since
   // nsDisplayItem::ComputeVisibility should only be called from
   // nsDisplayList::ComputeVisibility (which sets mVisibleRect on the item)
   mStoredList.RecomputeVisibility(aBuilder, &untransformedVisible);
   return true;
@@ -3069,17 +3472,17 @@ void nsDisplayTransform::HitTest(nsDispl
 
     gfxRect rect = matrix.Inverse().ProjectRectBounds(originalRect);;
 
     resultingRect = nsRect(NSFloatPixelsToAppUnits(float(rect.X()), factor),
                            NSFloatPixelsToAppUnits(float(rect.Y()), factor),
                            NSFloatPixelsToAppUnits(float(rect.Width()), factor),
                            NSFloatPixelsToAppUnits(float(rect.Height()), factor));
   }
-  
+
 
 #ifdef DEBUG_HIT
   printf("Frame: %p\n", dynamic_cast<void *>(mFrame));
   printf("  Untransformed point: (%f, %f)\n", resultingRect.X(), resultingRect.Y());
   PRUint32 originalFrameCount = aOutFrames.Length();
 #endif
 
   mStoredList.HitTest(aBuilder, resultingRect, aState, aOutFrames);
@@ -3095,18 +3498,18 @@ void nsDisplayTransform::HitTest(nsDispl
 
 float
 nsDisplayTransform::GetHitDepthAtPoint(const nsPoint& aPoint)
 {
   float factor = nsPresContext::AppUnitsPerCSSPixel();
   gfx3DMatrix matrix = GetTransform(factor);
 
   NS_ASSERTION(IsFrameVisible(mFrame, matrix), "We can't have hit a frame that isn't visible!");
-    
-  gfxPoint point = 
+
+  gfxPoint point =
     matrix.Inverse().ProjectPoint(gfxPoint(NSAppUnitsToFloatPixels(aPoint.x, factor),
                                            NSAppUnitsToFloatPixels(aPoint.y, factor)));
 
   gfxPoint3D transformed = matrix.Transform3D(gfxPoint3D(point.x, point.y, 0));
   return transformed.z;
 }
 
 /* The bounding rectangle for the object is the overflow rectangle translated
@@ -3145,17 +3548,17 @@ nsRegion nsDisplayTransform::GetOpaqueRe
                                              bool* aSnap)
 {
   *aSnap = false;
   nsRect untransformedVisible;
   float factor = nsPresContext::AppUnitsPerCSSPixel();
   if (!UntransformRectMatrix(mVisibleRect, GetTransform(factor), factor, &untransformedVisible)) {
       return nsRegion();
   }
-  
+
   const gfx3DMatrix& matrix = GetTransform(nsPresContext::AppUnitsPerCSSPixel());
 
   nsRegion result;
   gfxMatrix matrix2d;
   bool tmpSnap;
   if (matrix.Is2D(&matrix2d) &&
       matrix2d.PreservesAxisAlignedRectangles() &&
       mStoredList.GetOpaqueRegion(aBuilder, &tmpSnap).Contains(untransformedVisible)) {
@@ -3292,17 +3695,17 @@ bool nsDisplayTransform::UntransformRect
                                            nsRect* aOutRect)
 {
   NS_PRECONDITION(aFrame, "Can't take the transform based on a null frame!");
 
   /* Grab the matrix.  If the transform is degenerate, just hand back the
    * empty rect.
    */
   float factor = nsPresContext::AppUnitsPerCSSPixel();
-  gfx3DMatrix matrix = GetResultingTransformMatrix(aFrame, aOrigin, factor, nullptr);
+  gfx3DMatrix matrix = GetResultingTransformMatrix(aFrame, aOrigin, factor);
 
   return UntransformRectMatrix(aUntransformedBounds, matrix, factor, aOutRect);
 }
 
 nsDisplaySVGEffects::nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder,
                                          nsIFrame* aFrame, nsDisplayList* aList)
     : nsDisplayWrapList(aBuilder, aFrame, aList),
       mEffectsBounds(aFrame->GetVisualOverflowRectRelativeToSelf())
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -103,20 +103,20 @@ public:
    * @param aReferenceFrame the frame at the root of the subtree; its origin
    * is the origin of the reference coordinate system for this display list
    * @param aIsForEvents true if we're creating this list in order to
    * determine which frame is under the mouse position
    * @param aBuildCaret whether or not we should include the caret in any
    * display lists that we make.
    */
   enum Mode {
-	PAINTING,
-	EVENT_DELIVERY,
-	PLUGIN_GEOMETRY,
-	OTHER
+    PAINTING,
+    EVENT_DELIVERY,
+    PLUGIN_GEOMETRY,
+    OTHER
   };
   nsDisplayListBuilder(nsIFrame* aReferenceFrame, Mode aMode, bool aBuildCaret);
   ~nsDisplayListBuilder();
 
   /**
    * @return true if the display is being built in order to determine which
    * frame is under the mouse position.
    */
@@ -2348,16 +2348,23 @@ public:
                                 const nsPoint &aOrigin,
                                 nsRect* aOutRect);
   
   static bool UntransformRectMatrix(const nsRect &aUntransformedBounds, 
                                     const gfx3DMatrix& aMatrix,
                                     float aAppUnitsPerPixel,
                                     nsRect* aOutRect);
 
+  static gfxPoint3D GetDeltaToMozTransformOrigin(const nsIFrame* aFrame,
+                                                 float aAppUnitsPerPixel,
+                                                 const nsRect* aBoundsOverride);
+
+  static gfxPoint3D GetDeltaToMozPerspectiveOrigin(const nsIFrame* aFrame,
+                                                   float aAppUnitsPerPixel);
+
   /**
    * Returns the bounds of a frame as defined for resolving percentage
    * <translation-value>s in CSS transforms.  If
    * UNIFIED_CONTINUATIONS is not defined, this is simply the frame's bounding
    * rectangle, translated to the origin.  Otherwise, returns the smallest
    * rectangle containing a frame and all of its continuations.  For example,
    * if there is a <span> element with several continuations split over
    * several lines, this function will return the rectangle containing all of
@@ -2381,16 +2388,20 @@ public:
    *        for the frame's bounding rectangle. Otherwise, it will use the
    *        value of aBoundsOverride.  This is mostly for internal use and in
    *        most cases you will not need to specify a value.
    */
   static gfx3DMatrix GetResultingTransformMatrix(const nsIFrame* aFrame,
                                                  const nsPoint& aOrigin,
                                                  float aAppUnitsPerPixel,
                                                  const nsRect* aBoundsOverride = nullptr,
+                                                 const nsCSSValueList* aTransformOverride = nullptr,
+                                                 gfxPoint3D* aToMozOrigin = nullptr,
+                                                 gfxPoint3D* aToPerspectiveOrigin = nullptr,
+                                                 nscoord* aChildPerspective = nullptr,
                                                  nsIFrame** aOutAncestor = nullptr);
   /**
    * Return true when we should try to prerender the entire contents of the
    * transformed frame even when it's not completely visible (yet).
    */
   static bool ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBuilder,
                                                 nsIFrame* aFrame);
 
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 sw=2 et tw=78: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "base/basictypes.h"
 #include "mozilla/Util.h"
 
 #include "nsLayoutUtils.h"
 #include "nsIFormControlFrame.h"
 #include "nsPresContext.h"
 #include "nsIContent.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLElement.h"
@@ -65,29 +66,31 @@
 #include "mozilla/dom/Element.h"
 #include "nsCanvasFrame.h"
 #include "gfxDrawable.h"
 #include "gfxUtils.h"
 #include "nsDataHashtable.h"
 #include "nsTextFrame.h"
 #include "nsFontFaceList.h"
 #include "nsFontInflationData.h"
-
+#include "CompositorParent.h"
 #include "nsSVGUtils.h"
 #include "nsSVGIntegrationUtils.h"
 #include "nsSVGForeignObjectFrame.h"
 #include "nsSVGOuterSVGFrame.h"
 
 #include "mozilla/Preferences.h"
 
 #ifdef MOZ_XUL
 #include "nsXULPopupManager.h"
 #endif
 
 #include "sampler.h"
+#include "nsAnimationManager.h"
+#include "nsTransitionManager.h"
 
 using namespace mozilla;
 using namespace mozilla::layers;
 using namespace mozilla::dom;
 using namespace mozilla::layout;
 
 #ifdef DEBUG
 // TODO: remove, see bug 598468.
@@ -108,33 +111,89 @@ static ContentMap* sContentMap = NULL;
 static ContentMap& GetContentMap() {
   if (!sContentMap) {
     sContentMap = new ContentMap();
     sContentMap->Init();
   }
   return *sContentMap;
 }
 
+bool
+nsLayoutUtils::HasAnimationsForCompositor(nsIContent* aContent,
+                                          nsCSSProperty aProperty)
+{
+  if (!aContent->MayHaveAnimations())
+    return false;
+  ElementAnimations* animations =
+    static_cast<ElementAnimations*>(aContent->GetProperty(nsGkAtoms::animationsProperty));
+  if (animations) {
+    bool propertyMatches = animations->HasAnimationOfProperty(aProperty);
+    if (propertyMatches && animations->CanPerformOnCompositorThread()) {
+      return true;
+    }
+  }
+
+  ElementTransitions* transitions =
+    static_cast<ElementTransitions*>(aContent->GetProperty(nsGkAtoms::transitionsProperty));
+  if (transitions) {
+    bool propertyMatches = transitions->HasTransitionOfProperty(aProperty);
+    if (propertyMatches && transitions->CanPerformOnCompositorThread()) {
+      return true;
+    }
+  }
+
+  return false;
+}
 
 bool
 nsLayoutUtils::Are3DTransformsEnabled()
 {
   static bool s3DTransformsEnabled;
   static bool s3DTransformPrefCached = false;
 
   if (!s3DTransformPrefCached) {
     s3DTransformPrefCached = true;
-    mozilla::Preferences::AddBoolVarCache(&s3DTransformsEnabled, 
+    mozilla::Preferences::AddBoolVarCache(&s3DTransformsEnabled,
                                           "layout.3d-transforms.enabled");
   }
 
   return s3DTransformsEnabled;
 }
 
 bool
+nsLayoutUtils::AreOpacityAnimationsEnabled()
+{
+  static bool sAreOpacityAnimationsEnabled;
+  static bool sOpacityPrefCached = false;
+
+  if (!sOpacityPrefCached) {
+    sOpacityPrefCached = true;
+    Preferences::AddBoolVarCache(&sAreOpacityAnimationsEnabled,
+                                 "layers.offmainthreadcomposition.animate-opacity");
+  }
+
+  return sAreOpacityAnimationsEnabled && CompositorParent::CompositorLoop();
+}
+
+bool
+nsLayoutUtils::AreTransformAnimationsEnabled()
+{
+  static bool sAreTransformAnimationsEnabled;
+  static bool sTransformPrefCached = false;
+
+  if (!sTransformPrefCached) {
+    sTransformPrefCached = true;
+    Preferences::AddBoolVarCache(&sAreTransformAnimationsEnabled,
+                                 "layers.offmainthreadcomposition.animate-transform");
+  }
+
+  return sAreTransformAnimationsEnabled && CompositorParent::CompositorLoop();
+}
+
+bool
 nsLayoutUtils::UseBackgroundNearestFiltering()
 {
   static bool sUseBackgroundNearestFilteringEnabled;
   static bool sUseBackgroundNearestFilteringPrefInitialised = false;
 
   if (!sUseBackgroundNearestFilteringPrefInitialised) {
     sUseBackgroundNearestFilteringPrefInitialised = true;
     sUseBackgroundNearestFilteringEnabled = mozilla::Preferences::GetBool("gfx.filter.nearest.force-enabled", false);
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -1493,21 +1493,34 @@ public:
    *    (void)SizeOfTextRunsForFrames(rootFrame, nullptr, true);
    *    total = SizeOfTextRunsForFrames(rootFrame, mallocSizeOf, false);
    */
   static size_t SizeOfTextRunsForFrames(nsIFrame* aFrame,
                                         nsMallocSizeOfFun aMallocSizeOf,
                                         bool clear);
 
   /**
+   * Returns true if the content node has animations or transitions that can be
+   * performed on the compositor.
+   */
+  static bool HasAnimationsForCompositor(nsIContent* aContent,
+                                         nsCSSProperty aProperty);
+
+  /**
    * Checks if CSS 3D transforms are currently enabled.
    */
   static bool Are3DTransformsEnabled();
 
   /**
+   * Checks if off-main-thread transform and opacity animations are enabled.
+   */
+  static bool AreOpacityAnimationsEnabled();
+  static bool AreTransformAnimationsEnabled();
+
+  /**
    * Checks if we should forcibly use nearest pixel filtering for the
    * background.
    */
   static bool UseBackgroundNearestFiltering();
 
   /**
    * Checks whether we want to use the GPU to scale images when
    * possible.
--- a/layout/base/nsStyleConsts.h
+++ b/layout/base/nsStyleConsts.h
@@ -801,16 +801,19 @@ static inline mozilla::css::Side operato
 #define NS_STYLE_PAGE_BREAK_AVOID               2
 #define NS_STYLE_PAGE_BREAK_LEFT                3
 #define NS_STYLE_PAGE_BREAK_RIGHT               4
 
 // See nsStyleColumn
 #define NS_STYLE_COLUMN_COUNT_AUTO              0
 #define NS_STYLE_COLUMN_COUNT_UNLIMITED         (-1)
 
+#define NS_STYLE_COLUMN_FILL_AUTO               0
+#define NS_STYLE_COLUMN_FILL_BALANCE            1
+
 // See nsStyleUIReset
 #define NS_STYLE_IME_MODE_AUTO                  0
 #define NS_STYLE_IME_MODE_NORMAL                1
 #define NS_STYLE_IME_MODE_ACTIVE                2
 #define NS_STYLE_IME_MODE_DISABLED              3
 #define NS_STYLE_IME_MODE_INACTIVE              4
 
 // See nsStyleGradient
--- a/layout/base/tests/test_bug435293-skew.html
+++ b/layout/base/tests/test_bug435293-skew.html
@@ -32,43 +32,43 @@ https://bugzilla.mozilla.org/show_bug.cg
        Degrees and grads do not suffer this problem.  */
     #test1 {
       -moz-transform: skewx(30deg);
     }
     #test2 {
       -moz-transform: skewy(60deg);
     }
     #test3 {
-      -moz-transform: skewx(45deg);
+      -moz-transform: skew(45deg, 45deg);
     }
     #test4 {
-      -moz-transform: skewy(360deg);
+      -moz-transform: skew(360deg, 45deg);
     }
     #test5 {
-      -moz-transform: skewx(80%);
+      -moz-transform: skew(45deg, 150grad);
     }
     #test6 {
-      -moz-transform: skewy(2em);
+      -moz-transform: skew(80%, 78px);
     }
     #test7 {
-      -moz-transform: skewx(-45deg);
+      -moz-transform: skew(2em, 40ex);
     }
     #test8 {
-      -moz-transform: skewy(-465deg);
+      -moz-transform: skew(-45deg, -465deg);
     }
     #test9 {
-      -moz-transform: skewx(30deg, 30deg);
+      -moz-transform: skew(30deg, 30deg, 30deg);
     }
 
     /* approach the singularity from the negative side */
     #test10 {
-      -moz-transform: skewx(90.001deg);
+      -moz-transform: skew(50grad, 90.001deg);
     }
     #test11 {
-      -moz-transform: skewy(90.001deg);
+      -moz-transform: skew(300grad, 90.001deg);
     }
   </style>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=435293">Mozilla Bug 435293</a>
 <p id="display"></p>
 <div id="content">
   <div class="pane"><div id="test1" class="test">test</div></div>
@@ -112,59 +112,59 @@ function runtests() {
   is((+tformValues[0]), 1, "Test2: skewy: param 0 is 1");
   ok(verifyRounded(tformValues[1], 1.73205), "Test2: skewy: Rounded param 1 is in bounds");
   is((+tformValues[2]), 0, "Test2: skewy: param 2 is 0");
   is((+tformValues[3]), 1, "Test2: skewy: param 3 is 1");
   is((+tformValues[4]), 0, "Test2: skewy: param 4 is 0");
   is((+tformValues[5]), 0, "Test2: skewy: param 5 is 0");
 
   style = window.getComputedStyle(document.getElementById("test3"), "");
-  is(style.getPropertyValue("-moz-transform"), "matrix(1, 0, 1, 1, 0, 0)",
+  is(style.getPropertyValue("-moz-transform"), "matrix(1, 1, 1, 1, 0, 0)",
      "Test3: Skew proper matrix is applied");
 
   style = window.getComputedStyle(document.getElementById("test4"), "");
-  is(style.getPropertyValue("-moz-transform"), "matrix(1, 0, 0, 1, 0, 0)",
+  is(style.getPropertyValue("-moz-transform"), "matrix(1, 1, 0, 1, 0, 0)",
      "Test4: Skew angle wrap: proper matrix is applied");
 
   style = window.getComputedStyle(document.getElementById("test5"), "");
-  is(style.getPropertyValue("-moz-transform"), "none",
-     "Test5: Skewx with invalid units");
+  is(style.getPropertyValue("-moz-transform"), "matrix(1, -1, 1, 1, 0, 0)",
+     "Test5: Skew mixing deg and grad");
 
   style = window.getComputedStyle(document.getElementById("test6"), "");
   is(style.getPropertyValue("-moz-transform"), "none",
-     "Test6: Skewy with invalid units");
+     "Test6: Skew with invalid units");
 
   style = window.getComputedStyle(document.getElementById("test7"), "");
-  is(style.getPropertyValue("-moz-transform"), "matrix(1, 0, -1, 1, 0, 0)",
-     "Test7: Skewx with negative angle");
+  is(style.getPropertyValue("-moz-transform"), "none",
+     "Test7: Skew with more invalid units");
 
   // Test 8: skew with negative degrees, here again we must handle rounding.
-  // The matrix should be: matrix(1, 3.73206, 0, 1, 0, 0)
+  // The matrix should be: matrix(1, 3.73206, -1, 1, 0, 0)
   style = window.getComputedStyle(document.getElementById("test8"), "");
   tformStyle = style.getPropertyValue("-moz-transform");
   tformValues = tformStyle.substring(tformStyle.indexOf('(') + 1,
                                      tformStyle.indexOf(')')).split(',');
   is(tformValues[0], 1, "Test8: Test skew with negative degrees-param 0 is 1");
   ok(verifyRounded(tformValues[1], 3.73206), "Test8: Rounded param 1 is in bounds");
-  is((+tformValues[2]), 0, "Test8: param 2 is 0");
+  is((+tformValues[2]), -1, "Test8: param 2 is -1");
   is((+tformValues[3]), 1, "Test8: param 3 is 1");
   is((+tformValues[4]), 0, "Test8: param 4 is 0");
   is((+tformValues[5]), 0, "Test8: param 5 is 0");
 
   style = window.getComputedStyle(document.getElementById("test9"), "");
   is(style.getPropertyValue("-moz-transform"), "none",
-     "Test9: Skewx with two parameters should be ignored");
+     "Test9: Skew in 3d should be ignored");
 
   style = window.getComputedStyle(document.getElementById("test10"), "");
-  is(style.getPropertyValue("-moz-transform"), "matrix(1, 0, -10000, 1, 0, 0)",
-     "Test10: Skewx with nearly infinite numbers");
+  is(style.getPropertyValue("-moz-transform"), "matrix(1, -10000, 1, 1, 0, 0)",
+     "Test10: Skew with nearly infinite numbers");
 
   style = window.getComputedStyle(document.getElementById("test11"), "");
-  is(style.getPropertyValue("-moz-transform"), "matrix(1, -10000, 0, 1, 0, 0)",
-     "Test11: Skewy with nearly infinite numbers");
+  is(style.getPropertyValue("-moz-transform"), "matrix(1, -10000, 10000, 1, 0, 0)",
+     "Test11: Skew with more infinite numbers");
 }
 
 // Verifies that aVal is +/- 0.00001 of aTrueVal
 // Returns true if so, false if not
 function verifyRounded(aVal, aTrueVal) {
   return (Math.abs(aVal - aTrueVal).toFixed(5) <= 0.00001);
 }
 </script>
--- a/layout/generic/crashtests/399412-1.html
+++ b/layout/generic/crashtests/399412-1.html
@@ -12,16 +12,17 @@
   height: 150px;
   border: 1px silver solid;
 }
 body {
   height: 60px;
   width: 300px;
   -moz-column-width: 50px;
   -moz-column-gap: 1px;
+  -moz-column-fill: auto;
 }
 </style>
 
 </head>
 
 <body onload="s=document.getElementById('s'); s.parentNode.removeChild(s);">
 
 <div class="container"><div class="overflow"></div></div>
--- a/layout/generic/crashtests/673770.html
+++ b/layout/generic/crashtests/673770.html
@@ -8,13 +8,13 @@
         document.body.style.height = "8px";
         document.documentElement.style.fontSize = "22050893469px";
         document.documentElement.offsetHeight;
         document.getElementById("x").style.counterReset = "chicken";
         document.documentElement.offsetHeight;
       }
     </script>
   </head>
-  <body style="-moz-column-width: 1px;" onload="boom();">
+  <body style="-moz-column-width: 1px; -moz-column-fill: auto;" onload="boom();">
     <hr size="100" color="blue"><div style="position: absolute;"></div><div id="x" style="height: 5px;"></div>
   </body>
 </html>
 
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -370,17 +370,17 @@ load 660451-1.html
 load 665853.html
 load text-overflow-form-elements.html
 load text-overflow-iframe.html
 load text-overflow-bug666751-1.html
 load text-overflow-bug666751-2.html
 asserts(0-1) load text-overflow-bug670564.xhtml
 load text-overflow-bug671796.xhtml
 load 667025.html
-asserts(14) asserts-if(Android,8) load 673770.html # bug 569193 and bug 459597
+asserts-if(Android,8) load 673770.html # bug 569193 and bug 459597
 load 679933-1.html
 load 682649-1.html
 load 683702-1.xhtml
 load 688996-1.html
 load 688996-2.html
 load 683712.html
 load text-overflow-bug713610.html
 load 700031.xhtml
--- a/layout/generic/nsColumnSetFrame.cpp
+++ b/layout/generic/nsColumnSetFrame.cpp
@@ -105,18 +105,23 @@ protected:
     nscoord mMaxHeight;
     // The sum of the "content heights" for all columns
     nscoord mSumHeight;
     // The "content height" of the last column
     nscoord mLastHeight;
     // The maximum "content height" of all columns that overflowed
     // their available height
     nscoord mMaxOverflowingHeight;
+    // Whether or not we should revert back to 'auto' setting for column-fill.
+    // This happens if we overflow our columns such that we no longer have
+    // enough room to keep balancing.
+    bool mShouldRevertToAuto;
     void Reset() {
       mMaxHeight = mSumHeight = mLastHeight = mMaxOverflowingHeight = 0;
+      mShouldRevertToAuto = false;
     }
   };
   
   /**
    * Similar to nsBlockFrame::DrainOverflowLines. Locate any columns not
    * handled by our prev-in-flow, and any columns sitting on our own
    * overflow list, and put them in our primary child list for reflowing.
    */
@@ -320,16 +325,18 @@ nsColumnSetFrame::ChooseColumnStrategy(c
   const nsStyleColumn* colStyle = GetStyleColumn();
   nscoord availContentWidth = GetAvailableContentWidth(aReflowState);
   if (aReflowState.ComputedWidth() != NS_INTRINSICSIZE) {
     availContentWidth = aReflowState.ComputedWidth();
   }
   nscoord colHeight = GetAvailableContentHeight(aReflowState);
   if (aReflowState.ComputedHeight() != NS_INTRINSICSIZE) {
     colHeight = aReflowState.ComputedHeight();
+  } else if (aReflowState.mComputedMaxHeight != NS_INTRINSICSIZE) {
+    colHeight = aReflowState.mComputedMaxHeight;
   }
 
   nscoord colGap = GetColumnGap(this, colStyle);
   PRInt32 numColumns = colStyle->mColumnCount;
 
   const PRUint32 MAX_NESTED_COLUMN_BALANCING = 2;
   PRUint32 cnt = 1;
   for (const nsHTMLReflowState* rs = aReflowState.parentReflowState; rs && cnt
@@ -389,27 +396,29 @@ nsColumnSetFrame::ChooseColumnStrategy(c
     // Compute extra space and divide it among the columns
     nscoord extraSpace =
       NS_MAX(0, availContentWidth - (colWidth*numColumns + colGap*(numColumns - 1)));
     nscoord extraToColumns = extraSpace/numColumns;
     colWidth += extraToColumns;
     expectedWidthLeftOver = extraSpace - (extraToColumns*numColumns);
   }
 
-  // NOTE that the non-balancing behavior for non-auto computed height
-  // is not in the CSS3 columns draft as of 18 January 2001
-  if (aReflowState.ComputedHeight() == NS_INTRINSICSIZE) {
+  // If column-fill is set to 'balance', then we want to balance the columns.
+  if (colStyle->mColumnFill == NS_STYLE_COLUMN_FILL_BALANCE) {
     // Balancing!
     if (numColumns <= 0) {
       // Hmm, auto column count, column width or available width is unknown,
       // and balancing is required. Let's just use one column then.
       numColumns = 1;
     }
-    colHeight = NS_MIN(mLastBalanceHeight, GetAvailableContentHeight(aReflowState));
+
+    colHeight = NS_MIN(mLastBalanceHeight,
+                       colHeight);
   } else {
+    // This is the case when the column-fill property is set to 'auto'.
     // No balancing, so don't limit the column count
     numColumns = PR_INT32_MAX;
   }
 
 #ifdef DEBUG_roc
   printf("*** nsColumnSetFrame::ChooseColumnStrategy: numColumns=%d, colWidth=%d, expectedWidthLeftOver=%d, colHeight=%d, colGap=%d\n",
          numColumns, colWidth, expectedWidthLeftOver, colHeight, colGap);
 #endif
@@ -729,30 +738,47 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
           kidNextInFlow->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
         }
       }
       else if (kidNextInFlow->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
         aStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
         reflowNext = true;
         kidNextInFlow->RemoveStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
       }
-        
+
+
+      if ((contentBottom > aReflowState.mComputedMaxHeight ||
+          contentBottom > aReflowState.ComputedHeight()) &&
+          aConfig.mBalanceColCount < PR_INT32_MAX) {
+        // We overflowed vertically, but have not exceeded the number
+        // of columns. If we're balancing, then we should try reverting
+        // to auto instead.
+        aColData.mShouldRevertToAuto = true;
+      }
+
       if (columnCount >= aConfig.mBalanceColCount) {
-        // No more columns allowed here. Stop.
-        aStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
-        kidNextInFlow->AddStateBits(NS_FRAME_IS_DIRTY);
-        
-        // Move any of our leftover columns to our overflow list. Our
-        // next-in-flow will eventually pick them up.
-        const nsFrameList& continuationColumns = mFrames.RemoveFramesAfter(child);
-        if (continuationColumns.NotEmpty()) {
-          SetOverflowFrames(PresContext(), continuationColumns);
+        if (contentBottom >= aReflowState.availableHeight) {
+          // No more columns allowed here. Stop.
+          aStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
+          kidNextInFlow->AddStateBits(NS_FRAME_IS_DIRTY);
+          // Move any of our leftover columns to our overflow list. Our
+          // next-in-flow will eventually pick them up.
+          const nsFrameList& continuationColumns = mFrames.RemoveFramesAfter(child);
+          if (continuationColumns.NotEmpty()) {
+            SetOverflowFrames(PresContext(), continuationColumns);
+          }
+          child = nsnull;
+          break;
+        } else if (contentBottom > aReflowState.mComputedMaxHeight ||
+                   contentBottom > aReflowState.ComputedHeight()) {
+          aColData.mShouldRevertToAuto = true;
+        } else {
+          // The number of columns required is too high.
+          allFit = false;
         }
-        child = nullptr;
-        break;
       }
     }
 
     if (PresContext()->HasPendingInterrupt()) {
       // Stop the loop now while |child| still points to the frame that bailed
       // out.  We could keep going here and condition a bunch of the code in
       // this loop on whether there's an interrupt, or even just keep going and
       // trying to reflow the blocks (even though we know they'll interrupt
@@ -912,164 +938,182 @@ nsColumnSetFrame::Reflow(nsPresContext* 
   // what the average column height should be, because we can measure
   // the heights of all the columns and sum them up. But don't do this
   // if we have a next in flow because we don't want to suck all its
   // content back here and then have to push it out again!
   nsIFrame* nextInFlow = GetNextInFlow();
   bool unboundedLastColumn = isBalancing && !nextInFlow;
   nsCollapsingMargin carriedOutBottomMargin;
   ColumnBalanceData colData;
-  bool feasible = ReflowChildren(aDesiredSize, aReflowState,
-    aStatus, config, unboundedLastColumn, &carriedOutBottomMargin, colData);
+  colData.mShouldRevertToAuto = false;
+
+  // This loop exists in order to try balancing initially. If the balancing
+  // overflows, then we want to revert to column-fill: auto.
+
+  // Our loop invariant is: colData.mShouldRevertToAuto is true if and only
+  // if we've reflowed our children, and during the most recent reflow of
+  // children, we were balancing and we overflowed in the block direction.
+  do {
+    if (colData.mShouldRevertToAuto) {
+      config = ChooseColumnStrategy(aReflowState);
+      isBalancing = false;
+      config.mBalanceColCount = PR_INT32_MAX;
+    }
 
-  if (isBalancing && !aPresContext->HasPendingInterrupt()) {
-    nscoord availableContentHeight = GetAvailableContentHeight(aReflowState);
-  
-    // Termination of the algorithm below is guaranteed because
-    // knownFeasibleHeight - knownInfeasibleHeight decreases in every
-    // iteration.
-    nscoord knownFeasibleHeight = NS_INTRINSICSIZE;
-    nscoord knownInfeasibleHeight = 0;
-    // We set this flag when we detect that we may contain a frame
-    // that can break anywhere (thus foiling the linear decrease-by-one
-    // search)
-    bool maybeContinuousBreakingDetected = false;
+    bool feasible = ReflowChildren(aDesiredSize, aReflowState,
+      aStatus, config, unboundedLastColumn, &carriedOutBottomMargin, colData);
+
+    if (isBalancing && !aPresContext->HasPendingInterrupt()) {
+      nscoord availableContentHeight = GetAvailableContentHeight(aReflowState);
 
-    while (!aPresContext->HasPendingInterrupt()) {
-      nscoord lastKnownFeasibleHeight = knownFeasibleHeight;
+      // Termination of the algorithm below is guaranteed because
+      // knownFeasibleHeight - knownInfeasibleHeight decreases in every
+      // iteration.
+      nscoord knownFeasibleHeight = NS_INTRINSICSIZE;
+      nscoord knownInfeasibleHeight = 0;
+      // We set this flag when we detect that we may contain a frame
+      // that can break anywhere (thus foiling the linear decrease-by-one
+      // search)
+      bool maybeContinuousBreakingDetected = false;
 
-      // Record what we learned from the last reflow
-      if (feasible) {
-        // maxHeight is feasible. Also, mLastBalanceHeight is feasible.
-        knownFeasibleHeight = NS_MIN(knownFeasibleHeight, colData.mMaxHeight);
-        knownFeasibleHeight = NS_MIN(knownFeasibleHeight, mLastBalanceHeight);
+      while (!aPresContext->HasPendingInterrupt()) {
+        nscoord lastKnownFeasibleHeight = knownFeasibleHeight;
+
+        // Record what we learned from the last reflow
+        if (feasible) {
+          // maxHeight is feasible. Also, mLastBalanceHeight is feasible.
+          knownFeasibleHeight = NS_MIN(knownFeasibleHeight, colData.mMaxHeight);
+          knownFeasibleHeight = NS_MIN(knownFeasibleHeight, mLastBalanceHeight);
 
-        // Furthermore, no height less than the height of the last
-        // column can ever be feasible. (We might be able to reduce the
-        // height of a non-last column by moving content to a later column,
-        // but we can't do that with the last column.)
-        if (mFrames.GetLength() == config.mBalanceColCount) {
+          // Furthermore, no height less than the height of the last
+          // column can ever be feasible. (We might be able to reduce the
+          // height of a non-last column by moving content to a later column,
+          // but we can't do that with the last column.)
+          if (mFrames.GetLength() == config.mBalanceColCount) {
+            knownInfeasibleHeight = NS_MAX(knownInfeasibleHeight,
+                                           colData.mLastHeight - 1);
+          }
+        } else {
+          knownInfeasibleHeight = NS_MAX(knownInfeasibleHeight, mLastBalanceHeight);
+          // If a column didn't fit in its available height, then its current
+          // height must be the minimum height for unbreakable content in
+          // the column, and therefore no smaller height can be feasible.
           knownInfeasibleHeight = NS_MAX(knownInfeasibleHeight,
-                                         colData.mLastHeight - 1);
+                                         colData.mMaxOverflowingHeight - 1);
+
+          if (unboundedLastColumn) {
+            // The last column is unbounded, so all content got reflowed, so the
+            // mColMaxHeight is feasible.
+            knownFeasibleHeight = NS_MIN(knownFeasibleHeight,
+                                         colData.mMaxHeight);
+          }
         }
-      } else {
-        knownInfeasibleHeight = NS_MAX(knownInfeasibleHeight, mLastBalanceHeight);
-        // If a column didn't fit in its available height, then its current
-        // height must be the minimum height for unbreakable content in
-        // the column, and therefore no smaller height can be feasible.
-        knownInfeasibleHeight = NS_MAX(knownInfeasibleHeight,
-                                       colData.mMaxOverflowingHeight - 1);
-
-        if (unboundedLastColumn) {
-          // The last column is unbounded, so all content got reflowed, so the
-          // mColMaxHeight is feasible.
-          knownFeasibleHeight = NS_MIN(knownFeasibleHeight,
-                                       colData.mMaxHeight);
-        }
-      }
 
 #ifdef DEBUG_roc
-      printf("*** nsColumnSetFrame::Reflow balancing knownInfeasible=%d knownFeasible=%d\n",
-             knownInfeasibleHeight, knownFeasibleHeight);
+        printf("*** nsColumnSetFrame::Reflow balancing knownInfeasible=%d knownFeasible=%d\n",
+               knownInfeasibleHeight, knownFeasibleHeight);
 #endif
 
-      if (knownInfeasibleHeight >= knownFeasibleHeight - 1) {
-        // knownFeasibleHeight is where we want to be
-        break;
-      }
+
+        if (knownInfeasibleHeight >= knownFeasibleHeight - 1) {
+          // knownFeasibleHeight is where we want to be
+          break;
+
+        }
+        if (knownInfeasibleHeight >= availableContentHeight) {
+          break;
+        }
+
+        if (lastKnownFeasibleHeight - knownFeasibleHeight == 1) {
+          // We decreased the feasible height by one twip only. This could
+          // indicate that there is a continuously breakable child frame
+          // that we are crawling through.
+          maybeContinuousBreakingDetected = true;
+        }
 
-      if (knownInfeasibleHeight >= availableContentHeight) {
-        break;
-      }
+        nscoord nextGuess = (knownFeasibleHeight + knownInfeasibleHeight)/2;
+        // The constant of 600 twips is arbitrary. It's about two line-heights.
+        if (knownFeasibleHeight - nextGuess < 600 &&
+            !maybeContinuousBreakingDetected) {
+          // We're close to our target, so just try shrinking just the
+          // minimum amount that will cause one of our columns to break
+          // differently.
+          nextGuess = knownFeasibleHeight - 1;
+        } else if (unboundedLastColumn) {
+          // Make a guess by dividing that into N columns. Add some slop
+          // to try to make it on the feasible side.  The constant of
+          // 600 twips is arbitrary. It's about two line-heights.
+          nextGuess = colData.mSumHeight/config.mBalanceColCount + 600;
+          // Sanitize it
+          nextGuess = clamped(nextGuess, knownInfeasibleHeight + 1,
+                                         knownFeasibleHeight - 1);
+        } else if (knownFeasibleHeight == NS_INTRINSICSIZE) {
+          // This can happen when we had a next-in-flow so we didn't
+          // want to do an unbounded height measuring step. Let's just increase
+          // from the infeasible height by some reasonable amount.
+          nextGuess = knownInfeasibleHeight*2 + 600;
+        }
+        // Don't bother guessing more than our height constraint.
+        nextGuess = NS_MIN(availableContentHeight, nextGuess);
 
-      if (lastKnownFeasibleHeight - knownFeasibleHeight == 1) {
-        // We decreased the feasible height by one twip only. This could
-        // indicate that there is a continuously breakable child frame
-        // that we are crawling through.
-        maybeContinuousBreakingDetected = true;
+#ifdef DEBUG_roc
+        printf("*** nsColumnSetFrame::Reflow balancing choosing next guess=%d\n", nextGuess);
+#endif
+
+        config.mColMaxHeight = nextGuess;
+
+        unboundedLastColumn = false;
+        AddStateBits(NS_FRAME_IS_DIRTY);
+        feasible = ReflowChildren(aDesiredSize, aReflowState,
+                                  aStatus, config, false,
+                                  &carriedOutBottomMargin, colData);
       }
 
-      nscoord nextGuess = (knownFeasibleHeight + knownInfeasibleHeight)/2;
-      // The constant of 600 twips is arbitrary. It's about two line-heights.
-      if (knownFeasibleHeight - nextGuess < 600 &&
-          !maybeContinuousBreakingDetected) {
-        // We're close to our target, so just try shrinking just the
-        // minimum amount that will cause one of our columns to break
-        // differently.
-        nextGuess = knownFeasibleHeight - 1;
-      } else if (unboundedLastColumn) {
-        // Make a guess by dividing that into N columns. Add some slop
-        // to try to make it on the feasible side.  The constant of
-        // 600 twips is arbitrary. It's about two line-heights.
-        nextGuess = colData.mSumHeight/config.mBalanceColCount + 600;
-        // Sanitize it
-        nextGuess = clamped(nextGuess, knownInfeasibleHeight + 1,
-                                       knownFeasibleHeight - 1);
-      } else if (knownFeasibleHeight == NS_INTRINSICSIZE) {
-        // This can happen when we had a next-in-flow so we didn't
-        // want to do an unbounded height measuring step. Let's just increase
-        // from the infeasible height by some reasonable amount.
-        nextGuess = knownInfeasibleHeight*2 + 600;
+      if (!feasible && !aPresContext->HasPendingInterrupt()) {
+        // We may need to reflow one more time at the feasible height to
+        // get a valid layout.
+        bool skip = false;
+        if (knownInfeasibleHeight >= availableContentHeight) {
+          config.mColMaxHeight = availableContentHeight;
+          if (mLastBalanceHeight == availableContentHeight) {
+            skip = true;
+          }
+        } else {
+          config.mColMaxHeight = knownFeasibleHeight;
+        }
+        if (!skip) {
+          // If our height is unconstrained, make sure that the last column is
+          // allowed to have arbitrary height here, even though we were balancing.
+          // Otherwise we'd have to split, and it's not clear what we'd do with
+          // that.
+          AddStateBits(NS_FRAME_IS_DIRTY);
+          ReflowChildren(aDesiredSize, aReflowState, aStatus, config,
+                         availableContentHeight == NS_UNCONSTRAINEDSIZE,
+                         &carriedOutBottomMargin, colData);
+        }
       }
-      // Don't bother guessing more than our height constraint.
-      nextGuess = NS_MIN(availableContentHeight, nextGuess);
-
-#ifdef DEBUG_roc
-      printf("*** nsColumnSetFrame::Reflow balancing choosing next guess=%d\n", nextGuess);
-#endif
-
-      config.mColMaxHeight = nextGuess;
-      
-      unboundedLastColumn = false;
-      AddStateBits(NS_FRAME_IS_DIRTY);
-      feasible = ReflowChildren(aDesiredSize, aReflowState,
-                                aStatus, config, false, 
-                                &carriedOutBottomMargin, colData);
     }
 
-    if (!feasible && !aPresContext->HasPendingInterrupt()) {
-      // We may need to reflow one more time at the feasible height to
-      // get a valid layout.
-      bool skip = false;
-      if (knownInfeasibleHeight >= availableContentHeight) {
-        config.mColMaxHeight = availableContentHeight;
-        if (mLastBalanceHeight == availableContentHeight) {
-          skip = true;
-        }
-      } else {
-        config.mColMaxHeight = knownFeasibleHeight;
-      }
-      if (!skip) {
-        // If our height is unconstrained, make sure that the last column is
-        // allowed to have arbitrary height here, even though we were balancing.
-        // Otherwise we'd have to split, and it's not clear what we'd do with
-        // that.
-        AddStateBits(NS_FRAME_IS_DIRTY);
-        ReflowChildren(aDesiredSize, aReflowState, aStatus, config,
-                       availableContentHeight == NS_UNCONSTRAINEDSIZE,
-                       &carriedOutBottomMargin, colData);
-      }
+ } while (colData.mShouldRevertToAuto);
+
+    if (aPresContext->HasPendingInterrupt() &&
+        aReflowState.availableHeight == NS_UNCONSTRAINEDSIZE) {
+      // In this situation, we might be lying about our reflow status, because
+      // our last kid (the one that got interrupted) was incomplete.  Fix that.
+      aStatus = NS_FRAME_COMPLETE;
     }
-  }
+
+    CheckInvalidateSizeChange(aDesiredSize);
 
-  if (aPresContext->HasPendingInterrupt() &&
-      aReflowState.availableHeight == NS_UNCONSTRAINEDSIZE) {
-    // In this situation, we might be lying about our reflow status, because
-    // our last kid (the one that got interrupted) was incomplete.  Fix that.
-    aStatus = NS_FRAME_COMPLETE;
-  }
-  
-  CheckInvalidateSizeChange(aDesiredSize);
+    // XXXjwir3: This call should be replaced with FinishWithAbsoluteFrames
+    //           when bug 724978 is fixed and nsColumnSetFrame is a full absolute
+    //           container.
+    FinishAndStoreOverflow(&aDesiredSize);
 
-  // XXXjwir3: This call should be replaced with FinishWithAbsoluteFrames
-  //           when bug 724978 is fixed and nsColumnSetFrame is a full absolute
-  //           container.
-  FinishAndStoreOverflow(&aDesiredSize);
-
-  aDesiredSize.mCarriedOutBottomMargin = carriedOutBottomMargin;
+    aDesiredSize.mCarriedOutBottomMargin = carriedOutBottomMargin;
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
 
   NS_ASSERTION(NS_FRAME_IS_FULLY_COMPLETE(aStatus) ||
                aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE,
                "Column set should be complete if the available height is unconstrained");
 
   return NS_OK;
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -87,16 +87,18 @@
 #include "nsDeckFrame.h"
 #include "nsTableFrame.h"
 
 #include "gfxContext.h"
 #include "nsRenderingContext.h"
 #include "CSSCalc.h"
 #include "nsAbsoluteContainingBlock.h"
 #include "nsFontInflationData.h"
+#include "nsAnimationManager.h"
+#include "nsTransitionManager.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/LookAndFeel.h"
 
 using namespace mozilla;
 using namespace mozilla::layers;
 using namespace mozilla::layout;
 
@@ -930,19 +932,30 @@ nsRect
 nsIFrame::GetPaddingRect() const
 {
   return GetPaddingRectRelativeToSelf() + GetPosition();
 }
 
 bool
 nsIFrame::IsTransformed() const
 {
-  return (mState & NS_FRAME_MAY_BE_TRANSFORMED) &&
+  return ((mState & NS_FRAME_MAY_BE_TRANSFORMED) &&
           (GetStyleDisplay()->HasTransform() ||
-           IsSVGTransformed());
+           IsSVGTransformed() ||
+           (mContent &&
+            nsLayoutUtils::HasAnimationsForCompositor(mContent,
+                                                      eCSSProperty_transform))));
+}
+
+bool
+nsIFrame::HasOpacity() const
+{
+  return GetStyleDisplay()->mOpacity < 1.0f || (mContent &&
+           nsLayoutUtils::HasAnimationsForCompositor(mContent,
+                                                     eCSSProperty_opacity));
 }
 
 bool
 nsIFrame::IsSVGTransformed(gfxMatrix *aOwnTransforms,
                            gfxMatrix *aFromParentTransforms) const
 {
   return false;
 }
@@ -1759,34 +1772,37 @@ nsIFrame::BuildDisplayListForStackingCon
   // Replaced elements have their visibility handled here, because
   // they're visually atomic
   if (IsFrameOfType(eReplaced) && !IsVisibleForPainting(aBuilder))
     return NS_OK;
 
   nsRect clipPropClip;
   const nsStyleDisplay* disp = GetStyleDisplay();
   // We can stop right away if this is a zero-opacity stacking context and
-  // we're painting.
-  if (disp->mOpacity == 0.0 && aBuilder->IsForPainting())
+  // we're painting, and we're not animating opacity.
+  if (disp->mOpacity == 0.0 && aBuilder->IsForPainting() &&
+      !nsLayoutUtils::HasAnimationsForCompositor(mContent,
+                                                 eCSSProperty_opacity)) {
     return NS_OK;
+  }
 
   bool applyClipPropClipping =
       ApplyClipPropClipping(aBuilder, disp, this, &clipPropClip);
   nsRect dirtyRect = aDirtyRect;
 
   bool inTransform = aBuilder->IsInTransform();
   if (IsTransformed()) {
     if (aBuilder->IsForPainting() &&
         nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder, this)) {
       dirtyRect = GetVisualOverflowRectRelativeToSelf();
     } else {
       // Trying to  back-transform arbitrary rects gives us really weird results. I believe 
       // this is from points that lie beyond the vanishing point. As a workaround we transform t
       // he overflow rect into screen space and compare in that coordinate system.
-        
+
       // Transform the overflow rect into screen space
       nsRect overflow = GetVisualOverflowRectRelativeToSelf();
       nsPoint offset = aBuilder->ToReferenceFrame(this);
       overflow += offset;
       overflow = nsDisplayTransform::TransformRect(overflow, this, offset);
 
       dirtyRect += offset;
 
@@ -1906,33 +1922,32 @@ nsIFrame::BuildDisplayListForStackingCon
       (!resultList.IsEmpty() || usingSVGEffects)) {
     nsDisplayClipPropWrapper wrapper(clipPropClip);
     nsDisplayItem* item = wrapper.WrapList(aBuilder, this, &resultList);
     if (!item)
       return NS_ERROR_OUT_OF_MEMORY;
     // resultList was emptied
     resultList.AppendToTop(item);
   }
-
   /* If there are any SVG effects, wrap the list up in an SVG effects item
    * (which also handles CSS group opacity). Note that we create an SVG effects
    * item even if resultList is empty, since a filter can produce graphical
    * output even if the element being filtered wouldn't otherwise do so.
    */
   if (usingSVGEffects) {
     /* List now emptied, so add the new list to the top. */
     rv = resultList.AppendNewToTop(
         new (aBuilder) nsDisplaySVGEffects(aBuilder, this, &resultList));
     if (NS_FAILED(rv))
       return rv;
   }
   /* Else, if the list is non-empty and there is CSS group opacity without SVG
    * effects, wrap it up in an opacity item.
    */
-  else if (disp->mOpacity < 1.0f &&
+  else if (HasOpacity() &&
            !nsSVGUtils::CanOptimizeOpacity(this) &&
            !resultList.IsEmpty()) {
     rv = resultList.AppendNewToTop(
         new (aBuilder) nsDisplayOpacity(aBuilder, this, &resultList));
     if (NS_FAILED(rv))
       return rv;
   }
 
@@ -2076,17 +2091,17 @@ nsIFrame::BuildDisplayListForChild(nsDis
   // Don't paint our children if the theme object is a leaf.
   if (IsThemed(ourDisp) &&
       !PresContext()->GetTheme()->WidgetIsContainer(ourDisp->mAppearance))
     return NS_OK;
 
   // Child is composited if it's transformed, partially transparent, or has
   // SVG effects.
   const nsStyleDisplay* disp = child->GetStyleDisplay();
-  bool isVisuallyAtomic = disp->mOpacity != 1.0f
+  bool isVisuallyAtomic = child->HasOpacity()
     || child->IsTransformed()
     || nsSVGIntegrationUtils::UsingEffectsForFrame(child);
 
   bool isPositioned = !isSVG && disp->IsPositioned();
   if (isVisuallyAtomic || isPositioned || (!isSVG && disp->IsFloating()) ||
       ((disp->mClipFlags & NS_STYLE_CLIP_RECT) &&
        IsSVGContentWithCSSClip(child)) ||
       (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) {
@@ -3005,16 +3020,20 @@ HandleFrameSelection(nsFrameSelection*  
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsFrame::HandleRelease(nsPresContext* aPresContext,
                                      nsGUIEvent*    aEvent,
                                      nsEventStatus* aEventStatus)
 {
+  if (aEvent->eventStructType != NS_MOUSE_EVENT) {
+    return NS_OK;
+  }
+
   nsIFrame* activeFrame = GetActiveSelectionFrame(aPresContext, this);
 
   nsCOMPtr<nsIContent> captureContent = nsIPresShell::GetCapturingContent();
 
   // We can unconditionally stop capturing because
   // we should never be capturing when the mouse button is up
   nsIPresShell::SetCapturingContent(nullptr, 0);
 
@@ -4740,34 +4759,34 @@ nsIFrame::GetTransformMatrix(nsIFrame* a
    * transform/translate matrix that will apply our current transform, then
    * shift us to our parent.
    */
   if (IsTransformed()) {
     /* Compute the delta to the parent, which we need because we are converting
      * coordinates to our parent.
      */
     NS_ASSERTION(nsLayoutUtils::GetCrossDocParentFrame(this),
-	             "Cannot transform the viewport frame!");
+                 "Cannot transform the viewport frame!");
     PRInt32 scaleFactor = PresContext()->AppUnitsPerDevPixel();
 
     gfx3DMatrix result =
-      nsDisplayTransform::GetResultingTransformMatrix(this, nsPoint(0, 0),
-                                                      scaleFactor, nullptr, aOutAncestor);
+      nsDisplayTransform::GetResultingTransformMatrix(this, nsPoint(0, 0), scaleFactor, nullptr,
+                                                      nullptr, nullptr, nullptr, nullptr, aOutAncestor);
     // XXXjwatt: seems like this will double count offsets in the face of preserve-3d:
     nsPoint delta = GetOffsetToCrossDoc(*aOutAncestor);
     /* Combine the raw transform with a translation to our parent. */
     result *= gfx3DMatrix::Translation
       (NSAppUnitsToFloatPixels(delta.x, scaleFactor),
        NSAppUnitsToFloatPixels(delta.y, scaleFactor),
        0.0f);
     return result;
   }
-  
+
   *aOutAncestor = nsLayoutUtils::GetCrossDocParentFrame(this);
-  
+
   /* Otherwise, we're not transformed.  In that case, we'll walk up the frame
    * tree until we either hit the root frame or something that may be
    * transformed.  We'll then change coordinates into that frame, since we're
    * guaranteed that nothing in-between can be transformed.  First, however,
    * we have to check to see if we have a parent.  If not, we'll set the
    * outparam to null (indicating that there's nothing left) and will hand back
    * the identity matrix.
    */
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1222,16 +1222,18 @@ public:
   virtual bool NeedsView() { return false; }
 
   /**
    * Returns true if this frame is transformed (e.g. has CSS or SVG transforms)
    * or if its parent is an SVG frame that has children-only transforms (e.g.
    * an SVG viewBox attribute).
    */
   bool IsTransformed() const;
+  
+  bool HasOpacity() const;
 
   /**
    * Returns true if this frame is an SVG frame that has SVG transforms applied
    * to it, or if its parent frame is an SVG frame that has children-only
    * transforms (e.g. an SVG viewBox attribute).
    * If aOwnTransforms is non-null and the frame has its own SVG transforms,
    * aOwnTransforms will be set to these transforms. If aFromParentTransforms
    * is non-null and the frame has an SVG parent with children-only transforms,
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -113,17 +113,17 @@
 #include <errno.h>
 
 #include "nsContentCID.h"
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 #ifdef XP_MACOSX
 #include "gfxQuartzNativeDrawing.h"
 #include "nsPluginUtilsOSX.h"
-#include "nsCoreAnimationSupport.h"
+#include "mozilla/gfx/QuartzSupport.h"
 #endif
 
 #ifdef MOZ_WIDGET_GTK2
 #include <gdk/gdk.h>
 #include <gdk/gdkx.h>
 #include <gtk/gtk.h>
 #include "gfxXlibNativeRenderer.h"
 #endif
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -240,16 +240,17 @@ TransformShadowTree(nsDisplayListBuilder
                     nsIFrame* aFrame, Layer* aLayer,
                     const ViewTransform& aTransform,
                     float aTempScaleDiffX = 1.0,
                     float aTempScaleDiffY = 1.0)
 {
   ShadowLayer* shadow = aLayer->AsShadowLayer();
   shadow->SetShadowClipRect(aLayer->GetClipRect());
   shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
+  shadow->SetShadowOpacity(aLayer->GetOpacity());
 
   const FrameMetrics* metrics = GetFrameMetrics(aLayer);
 
   gfx3DMatrix shadowTransform = aLayer->GetBaseTransform();
   ViewTransform layerTransform = aTransform;
 
   if (metrics && metrics->IsScrollable()) {
     const ViewID scrollId = metrics->mScrollId;
--- a/layout/reftests/bugs/368020-1-ref.html
+++ b/layout/reftests/bugs/368020-1-ref.html
@@ -1,16 +1,16 @@
 <!DOCTYPE HTML>
 <html>
 <head>
 <title>Testcase, bug 368020</title>
 </head>
 <body>
 
-<div style="-moz-column-count: 2; column-count: 2; height: 4.5em; background:yellow">
+<div style="-moz-column-count: 2; column-count: 2; -moz-column-fill: auto; height: 4.5em; background:yellow">
 
   <div style="margin: 7px 1% 2px 2em; border: medium dotted; border-width: 2px 3px 4px 5px;">
     <div style="background: url(repeatable-diagonal-gradient.png);">
       <div style="padding: 8px 6px 4px 2px;">
         blah<br>
         blah<br>
         blah<br>
         blah
--- a/layout/reftests/bugs/368020-1.html
+++ b/layout/reftests/bugs/368020-1.html
@@ -1,16 +1,16 @@
 <!DOCTYPE HTML>
 <html>
 <head>
 <title>Testcase, bug 368020</title>
 </head>
 <body>
 
-<div style="-moz-column-count: 2; column-count: 2; height: 4.5em; background:yellow">
+<div style="-moz-column-count: 2; column-count: 2; -moz-column-fill: auto; height: 4.5em; background:yellow">
 
   <div>
     <div style="background: url(repeatable-diagonal-gradient.png); background-clip: padding-box; background-clip: padding; background-origin: padding-box; background-origin: padding; margin: 7px 1% 2px 2em; border: medium dotted; border-width: 2px 3px 4px 5px; padding: 8px 6px 4px 2px;">
       <div>
         blah<br>
         blah<br>
         blah<br>
         blah
--- a/layout/reftests/bugs/379349-2-ref.xhtml
+++ b/layout/reftests/bugs/379349-2-ref.xhtml
@@ -36,16 +36,17 @@
       width: 200pt;
       border-bottom: 4px solid blue;
     }
     body {
       height: 2.5in;
       width: 300pt;
       -moz-column-width: 100pt;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: solid gray;
       position: relative;
     }
   </style>
  </head>
  <body>
   <div class="overflow">
   </div>
--- a/layout/reftests/bugs/379349-2a.xhtml
+++ b/layout/reftests/bugs/379349-2a.xhtml
@@ -43,16 +43,17 @@
       height: 800%;
       border-bottom-color: blue;
     }
     body {
       height: 2.5in;
       width: 300pt;
       -moz-column-width: 100pt;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: solid gray;
     }
   </style>
  </head>
  <body>
   <div class="container no1">
     <div class="overflow">
     </div>
--- a/layout/reftests/bugs/379349-2b.xhtml
+++ b/layout/reftests/bugs/379349-2b.xhtml
@@ -43,16 +43,17 @@
       height: 800%;
       border-bottom-color: blue;
     }
     body {
       height: 2.5in;
       width: 300pt;
       -moz-column-width: 100pt;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: solid gray;
     }
   </style>
  </head>
  <body onload="document.getElementById('tester1').style.height = '9in';
                document.getElementById('tester1').offsetHeight;
                document.getElementById('tester2').style.height = '29in';
                document.getElementById('tester2').offsetHeight;
--- a/layout/reftests/bugs/563584-9c.html
+++ b/layout/reftests/bugs/563584-9c.html
@@ -1,11 +1,11 @@
 <!DOCTYPE HTML>
 <title>Test for pushing of floats to next column when float breaking in columns is disabled</title>
-<body style="-moz-column-width: 200px; margin: 0; -moz-column-gap: 0; height: 200px;">
+<body style="-moz-column-width: 200px; -moz-column-fill: auto; margin: 0; -moz-column-gap: 0; height: 200px;">
 <div style="float: left;">
   <div style="display: inline-block; vertical-align: top; height: 150px; width: 200px; background: yellow"></div>
 </div>
 <div style="float: left;">
   <div style="display: inline-block; vertical-align: top; height: 150px; width: 200px; background: aqua"></div>
 </div>
 <div style="float: left;">
   <div style="display: inline-block; vertical-align: top; height: 150px; width: 200px; background: fuchsia"></div>
--- a/layout/reftests/bugs/563584-9d.html
+++ b/layout/reftests/bugs/563584-9d.html
@@ -1,11 +1,11 @@
 <!DOCTYPE HTML>
 <title>Test for pushing of floats to next column when float breaking in columns is disabled</title>
-<body style="-moz-column-width: 200px; margin: 0; -moz-column-gap: 0; height: 200px;">
+<body style="-moz-column-width: 200px; margin: 0; -moz-column-fill: auto; -moz-column-gap: 0; height: 200px;">
 <div style="float: left;">
   <div style="display: inline-block; vertical-align: top; height: 150px; width: 200px; background: yellow"></div>
 </div>
 <div>&nbsp;</div>
 <div style="float: left;">
   <div style="display: inline-block; vertical-align: top; height: 150px; width: 200px; background: aqua"></div>
 </div>
 <div>&nbsp;</div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/columns/ahem.css
@@ -0,0 +1,4 @@
+@font-face {
+  font-family: "Ahem";
+  src: url(../fonts/Ahem.ttf);
+}
new file mode 100644
--- /dev/null
+++ b/layout/reftests/columns/columnfill-auto-ref.html
@@ -0,0 +1,32 @@
+<html>
+<head>
+  <link rel="stylesheet" type="text/css" href="ahem.css" />
+
+  <style>
+    td.text {
+      width: 200px;
+      text-align: left;
+      font-family: ahem;
+      font-size: 12pt;
+      line-height: 1.1;
+    }
+
+    table {
+      width: 100%;
+      font-family: ahem;
+      font-size: 12pt;
+      line-height: 1.1;
+    }
+  </style>
+</head>
+
+<body>
+  <table cellpadding=0 cellspacing=0>
+    <tr>
+      <td class="text" valign="top">
+        Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed feugiat libero vel diam.</td>
+      <td class="text" valign="top">Pellentesque pulvinar commodo lacus. Sed fringilla. Sed lectus. Praesent laoreet orci</td>
+      <td valign="top" class="text">vitae nisi. Duis venenatis tristique massa. Sed commodo diam at mauris.</td>
+    </tr>
+  </table>
+</body>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/columns/columnfill-auto.html
@@ -0,0 +1,19 @@
+<html>
+  <head>
+    <link rel="stylesheet" type="text/css" href="ahem.css" />
+  </head>
+
+  <body>
+    <div style="width: 100%">
+    <div style="-moz-column-width: 200px;
+                -moz-column-gap: 0px;
+                -moz-column-fill: auto;
+                height: 120px;
+                font-family: ahem;
+                font-size: 12pt;
+		line-height: 1.1;">
+      Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed feugiat libero vel diam. Pellentesque pulvinar commodo lacus. Sed fringilla. Sed lectus. Praesent laoreet orci vitae nisi. Duis venenatis tristique massa. Sed commodo diam at mauris.
+    </div>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/columns/columnfill-balance-ref.html
@@ -0,0 +1,33 @@
+<html>
+  <head>
+    <link rel="stylesheet" type="text/css" href="ahem.css" />
+
+    <style>
+      td {
+        width: 200px;
+        font-family: ahem;
+      }
+
+      table {
+        width: 100%;
+        height: 150px;
+        padding-bottom: 0;
+        margin-bottom: 0;
+        font-family: ahem;
+      }
+    </style>
+  </head>
+  <body>
+    <table cellpadding=0 cellspacing=0>
+      <tr>
+        <td valign="top">
+          Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed feugiat libero vel diam.
+        </td>
+        <td valign="top">Pellentesque pulvinar commodo lacus. Sed fringilla. Sed lectus. Praesent laoreet orci
+        </td>
+        <td valign="top">vitae nisi. Duis venenatis tristique massa. Sed commodo diam at mauris.
+        </td>
+      </tr>
+    </table>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/columns/columnfill-balance.html
@@ -0,0 +1,16 @@
+<html>
+  <head>
+      <link rel="stylesheet" type="text/css" href="ahem.css" />
+  </head>
+  <body>
+    <div style="-moz-column-width: 200px;
+                -moz-column-gap: 0px;
+                -moz-column-fill: balance;
+                height: 150px;
+                margin-bottom: 0;
+                padding-bottom: 0;
+                font-family: ahem;">
+      Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed feugiat libero vel diam. Pellentesque pulvinar commodo lacus. Sed fringilla. Sed lectus. Praesent laoreet orci vitae nisi. Duis venenatis tristique massa. Sed commodo diam at mauris.
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/columns/columnfill-overflow-ref.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <style type="text/css">
+      div.container {
+        width:54em;
+        background-color: gray;
+      }
+
+      div.multicolumn {
+        height: 5em;
+        overflow: visible;
+
+        column-width:15em;
+        column-gap: 2em;
+        column-rule: 4px solid green;
+        column-fill: auto;
+
+        -moz-column-width:15em;
+        -moz-column-gap: 2em;
+        -moz-column-rule: 4px solid green;
+        -moz-column-fill: auto;
+
+        padding: 5px;
+      }
+
+      p {
+        margin: 0;
+        padding: 0
+      }
+    </style>
+  </head>
+  <body>
+    <div class="container">
+      <div class="multicolumn">
+        <p>Ab cde fgh i jkl. Mnopqr stu vw xyz. A bcdef g hij klm nopqrstuv wxy z. Abc de fghi jklmno. Pqrstu vwx yz. Abc def ghi jkl.M nop qrst uv wx yz. Ab cde fgh i jkl. Mnopqr stu vw xyz. A bcdef g hij klm nopqrstuv wxy z. Abc de fghi jklmno. Pqrstu vwx yz. Abc def ghi jkl.M nop qrst uv wx yz. Ab cde fgh i jkl. Mnopqr stu vw xyz. A bcdef g hij klm nopqrstuv wxy z. Abc de fghi jklmno. Pqrstu vwx yz. Abc def ghi jkl.M nop qrst uv wx yz. Ab cde fgh i jkl. Mnopqr stu vw xyz. A bcdef g hij klm nopqrstuv wxy z. Abc de fghi jklmno. Pqrstu vwx yz. Abc def ghi jkl.M nop qrst uv wx yz. Ab cde fgh i jkl. Mnopqr stu vw xyz. A bcdef g hij klm nopqrstuv wxy z. Abc de fghi jklmno. Pqrstu vwx yz. Abc def ghi jkl.M nop qrst uv wx yz. Ab cde fgh i jkl. Mnopqr stu vw xyz. A bcdef g hij klm nopqrstuv wxy z. Abc de fghi jklmno. Pqrstu vwx yz. Abc def ghi jkl.M nop qrst uv wx yz. Ab cde fgh i jkl. Mnopqr stu vw xyz. A bcdef g hij klm nopqrstuv wxy z. Abc de fghi jklmno. Pqrstu vwx yz. Abc def ghi jkl.M nop qrst uv wx yz. </p>
+      </div>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/columns/columnfill-overflow.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <style type="text/css">
+      div.container {
+        width:54em;
+        background-color: gray;
+      }
+
+      div.multicolumn {
+        height: 5em;
+        overflow: visible;
+
+        column-width:15em;
+        column-gap: 2em;
+        column-rule: 4px solid green;
+        column-fill: balance;
+
+        -moz-column-width:15em;
+        -moz-column-gap: 2em;
+        -moz-column-rule: 4px solid green;
+        -moz-column-fill: balance;
+
+        padding: 5px;
+      }
+
+      p {
+        margin: 0;
+        padding: 0
+      }
+    </style>
+  </head>
+  <body>
+    <div class="container">
+      <div class="multicolumn">
+        <p>Ab cde fgh i jkl. Mnopqr stu vw xyz. A bcdef g hij klm nopqrstuv wxy z. Abc de fghi jklmno. Pqrstu vwx yz. Abc def ghi jkl.M nop qrst uv wx yz. Ab cde fgh i jkl. Mnopqr stu vw xyz. A bcdef g hij klm nopqrstuv wxy z. Abc de fghi jklmno. Pqrstu vwx yz. Abc def ghi jkl.M nop qrst uv wx yz. Ab cde fgh i jkl. Mnopqr stu vw xyz. A bcdef g hij klm nopqrstuv wxy z. Abc de fghi jklmno. Pqrstu vwx yz. Abc def ghi jkl.M nop qrst uv wx yz. Ab cde fgh i jkl. Mnopqr stu vw xyz. A bcdef g hij klm nopqrstuv wxy z. Abc de fghi jklmno. Pqrstu vwx yz. Abc def ghi jkl.M nop qrst uv wx yz. Ab cde fgh i jkl. Mnopqr stu vw xyz. A bcdef g hij klm nopqrstuv wxy z. Abc de fghi jklmno. Pqrstu vwx yz. Abc def ghi jkl.M nop qrst uv wx yz. Ab cde fgh i jkl. Mnopqr stu vw xyz. A bcdef g hij klm nopqrstuv wxy z. Abc de fghi jklmno. Pqrstu vwx yz. Abc def ghi jkl.M nop qrst uv wx yz. Ab cde fgh i jkl. Mnopqr stu vw xyz. A bcdef g hij klm nopqrstuv wxy z. Abc de fghi jklmno. Pqrstu vwx yz. Abc def ghi jkl.M nop qrst uv wx yz. </p>
+      </div>
+    </div>
+  </body>
+</html>
--- a/layout/reftests/columns/reftest.list
+++ b/layout/reftests/columns/reftest.list
@@ -11,14 +11,17 @@
 == column-balancing-overflow-003.html column-balancing-overflow-003.ref.html
 == column-balancing-overflow-004.html column-balancing-overflow-004.ref.html
 == column-balancing-overflow-005.html column-balancing-overflow-005.ref.html
 == column-balancing-000.html column-balancing-000.ref.html
 == column-balancing-001.html column-balancing-000.ref.html
 == column-balancing-002.html column-balancing-002.ref.html
 == column-balancing-003.html column-balancing-000.ref.html
 == column-balancing-004.html column-balancing-004.ref.html
+HTTP(..) == columnfill-balance.html columnfill-balance-ref.html
+HTTP(..) == columnfill-auto.html columnfill-auto-ref.html
 == columnrule-basic.html columnrule-basic-ref.html
 == columnrule-complex.html columnrule-complex-ref.html
 != columnrule-linestyles.html columnrule-linestyles-notref.html
 == columnrule-padding.html columnrule-padding-ref.html
+== columnfill-overflow.html columnfill-overflow-ref.html
 == margin-collapsing-bug616722-1.html margin-collapsing-bug616722-1-ref.html
 == margin-collapsing-bug616722-2.html margin-collapsing-bug616722-2-ref.html
--- a/layout/reftests/pagination/abspos-overflow-01-cols.xhtml
+++ b/layout/reftests/pagination/abspos-overflow-01-cols.xhtml
@@ -29,16 +29,17 @@
       background: white;
       width: 100pt;
     }
     #colset {
       width: 300pt;
       height: 2in;
       -moz-column-count: 3;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: silver 2pt;
       border-style: none solid;
     }
     #redline {
       width: 303pt;
       border-top: 4px solid red;
       margin-top: -1in;
       position: relative;
--- a/layout/reftests/pagination/border-breaking-000-cols.xhtml
+++ b/layout/reftests/pagination/border-breaking-000-cols.xhtml
@@ -20,16 +20,17 @@
       height: 200px;
     }
 
     body {
       height: 200px;
       width: 300px;
       -moz-column-width: 150px;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: solid silver;
       border-style: none solid;
     }
   </style>
  </head>
  <body>
   <div class="container">
     <div class="box">
--- a/layout/reftests/pagination/border-breaking-001-cols.ref.xhtml
+++ b/layout/reftests/pagination/border-breaking-001-cols.ref.xhtml
@@ -15,16 +15,17 @@
       height: 500px;
     }
 
     .body {
       height: 200px;
       width: 300px;
       -moz-column-width: 100px;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: solid silver;
       border-style: none solid;
       background: yellow;
     }
   </style>
  </head>
  <body>
   <div class="body">
--- a/layout/reftests/pagination/border-breaking-001-cols.xhtml
+++ b/layout/reftests/pagination/border-breaking-001-cols.xhtml
@@ -44,16 +44,17 @@
       height: 100px;
     }
 
     body {
       height: 200px;
       width: 300px;
       -moz-column-width: 100px;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: solid silver;
       border-style: none solid;
     }
   </style>
  </head>
  <body>
   <div class="abs">
     <div class="container">
--- a/layout/reftests/pagination/border-breaking-002-cols.ref.xhtml
+++ b/layout/reftests/pagination/border-breaking-002-cols.ref.xhtml
@@ -11,16 +11,17 @@
       border-top: solid 10px aqua;
     }
 
     .multicol {
       height: 200px;
       width: 300px;
       -moz-column-width: 150px;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: solid silver;
     }
   </style>
  </head>
  <body>
   There must be a continuous 10px line at the top
   of the gray box, the left half blue and the right
   half aqua.
--- a/layout/reftests/pagination/border-breaking-002-cols.xhtml
+++ b/layout/reftests/pagination/border-breaking-002-cols.xhtml
@@ -12,16 +12,17 @@
       border-bottom: solid 10px aqua;
     }
 
     .multicol {
       height: 200px;
       width: 300px;
       -moz-column-width: 150px;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: solid silver;
     }
   </style>
  </head>
  <body>
   There must be a continuous 10px line at the top
   of the gray box, the left half blue and the right
   half aqua.
--- a/layout/reftests/pagination/border-breaking-003-cols.xhtml
+++ b/layout/reftests/pagination/border-breaking-003-cols.xhtml
@@ -15,16 +15,17 @@
       border-bottom: 10px solid aqua;
     }
 
     .multicol {
       height: 200px;
       width: 300px;
       -moz-column-width: 150px;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: solid silver;
     }
   </style>
  </head>
  <body>
   There must be two continuous 10px lines at the top
   of the gray box, the top one blue and the bottom one
   aqua.
--- a/layout/reftests/pagination/content-inserted-002.ref.xhtml
+++ b/layout/reftests/pagination/content-inserted-002.ref.xhtml
@@ -8,16 +8,17 @@
       font-size: 16px;
     }
 
     #colset {
       height: 200px;
       width: 450px;
       -moz-column-width: 150px;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: 3px solid silver;
     }
 
     #mark {
       border-bottom: 4px solid blue;
     }
 
     #shift {
--- a/layout/reftests/pagination/content-inserted-002.xhtml
+++ b/layout/reftests/pagination/content-inserted-002.xhtml
@@ -8,16 +8,17 @@
       font-size: 16px;
     }
 
     #colset {
       height: 200px;
       width: 450px;
       -moz-column-width: 150px;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: 3px solid silver;
     }
 
     #x {
       height: 500px;
     }
 
     #x:after {
--- a/layout/reftests/pagination/content-inserted-003.xhtml
+++ b/layout/reftests/pagination/content-inserted-003.xhtml
@@ -8,16 +8,17 @@
       font-size: 16px;
     }
 
     #colset {
       height: 200px;
       width: 450px;
       -moz-column-width: 150px;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: 3px solid silver;
     }
 
     #x {
       height: 500px;
     }
 
     #x:after {
--- a/layout/reftests/pagination/content-inserted-004.xhtml
+++ b/layout/reftests/pagination/content-inserted-004.xhtml
@@ -8,16 +8,17 @@
       font-size: 16px;
     }
 
     #colset {
       height: 200px;
       width: 450px;
       -moz-column-width: 150px;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: 3px solid silver;
     }
 
     #x {
       height: 500px;
     }
 
     #x:before {
--- a/layout/reftests/pagination/content-inserted-005.xhtml
+++ b/layout/reftests/pagination/content-inserted-005.xhtml
@@ -8,16 +8,17 @@
       font-size: 16px;
     }
 
     #colset {
       height: 200px;
       width: 450px;
       -moz-column-width: 150px;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: 3px solid silver;
     }
 
     #x {
       border-bottom: 4px solid blue;
     }
 
     #x:before {
--- a/layout/reftests/pagination/content-inserted-006.xhtml
+++ b/layout/reftests/pagination/content-inserted-006.xhtml
@@ -8,16 +8,17 @@
       font-size: 16px;
     }
 
     #colset {
       height: 200px;
       width: 450px;
       -moz-column-width: 150px;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: 3px solid silver;
     }
 
     #x {
       height: 500px;
     }
 
     #x:after {
--- a/layout/reftests/pagination/content-inserted-007.xhtml
+++ b/layout/reftests/pagination/content-inserted-007.xhtml
@@ -8,16 +8,17 @@
       font-size: 16px;
     }
 
     #colset {
       height: 200px;
       width: 450px;
       -moz-column-width: 150px;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: 3px solid silver;
     }
 
     #x {
       height: 500px;
     }
 
     #x:before {
--- a/layout/reftests/pagination/content-inserted-009.xhtml
+++ b/layout/reftests/pagination/content-inserted-009.xhtml
@@ -8,16 +8,17 @@
       font-size: 16px;
     }
 
     #colset {
       height: 200px;
       width: 450px;
       -moz-column-width: 150px;
       -moz-column-gap: 0;
+      -moz-column-fill: auto;
       border: 3px solid silver;
     }
 
     #shift {
       height: 201px;
       border-bottom: 2px solid blue;
     }
     #overflow {
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -297,16 +297,18 @@ random-if(/^Windows\x20NT\x205\.1/.test(
 == tspan-xy-03.svg tspan-xy-ref.svg
 == tspan-xy-04.svg tspan-xy-ref.svg
 == tspan-xy-05.svg tspan-xy-ref.svg
 == tspan-xy-06.svg tspan-xy-ref.svg
 == tspan-xy-anchor-middle-01.svg tspan-xy-anchor-middle-ref.svg
 == tspan-xy-anchor-end-01.svg tspan-xy-anchor-end-ref.svg
 == userSpaceOnUse-and-pattern-01.svg userSpaceOnUse-and-pattern-01-ref.svg
 == viewBox-and-pattern-01.svg pass.svg
+== viewBox-and-pattern-02.svg pass.svg
+== viewBox-and-pattern-03.svg pass.svg
 == viewBox-invalid-01.svg pass.svg
 == viewBox-valid-01.svg pass.svg
 == viewBox-valid-02.xhtml pass.svg
 == viewport-percent-graphic-user-01.svg pass.svg
 
 == svg-effects-area-unzoomed.xhtml svg-effects-area-unzoomed-ref.xhtml
 == svg-effects-area-zoomed-in.xhtml svg-effects-area-zoomed-in-ref.xhtml
 == svg-effects-area-zoomed-out.xhtml svg-effects-area-zoomed-out-ref.xhtml
copy from layout/reftests/svg/viewBox-and-pattern-01.svg
copy to layout/reftests/svg/viewBox-and-pattern-02.svg
--- a/layout/reftests/svg/viewBox-and-pattern-01.svg
+++ b/layout/reftests/svg/viewBox-and-pattern-02.svg
@@ -1,19 +1,20 @@
 <!--
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
 
   <title>Testcase for elements referencing a viewBox pattern</title>
 
-  <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=519368 -->
+  <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=773467 -->
 
   <defs>
-    <pattern id="test" patternUnits="userSpaceOnUse" x="10" y="10" width="20" height="20" viewBox="10 10 10 10">
+    <pattern id="test" x="10" y="10" width="20" height="20" viewBox="10 10 10 10"
+             patternContentUnits="userSpaceOnUse">
       <rect x="10" y="10" width="10" height="10" fill="lime" />
     </pattern>
   </defs>
   <rect width="100%" height="100%" fill="lime" />
   <rect x="20" y="20" width="100" height="100" fill="red" />
   <rect x="20" y="20" width="100" height="100" fill="url(#test)" />
 </svg>
copy from layout/reftests/svg/viewBox-and-pattern-01.svg
copy to layout/reftests/svg/viewBox-and-pattern-03.svg
--- a/layout/reftests/svg/viewBox-and-pattern-01.svg
+++ b/layout/reftests/svg/viewBox-and-pattern-03.svg
@@ -1,19 +1,19 @@
 <!--
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
 
   <title>Testcase for elements referencing a viewBox pattern</title>
 
-  <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=519368 -->
+  <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=773467 -->
 
   <defs>
-    <pattern id="test" patternUnits="userSpaceOnUse" x="10" y="10" width="20" height="20" viewBox="10 10 10 10">
-      <rect x="10" y="10" width="10" height="10" fill="lime" />
+    <pattern id="test" width="1" height="2" viewBox="0 0 10 10" patternUnits="userSpaceOnUse">
+      <rect y="-3" width="10" height="5" fill="lime" />
     </pattern>
   </defs>
   <rect width="100%" height="100%" fill="lime" />
-  <rect x="20" y="20" width="100" height="100" fill="red" />
-  <rect x="20" y="20" width="100" height="100" fill="url(#test)" />
+  <rect transform="scale(100)" x=".2" y=".2" width="1" height="0.5" fill="red" />
+  <rect transform="scale(100)" x=".2" y=".2" width="1" height="0.5" fill="url(#test)" />
 </svg>
--- a/layout/reftests/transform/compound-1-fail.html
+++ b/layout/reftests/transform/compound-1-fail.html
@@ -11,17 +11,17 @@
     div
     {
     -moz-transform-origin: top left;
     }
   </style>
 </head>
 <body>
   <div style="position:relative; left:400px; top:200px;">
-    <div style="-moz-transform: skewx(15deg);">
+    <div style="-moz-transform: skew(15deg);">
       <div style="-moz-transform: rotate(90deg);">
 	<div style="-moz-transform: scale(2);">
 	  <div style="-moz-transform: translate(100px);">
 	    <div class="test">
 	    </div>
 	  </div>
 	</div>
       </div>
--- a/layout/reftests/transform/compound-1-ref.html
+++ b/layout/reftests/transform/compound-1-ref.html
@@ -18,17 +18,17 @@
     }
   </style>
 </head>
 <body>
   <div style="position:relative; left:400px; top:200px;">
     <div style="-moz-transform: translate(100px);">
       <div style="-moz-transform: scale(2);">
 	<div style="-moz-transform: rotate(90deg);">
-	  <div style="-moz-transform: skewx(15deg);">
+	  <div style="-moz-transform: skew(15deg);">
 	    <div class="test">
 	    </div>
 	  </div>
 	</div>
       </div>
     </div>
   </div>
 </body>
--- a/layout/reftests/transform/compound-1a.html
+++ b/layout/reftests/transform/compound-1a.html
@@ -15,13 +15,13 @@
     body
     {
     overflow:hidden;
     }
   </style>
 </head>
 <body>
   <div style="position:relative; left:400px; top:200px;">
-    <div class="test" style="-moz-transform: translate(100px) scale(2) rotate(90deg) skewx(15deg);">
+    <div class="test" style="-moz-transform: translate(100px) scale(2) rotate(90deg) skew(15deg);">
     </div>
   </div>
 </body>
 </html>
--- a/layout/reftests/transform/reftest.list
+++ b/layout/reftests/transform/reftest.list
@@ -77,16 +77,20 @@ random == rotate-1f.html rotate-1-ref.ht
 == origin-name-3a.html origin-name-3-ref.html
 == origin-name-3b.html origin-name-3-ref.html
 # Snapping still applies after 90 degree rotations.
 == snapping-1.html snapping-1-ref.html
 # SVG effects should work on transforms.
 == transform-svg-1a.xhtml transform-svg-1-ref.xhtml
 == transform-svg-2a.xhtml transform-svg-2-ref.xhtml
 != transform-svg-2a.xhtml transform-svg-2-fail.xhtml
+# skew should allow a mix of one and two parameters.
+== skew-1a.html skew-1-ref.html
+== skew-1b.html skew-1-ref.html
+== skew-2a.html skew-2-ref.html
 # matrix with values equal to other transforms should behave indistinguishably
 == matrix-1a.html matrix-1-ref.html
 == matrix-2a.html matrix-2-ref.html
 == matrix-3a.html matrix-3-ref.html<