merge fx-team to m-c
authorRob Campbell <rcampbell@mozilla.com>
Mon, 12 Mar 2012 20:43:23 -0300
changeset 88805 2fb8fedd7fc86ab5e3fe0db41f5ad2c54356d3f7
parent 88804 eb08099d0b4417ac0230dc60049c99faabaeebb6 (current diff)
parent 88802 406113c400a91e801f7b9bd59cddc2125d4d76c7 (diff)
child 88806 3463e63451a49bc7ae75931eaba0e991aeabc192
child 88916 c1d32bb1b893be6da7e90774beef25646cafdd6d
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
milestone13.0a1
merge fx-team to m-c
--- a/accessible/src/base/TextAttrs.cpp
+++ b/accessible/src/base/TextAttrs.cpp
@@ -47,42 +47,16 @@
 #include "gfxUserFontSet.h"
 #include "nsFontMetrics.h"
 #include "nsLayoutUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
-// Constants and structures
-
-/**
- * Item of the gCSSTextAttrsMap map.
- */
-struct nsCSSTextAttrMapItem
-{
-  const char* mCSSName;
-  const char* mCSSValue;
-  nsIAtom** mAttrName;
-  const char* mAttrValue;
-};
-
-/**
- * The map of CSS properties to text attributes.
- */
-const char* const kAnyValue = nsnull;
-const char* const kCopyValue = nsnull;
-
-static nsCSSTextAttrMapItem gCSSTextAttrsMap[] =
-{
-  // CSS name            CSS value        Attribute name                     Attribute value
-  { "vertical-align",    kAnyValue,       &nsGkAtoms::textPosition,          kCopyValue }
-};
-
-////////////////////////////////////////////////////////////////////////////////
 // TextAttrsMgr
 ////////////////////////////////////////////////////////////////////////////////
 
 void
 TextAttrsMgr::GetAttributes(nsIPersistentProperties* aAttributes,
                             PRInt32* aStartHTOffset,
                             PRInt32* aEndHTOffset)
 {
@@ -134,88 +108,87 @@ TextAttrsMgr::GetAttributes(nsIPersisten
   nsIContent *offsetNode = nsnull, *offsetElm = nsnull;
   nsIFrame *frame = nsnull;
   if (mOffsetAcc) {
     offsetNode = mOffsetAcc->GetContent();
     offsetElm = nsCoreUtils::GetDOMElementFor(offsetNode);
     frame = offsetElm->GetPrimaryFrame();
   }
 
-  nsTArray<TextAttr*> textAttrArray(9);
-
   // "language" text attribute
   LangTextAttr langTextAttr(mHyperTextAcc, hyperTextElm, offsetNode);
-  textAttrArray.AppendElement(&langTextAttr);
-
-  // "text-position" text attribute
-  CSSTextAttr posTextAttr(0, hyperTextElm, offsetElm);
-  textAttrArray.AppendElement(&posTextAttr);
 
   // "background-color" text attribute
   BGColorTextAttr bgColorTextAttr(rootFrame, frame);
-  textAttrArray.AppendElement(&bgColorTextAttr);
 
   // "color" text attribute
   ColorTextAttr colorTextAttr(rootFrame, frame);
-  textAttrArray.AppendElement(&colorTextAttr);
 
   // "font-family" text attribute
   FontFamilyTextAttr fontFamilyTextAttr(rootFrame, frame);
-  textAttrArray.AppendElement(&fontFamilyTextAttr);
 
   // "font-size" text attribute
   FontSizeTextAttr fontSizeTextAttr(rootFrame, frame);
-  textAttrArray.AppendElement(&fontSizeTextAttr);
 
   // "font-style" text attribute
   FontStyleTextAttr fontStyleTextAttr(rootFrame, frame);
-  textAttrArray.AppendElement(&fontStyleTextAttr);
 
   // "font-weight" text attribute
   FontWeightTextAttr fontWeightTextAttr(rootFrame, frame);
-  textAttrArray.AppendElement(&fontWeightTextAttr);
 
   // "text-underline(line-through)-style(color)" text attributes
   TextDecorTextAttr textDecorTextAttr(rootFrame, frame);
-  textAttrArray.AppendElement(&textDecorTextAttr);
+
+  // "text-position" text attribute
+  TextPosTextAttr textPosTextAttr(rootFrame, frame);
+
+  TextAttr* attrArray[] =
+  {
+    &langTextAttr,
+    &bgColorTextAttr,
+    &colorTextAttr,
+    &fontFamilyTextAttr,
+    &fontSizeTextAttr,
+    &fontStyleTextAttr,
+    &fontWeightTextAttr,
+    &textDecorTextAttr,
+    &textPosTextAttr
+  };
 
   // Expose text attributes if applicable.
   if (aAttributes) {
-    PRUint32 len = textAttrArray.Length();
-    for (PRUint32 idx = 0; idx < len; idx++)
-      textAttrArray[idx]->Expose(aAttributes, mIncludeDefAttrs);
+    for (PRUint32 idx = 0; idx < ArrayLength(attrArray); idx++)
+      attrArray[idx]->Expose(aAttributes, mIncludeDefAttrs);
   }
 
   // Expose text attributes range where they are applied if applicable.
   if (mOffsetAcc)
-    GetRange(textAttrArray, aStartHTOffset, aEndHTOffset);
+    GetRange(attrArray, ArrayLength(attrArray), aStartHTOffset, aEndHTOffset);
 }
 
 void
-TextAttrsMgr::GetRange(const nsTArray<TextAttr*>& aTextAttrArray,
+TextAttrsMgr::GetRange(TextAttr* aAttrArray[], PRUint32 aAttrArrayLen,
                        PRInt32* aStartHTOffset, PRInt32* aEndHTOffset)
 {
-  PRUint32 attrLen = aTextAttrArray.Length();
-
   // Navigate backward from anchor accessible to find start offset.
   for (PRInt32 childIdx = mOffsetAccIdx - 1; childIdx >= 0; childIdx--) {
     nsAccessible *currAcc = mHyperTextAcc->GetChildAt(childIdx);
 
     // Stop on embedded accessible since embedded accessibles are combined into
     // own range.
     if (nsAccUtils::IsEmbeddedObject(currAcc))
       break;
 
     nsIContent* currElm = nsCoreUtils::GetDOMElementFor(currAcc->GetContent());
     if (!currElm)
       return;
 
     bool offsetFound = false;
-    for (PRUint32 attrIdx = 0; attrIdx < attrLen; attrIdx++) {
-      TextAttr* textAttr = aTextAttrArray[attrIdx];
+    for (PRUint32 attrIdx = 0; attrIdx < aAttrArrayLen; attrIdx++) {
+      TextAttr* textAttr = aAttrArray[attrIdx];
       if (!textAttr->Equal(currElm)) {
         offsetFound = true;
         break;
       }
     }
 
     if (offsetFound)
       break;
@@ -230,18 +203,18 @@ TextAttrsMgr::GetRange(const nsTArray<Te
     if (nsAccUtils::IsEmbeddedObject(currAcc))
       break;
 
     nsIContent* currElm = nsCoreUtils::GetDOMElementFor(currAcc->GetContent());
     if (!currElm)
       return;
 
     bool offsetFound = false;
-    for (PRUint32 attrIdx = 0; attrIdx < attrLen; attrIdx++) {
-      TextAttr* textAttr = aTextAttrArray[attrIdx];
+    for (PRUint32 attrIdx = 0; attrIdx < aAttrArrayLen; attrIdx++) {
+      TextAttr* textAttr = aAttrArray[attrIdx];
 
       // Alter the end offset when text attribute changes its value and stop
       // the search.
       if (!textAttr->Equal(currElm)) {
         offsetFound = true;
         break;
       }
     }
@@ -289,70 +262,16 @@ TextAttrsMgr::LangTextAttr::
   GetLang(nsIContent* aElm, nsAString& aLang)
 {
   nsCoreUtils::GetLanguageFor(aElm, mRootContent, aLang);
   return !aLang.IsEmpty();
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
-// CSSTextAttr
-////////////////////////////////////////////////////////////////////////////////
-
-TextAttrsMgr::CSSTextAttr::
-  CSSTextAttr(PRUint32 aIndex, nsIContent* aRootElm, nsIContent* aElm) :
-  TTextAttr<nsString>(!aElm), mIndex(aIndex)
-{
-  mIsRootDefined = GetValueFor(aRootElm, &mRootNativeValue);
-
-  if (aElm)
-    mIsDefined = GetValueFor(aElm, &mNativeValue);
-}
-
-bool
-TextAttrsMgr::CSSTextAttr::
-  GetValueFor(nsIContent* aElm, nsString* aValue)
-{
-  nsCOMPtr<nsIDOMCSSStyleDeclaration> currStyleDecl =
-    nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), aElm);
-  if (!currStyleDecl)
-    return false;
-
-  NS_ConvertASCIItoUTF16 cssName(gCSSTextAttrsMap[mIndex].mCSSName);
-
-  nsresult rv = currStyleDecl->GetPropertyValue(cssName, *aValue);
-  if (NS_FAILED(rv))
-    return true;
-
-  const char *cssValue = gCSSTextAttrsMap[mIndex].mCSSValue;
-  if (cssValue != kAnyValue && !aValue->EqualsASCII(cssValue))
-    return false;
-
-  return true;
-}
-
-void
-TextAttrsMgr::CSSTextAttr::
-  ExposeValue(nsIPersistentProperties* aAttributes, const nsString& aValue)
-{
-  const char* attrValue = gCSSTextAttrsMap[mIndex].mAttrValue;
-  if (attrValue != kCopyValue) {
-    nsAutoString formattedValue;
-    AppendASCIItoUTF16(attrValue, formattedValue);
-    nsAccUtils::SetAccAttr(aAttributes, *gCSSTextAttrsMap[mIndex].mAttrName,
-                           formattedValue);
-    return;
-  }
-
-  nsAccUtils::SetAccAttr(aAttributes, *gCSSTextAttrsMap[mIndex].mAttrName,
-                         aValue);
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
 // BGColorTextAttr
 ////////////////////////////////////////////////////////////////////////////////
 
 TextAttrsMgr::BGColorTextAttr::
   BGColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
   TTextAttr<nscolor>(!aFrame), mRootFrame(aRootFrame)
 {
   mIsRootDefined = GetColor(mRootFrame, &mRootNativeValue);
@@ -737,8 +656,109 @@ TextAttrsMgr::TextDecorTextAttr::
                            formattedStyle);
 
     nsAutoString formattedColor;
     StyleInfo::FormatColor(aValue.Color(), formattedColor);
     nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textLineThroughColor,
                            formattedColor);
   }
 }
+
+////////////////////////////////////////////////////////////////////////////////
+// TextPosTextAttr
+////////////////////////////////////////////////////////////////////////////////
+
+TextAttrsMgr::TextPosTextAttr::
+  TextPosTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
+  TTextAttr<TextPosValue>(!aFrame)
+{
+  mRootNativeValue = GetTextPosValue(aRootFrame);
+  mIsRootDefined = mRootNativeValue != eTextPosNone;
+
+  if (aFrame) {
+    mNativeValue = GetTextPosValue(aFrame);
+    mIsDefined = mNativeValue != eTextPosNone;
+  }
+}
+
+bool
+TextAttrsMgr::TextPosTextAttr::
+  GetValueFor(nsIContent* aContent, TextPosValue* aValue)
+{
+  nsIFrame* frame = aContent->GetPrimaryFrame();
+  if (frame) {
+    *aValue = GetTextPosValue(frame);
+    return *aValue != eTextPosNone;
+  }
+
+  return false;
+}
+
+void
+TextAttrsMgr::TextPosTextAttr::
+  ExposeValue(nsIPersistentProperties* aAttributes, const TextPosValue& aValue)
+{
+  switch (aValue) {
+    case eTextPosBaseline:
+      nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
+                             NS_LITERAL_STRING("baseline"));
+      break;
+
+    case eTextPosSub:
+      nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
+                             NS_LITERAL_STRING("sub"));
+      break;
+
+    case eTextPosSuper:
+      nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
+                             NS_LITERAL_STRING("super"));
+      break;
+  }
+}
+
+TextAttrsMgr::TextPosValue
+TextAttrsMgr::TextPosTextAttr::
+  GetTextPosValue(nsIFrame* aFrame) const
+{
+  const nsStyleCoord& styleCoord = aFrame->GetStyleTextReset()->mVerticalAlign;
+  switch (styleCoord.GetUnit()) {
+    case eStyleUnit_Enumerated:
+      switch (styleCoord.GetIntValue()) {
+        case NS_STYLE_VERTICAL_ALIGN_BASELINE:
+          return eTextPosBaseline;
+        case NS_STYLE_VERTICAL_ALIGN_SUB:
+          return eTextPosSub;
+        case NS_STYLE_VERTICAL_ALIGN_SUPER:
+          return eTextPosSuper;
+
+        // No good guess for these:
+        //   NS_STYLE_VERTICAL_ALIGN_TOP
+        //   NS_STYLE_VERTICAL_ALIGN_TEXT_TOP
+        //   NS_STYLE_VERTICAL_ALIGN_MIDDLE
+        //   NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM
+        //   NS_STYLE_VERTICAL_ALIGN_BOTTOM
+        //   NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE
+        // Do not expose value of text-position attribute.
+
+        default:
+          break;
+      }
+      return eTextPosNone;
+
+    case eStyleUnit_Percent:
+    {
+      float percentValue = styleCoord.GetPercentValue();
+      return percentValue > 0 ?
+        eTextPosSuper :
+        (percentValue < 0 ? eTextPosSub : eTextPosBaseline);
+    }
+
+    case eStyleUnit_Coord:
+    {
+       nscoord coordValue = styleCoord.GetCoordValue();
+       return coordValue > 0 ?
+         eTextPosSuper :
+         (coordValue < 0 ? eTextPosSub : eTextPosBaseline);
+    }
+  }
+
+  return eTextPosNone;
+}
--- a/accessible/src/base/TextAttrs.h
+++ b/accessible/src/base/TextAttrs.h
@@ -102,21 +102,22 @@ public:
 
 protected:
   /**
    * Calculates range (start and end offsets) of text where the text attributes
    * are stretched. New offsets may be smaller if one of text attributes changes
    * its value before or after the given offsets.
    *
    * @param aTextAttrArray  [in] text attributes array
+   * @param aAttrArrayLen   [in] text attributes array length
    * @param aStartHTOffset  [in, out] the start offset
    * @param aEndHTOffset    [in, out] the end offset
    */
   class TextAttr;
-  void GetRange(const nsTArray<TextAttr*>& aTextAttrArray,
+  void GetRange(TextAttr* aAttrArray[], PRUint32 aAttrArrayLen,
                 PRInt32* aStartHTOffset, PRInt32* aEndHTOffset);
 
 private:
   nsHyperTextAccessible* mHyperTextAcc;
 
   bool mIncludeDefAttrs;
 
   nsAccessible* mOffsetAcc;
@@ -152,17 +153,17 @@ protected:
    * Base class to work with text attributes. See derived classes below.
    */
   template<class T>
   class TTextAttr : public TextAttr
   {
   public:
     TTextAttr(bool aGetRootValue) : mGetRootValue(aGetRootValue) {}
 
-    // ITextAttr
+    // TextAttr
     virtual void Expose(nsIPersistentProperties* aAttributes,
                         bool aIncludeDefAttrValue)
     {
       if (mGetRootValue) {
         if (mIsRootDefined)
           ExposeValue(aAttributes, mRootNativeValue);
         return;
       }
@@ -238,37 +239,16 @@ protected:
 
   private:
     bool GetLang(nsIContent* aElm, nsAString& aLang);
     nsCOMPtr<nsIContent> mRootContent;
   };
 
 
   /**
-   * Class is used for the work with CSS based text attributes.
-   */
-  class CSSTextAttr : public TTextAttr<nsString>
-  {
-  public:
-    CSSTextAttr(PRUint32 aIndex, nsIContent* aRootElm, nsIContent* aElm);
-    virtual ~CSSTextAttr() { }
-
-  protected:
-
-    // TextAttr
-    virtual bool GetValueFor(nsIContent* aElm, nsString* aValue);
-    virtual void ExposeValue(nsIPersistentProperties* aAttributes,
-                             const nsString& aValue);
-
-  private:
-    PRInt32 mIndex;
-  };
-
-
-  /**
    * Class is used for the work with 'background-color' text attribute.
    */
   class BGColorTextAttr : public TTextAttr<nscolor>
   {
   public:
     BGColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
     virtual ~BGColorTextAttr() { }
 
@@ -430,14 +410,42 @@ protected:
   protected:
 
     // TextAttr
     virtual bool GetValueFor(nsIContent* aElm, TextDecorValue* aValue);
     virtual void ExposeValue(nsIPersistentProperties* aAttributes,
                              const TextDecorValue& aValue);
   };
 
+  /**
+   * Class is used for the work with "text-position" text attribute.
+   */
+
+  enum TextPosValue {
+    eTextPosNone = 0,
+    eTextPosBaseline,
+    eTextPosSub,
+    eTextPosSuper
+  };
+
+  class TextPosTextAttr : public TTextAttr<TextPosValue>
+  {
+  public:
+    TextPosTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
+    virtual ~TextPosTextAttr() { }
+
+  protected:
+
+    // TextAttr
+    virtual bool GetValueFor(nsIContent* aElm, TextPosValue* aValue);
+    virtual void ExposeValue(nsIPersistentProperties* aAttributes,
+                             const TextPosValue& aValue);
+
+  private:
+    TextPosValue GetTextPosValue(nsIFrame* aFrame) const;
+  };
+
 }; // TextAttrMgr
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/tests/mochitest/attributes/test_text.html
+++ b/accessible/tests/mochitest/attributes/test_text.html
@@ -176,16 +176,40 @@
       attrs = {};
       testTextAttrs(ID, 50, attrs, defAttrs, 50, 55);
 
       tempElem = tempElem.nextSibling.nextSibling;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = {"text-position": gComputedStyle.verticalAlign};
       testTextAttrs(ID, 55, attrs, defAttrs, 55, 64);
 
+      attrs = {};
+      testTextAttrs(ID, 64, attrs, defAttrs, 64, 69);
+
+      attrs = { "text-position": "super" };
+      testTextAttrs(ID, 69, attrs, defAttrs, 69, 84);
+
+      attrs = {};
+      testTextAttrs(ID, 84, attrs, defAttrs, 84, 89);
+
+      attrs = { "text-position": "sub" };
+      testTextAttrs(ID, 89, attrs, defAttrs, 89, 102);
+
+      attrs = {};
+      testTextAttrs(ID, 102, attrs, defAttrs, 102, 107);
+
+      attrs = { "text-position": "super" };
+      testTextAttrs(ID, 107, attrs, defAttrs, 107, 123);
+
+      attrs = {};
+      testTextAttrs(ID, 123, attrs, defAttrs, 123, 128);
+
+      attrs = { "text-position": "sub" };
+      testTextAttrs(ID, 128, attrs, defAttrs, 128, 142);
+
       //////////////////////////////////////////////////////////////////////////
       // area7
       ID = "area7";
       defAttrs = buildDefaultTextAttrs(ID, "12pt");
       defAttrs["language"] = "en";
       testDefaultTextAttrs(ID, defAttrs);
 
       attrs = {"language": "ru"};
@@ -501,16 +525,21 @@
 <body style="font-size: 12pt">
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=345759"
      title="Implement text attributes">
     Mozilla Bug 345759
   </a>
   <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=473569"
+     title="Restrict text-position to allowed values">
+    Mozilla Bug 473569
+  </a>
+  <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=473576"
      title="font-family text attribute should expose actual font used">
     Mozilla Bug 473576
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=523304"
      title="expose text-underline-color and text-line-through-color text attributes">
     Mozilla Bug 523304
@@ -544,17 +573,21 @@
     <span style="color: green">Green</span>
     <img src="../moz.png" alt="image"/>
     <span style="color: red">Red</span>Normal
   </p>
   <p id="area6">
     This <sup>sentence</sup> has the word 
     <span style="vertical-align:super;">sentence</span> in 
     <sub>superscript</sub> and 
-    <span style="vertical-align:sub;">subscript</span>
+    <span style="vertical-align:sub;">subscript</span> and
+    <span style="vertical-align:20%;">superscript 20%</span> and
+    <span style="vertical-align:-20%;">subscript 20%</span> and
+    <span style="vertical-align:20px;">superscript 20px</span> and
+    <span style="vertical-align:-20px;">subscript 20px</span>
   </p>
 
   <p lang="en" id="area7">
     <span lang="ru">Привет</span>
     <span style="background-color: blue">Blue BG color</span>
     <span lang="de">Ich bin/Du bist</span>
     <span lang="en">
       Normal
--- a/browser/components/places/content/browserPlacesViews.js
+++ b/browser/components/places/content/browserPlacesViews.js
@@ -371,41 +371,36 @@ PlacesViewBase.prototype = {
    * @param aPopup
    *        The livemark container popup
    * @param aStatus
    *        The livemark status
    */
   _setLivemarkStatusMenuItem:
   function PVB_setLivemarkStatusMenuItem(aPopup, aStatus) {
     let statusMenuitem = aPopup._statusMenuitem;
-    let stringId = "";
-    if (aStatus == Ci.mozILivemark.STATUS_LOADING)
-      stringId = "bookmarksLivemarkLoading";
-    else if (aStatus == Ci.mozILivemark.STATUS_FAILED)
-      stringId = "bookmarksLivemarkFailed";
-
-    if (stringId && !statusMenuitem) {
+    if (!statusMenuitem) {
       // Create the status menuitem and cache it in the popup object.
       statusMenuitem = document.createElement("menuitem");
-      statusMenuitem.setAttribute("livemarkStatus", stringId);
       statusMenuitem.className = "livemarkstatus-menuitem";
-      statusMenuitem.setAttribute("label", PlacesUIUtils.getString(stringId));
       statusMenuitem.setAttribute("disabled", true);
-      aPopup.insertBefore(statusMenuitem, aPopup._startMarker.nextSibling);
       aPopup._statusMenuitem = statusMenuitem;
     }
-    else if (stringId &&
-             statusMenuitem.getAttribute("livemarkStatus") != stringId) {
+
+    if (aStatus == Ci.mozILivemark.STATUS_LOADING ||
+        aStatus == Ci.mozILivemark.STATUS_FAILED) {
       // Status has changed, update the cached status menuitem.
+      let stringId = aStatus == Ci.mozILivemark.STATUS_LOADING ?
+                       "bookmarksLivemarkLoading" : "bookmarksLivemarkFailed";
       statusMenuitem.setAttribute("label", PlacesUIUtils.getString(stringId));
+      if (aPopup._startMarker.nextSibling != statusMenuitem)
+        aPopup.insertBefore(statusMenuitem, aPopup._startMarker.nextSibling);
     }
-    else if (!stringId && statusMenuitem) {
+    else {
       // The livemark has finished loading.
       aPopup.removeChild(aPopup._statusMenuitem);
-      aPopup._statusMenuitem = null;
     }
   },
 
   toggleCutNode: function PVB_toggleCutNode(aNode, aValue) {
     let elt = aNode._DOMElement;
     if (elt) {
       // We may get the popup for menus, but we need the menu itself.
       if (elt.localName == "menupopup")
@@ -1012,19 +1007,20 @@ PlacesToolbar.prototype = {
     if (aBefore)
       this._rootElt.insertBefore(button, aBefore);
     else
       this._rootElt.appendChild(button);
   },
 
   _updateChevronPopupNodesVisibility:
   function PT__updateChevronPopupNodesVisibility() {
-    for (let i = 0; i < this._chevronPopup.childNodes.length; i++) {
-      this._chevronPopup.childNodes[i].hidden =
-        this._rootElt.childNodes[i].style.visibility != "hidden";
+    for (let i = 0, node = this._chevronPopup._startMarker.nextSibling;
+         node != this._chevronPopup._endMarker;
+         i++, node = node.nextSibling) {
+      node.hidden = this._rootElt.childNodes[i].style.visibility != "hidden";
     }
   },
 
   _onChevronPopupShowing:
   function PT__onChevronPopupShowing(aEvent) {
     // Handle popupshowing only for the chevron popup, not for nested ones.
     if (aEvent.target != this._chevronPopup)
       return;
--- a/browser/config/mozconfigs/linux32/debug
+++ b/browser/config/mozconfigs/linux32/debug
@@ -13,8 +13,11 @@ export MOZILLA_OFFICIAL=1
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 #Use ccache
 ac_add_options --with-ccache=/usr/bin/ccache
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/linux32/nightly
+++ b/browser/config/mozconfigs/linux32/nightly
@@ -22,8 +22,11 @@ mk_add_options PROFILE_GEN_SCRIPT='$(PYT
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 #Use ccache
 ac_add_options --with-ccache=/usr/bin/ccache
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/linux32/release
+++ b/browser/config/mozconfigs/linux32/release
@@ -16,8 +16,11 @@ export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/linux64/debug
+++ b/browser/config/mozconfigs/linux64/debug
@@ -10,8 +10,11 @@ ac_add_options --enable-stdcxx-compat
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/linux64/nightly
+++ b/browser/config/mozconfigs/linux64/nightly
@@ -22,8 +22,11 @@ mk_add_options PROFILE_GEN_SCRIPT='$(PYT
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 #Use ccache
 ac_add_options --with-ccache=/usr/bin/ccache
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/linux64/release
+++ b/browser/config/mozconfigs/linux64/release
@@ -16,8 +16,11 @@ export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/macosx-universal/nightly
+++ b/browser/config/mozconfigs/macosx-universal/nightly
@@ -17,8 +17,11 @@ export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 ac_add_options --with-macbundlename-prefix=Firefox
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/macosx-universal/release
+++ b/browser/config/mozconfigs/macosx-universal/release
@@ -12,8 +12,11 @@ export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/macosx32/debug
+++ b/browser/config/mozconfigs/macosx32/debug
@@ -5,8 +5,11 @@ ac_add_options --enable-signmar
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 ac_add_options --with-macbundlename-prefix=Firefox
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/macosx64/debug
+++ b/browser/config/mozconfigs/macosx64/debug
@@ -10,8 +10,11 @@ mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 ac_add_options --with-macbundlename-prefix=Firefox
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/win32/debug
+++ b/browser/config/mozconfigs/win32/debug
@@ -3,8 +3,11 @@ ac_add_options --enable-trace-malloc
 ac_add_options --enable-signmar
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 mk_add_options MOZ_MAKE_FLAGS=-j1
 
 . $topsrcdir/browser/config/mozconfigs/win32/vs2010-mozconfig
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/win32/nightly
+++ b/browser/config/mozconfigs/win32/nightly
@@ -12,8 +12,11 @@ ac_add_options --enable-js-diagnostics
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 mk_add_options MOZ_MAKE_FLAGS=-j1
 
 . $topsrcdir/browser/config/mozconfigs/win32/vs2010-mozconfig
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/win32/release
+++ b/browser/config/mozconfigs/win32/release
@@ -8,8 +8,11 @@ ac_add_options --enable-jemalloc
 ac_add_options --enable-official-branding
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 . $topsrcdir/browser/config/mozconfigs/win32/vs2010-mozconfig
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/win64/debug
+++ b/browser/config/mozconfigs/win64/debug
@@ -4,8 +4,13 @@ ac_add_options --host=x86_64-pc-mingw32
 ac_add_options --enable-debug
 ac_add_options --enable-trace-malloc
 ac_add_options --enable-signmar
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 mk_add_options MOZ_MAKE_FLAGS=-j1
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
+
+. $topsrcdir/browser/config/mozconfigs/win64/vs2010-mozconfig
--- a/browser/config/mozconfigs/win64/nightly
+++ b/browser/config/mozconfigs/win64/nightly
@@ -13,8 +13,13 @@ ac_add_options --enable-signmar
 ac_add_options --enable-js-diagnostics
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 mk_add_options MOZ_MAKE_FLAGS=-j1
+
+# Package js shell.
+export MOZ_PACKAGE_JSSHELL=1
+
+. $topsrcdir/browser/config/mozconfigs/win64/vs2010-mozconfig
new file mode 100644
--- /dev/null
+++ b/browser/config/mozconfigs/win64/vs2010-mozconfig
@@ -0,0 +1,16 @@
+export INCLUDE=/c/tools/msvs10/vc/include:/c/tools/msvs10/vc/atlmfc/include:/c/tools/sdks/v7.0/include:/c/tools/sdks/v7.0/include/atl:/c/tools/sdks/dx10/include
+export LIBPATH=/c/tools/msvs10/vc/lib/amd64:/c/tools/msvs10/vc/atlmfc/lib/amd64
+export LIB=/c/tools/msvs10/vc/lib/amd64:/c/tools/msvs10/vc/atlmfc/lib/amd64:/c/tools/sdks/v7.0/lib/x64:/c/tools/sdks/dx10/lib/x64
+export PATH="/c/tools/msvs10/Common7/IDE:/c/tools/msvs10/VC/BIN/amd64:/c/tools/msvs10/VC/BIN/x86_amd64:/c/tools/msvs10/VC/BIN:/c/tools/msvs10/Common7/Tools:/c/tools/msvs10/VC/VCPackages:${PATH}"
+export WIN32_REDIST_DIR=/c/tools/msvs10/VC/redist/x64/Microsoft.VC100.CRT
+
+# Use 32bit linker for PGO crash bug.
+# https://connect.microsoft.com/VisualStudio/feedback/details/686117/
+export LD=/c/tools/msvs10/VC/BIN/x86_amd64/link.exe
+
+
+mk_add_options "export LIB=$LIB"
+mk_add_options "export LIBPATH=$LIBPATH"
+mk_add_options "export PATH=$PATH"
+mk_add_options "export INCLUDE=$INCLUDE"
+mk_add_options "export WIN32_REDIST_DIR=$WIN32_REDIST_DIR"
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -445,51 +445,43 @@ PBBUILD_BIN	= @PBBUILD@
 SDP		= @SDP@
 NSINSTALL_BIN	= @NSINSTALL_BIN@
 WGET		= @WGET@
 RPMBUILD	= @RPMBUILD@
 
 ifdef MOZ_NATIVE_JPEG
 JPEG_CFLAGS	= @JPEG_CFLAGS@
 JPEG_LIBS	= @JPEG_LIBS@
-JPEG_REQUIRES	=
 else
 JPEG_CFLAGS	= @MOZ_JPEG_CFLAGS@
 JPEG_LIBS	= @MOZ_JPEG_LIBS@
-JPEG_REQUIRES	= jpeg
 endif
 
 ifdef MOZ_NATIVE_ZLIB
 ZLIB_CFLAGS	= @ZLIB_CFLAGS@
 ZLIB_LIBS	= @ZLIB_LIBS@
-ZLIB_REQUIRES	=
 else
 ZLIB_CFLAGS	= @MOZ_ZLIB_CFLAGS@
 MOZ_ZLIB_LIBS = @MOZ_ZLIB_LIBS@
-ZLIB_REQUIRES	= zlib
 endif
 
 ifdef MOZ_NATIVE_BZ2
 BZ2_CFLAGS	= @BZ2_CFLAGS@
 BZ2_LIBS	= @BZ2_LIBS@
-BZ2_REQUIRES	=
 else
 BZ2_CFLAGS	= @MOZ_BZ2_CFLAGS@
 BZ2_LIBS	= @MOZ_BZ2_LIBS@
-BZ2_REQUIRES	= libbz2
 endif
 
 ifdef MOZ_NATIVE_PNG
 PNG_CFLAGS	= @PNG_CFLAGS@
 PNG_LIBS	= @PNG_LIBS@
-PNG_REQUIRES	=
 else
 PNG_CFLAGS	= @MOZ_PNG_CFLAGS@
 PNG_LIBS	= @MOZ_PNG_LIBS@
-PNG_REQUIRES	= png
 endif
 
 QCMS_LIBS	= @QCMS_LIBS@
 
 MOZ_HARFBUZZ_LIBS = @MOZ_HARFBUZZ_LIBS@
 MOZ_GRAPHITE_LIBS = @MOZ_GRAPHITE_LIBS@
 MOZ_GRAPHITE = @MOZ_GRAPHITE@
 MOZ_OTS_LIBS = @MOZ_OTS_LIBS@
@@ -702,16 +694,18 @@ ANDROID_VERSION   = @ANDROID_VERSION@
 ANDROID_PACKAGE_NAME = @ANDROID_PACKAGE_NAME@
 
 JS_SHARED_LIBRARY = @JS_SHARED_LIBRARY@
 
 MOZ_INSTRUMENT_EVENT_LOOP = @MOZ_INSTRUMENT_EVENT_LOOP@
 
 MOZ_SYSTEM_PLY = @MOZ_SYSTEM_PLY@
 
+MOZ_PACKAGE_JSSHELL = @MOZ_PACKAGE_JSSHELL@
+
 # We only want to do the pymake sanity on Windows, other os's can cope
 ifeq ($(HOST_OS_ARCH),WINNT)
 # Ensure invariants between GNU Make and pymake
 # Checked here since we want the sane error in a file that
 # actually can be found regardless of path-style.
 ifeq (_:,$(.PYMAKE)_$(findstring :,$(srcdir)))
 $(error Windows-style srcdir being used with GNU make. Did you mean to run $(topsrcdir)/build/pymake/make.py instead? [see-also: https://developer.mozilla.org/en/Gmake_vs._Pymake])
 endif
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1906,19 +1906,16 @@ echo-tier-dirs:
 	@$(foreach tier,$(TIERS),echo '$(tier):'; echo '  dirs: $(tier_$(tier)_dirs)'; echo '  staticdirs: $(tier_$(tier)_staticdirs)'; )
 
 echo-dirs:
 	@echo $(DIRS)
 
 echo-module:
 	@echo $(MODULE)
 
-echo-requires:
-	@echo $(REQUIRES)
-
 echo-depth-path:
 	@$(topsrcdir)/build/unix/print-depth-path.sh
 
 echo-module-name:
 	@$(topsrcdir)/build/package/rpm/print-module-name.sh
 
 echo-module-filelist:
 	@$(topsrcdir)/build/package/rpm/print-module-filelist.sh
@@ -2015,17 +2012,16 @@ endif
 FREEZE_VARIABLES = \
   CSRCS \
   CPPSRCS \
   EXPORTS \
   XPIDLSRCS \
   DIRS \
   LIBRARY \
   MODULE \
-  REQUIRES \
   SHORT_LIBNAME \
   TIERS \
   EXTRA_COMPONENTS \
   EXTRA_PP_COMPONENTS \
   $(NULL)
 
 $(foreach var,$(FREEZE_VARIABLES),$(eval $(var)_FROZEN := '$($(var))'))
 
--- a/configure.in
+++ b/configure.in
@@ -8826,16 +8826,18 @@ AC_SUBST(VPX_ARM_ASM)
 AC_SUBST(VPX_NEED_OBJ_INT_EXTRACT)
 AC_SUBST(MOZ_INSTRUMENT_EVENT_LOOP)
 AC_SUBST(LIBJPEG_TURBO_AS)
 AC_SUBST(LIBJPEG_TURBO_ASFLAGS)
 AC_SUBST(LIBJPEG_TURBO_X86_ASM)
 AC_SUBST(LIBJPEG_TURBO_X64_ASM)
 AC_SUBST(LIBJPEG_TURBO_ARM_ASM)
 
+AC_SUBST(MOZ_PACKAGE_JSSHELL)
+
 AC_MSG_CHECKING([for posix_fallocate])
 AC_TRY_LINK([#define _XOPEN_SOURCE 600
   #include <fcntl.h>],
                  [posix_fallocate(0, 0, 0);],
                  [ac_cv___posix_fallocate=true],
                  [ac_cv___posix_fallocate=false])
 
 if test "$ac_cv___posix_fallocate" = true ; then
--- a/content/base/public/nsDOMFile.h
+++ b/content/base/public/nsDOMFile.h
@@ -54,16 +54,18 @@
 #include "nsAutoPtr.h"
 
 #include "mozilla/GuardObjects.h"
 #include "mozilla/StandardInteger.h"
 #include "mozilla/dom/DOMError.h"
 #include "mozilla/dom/indexedDB/FileInfo.h"
 #include "mozilla/dom/indexedDB/FileManager.h"
 #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
+#include "nsWrapperCache.h"
+#include "nsCycleCollectionParticipant.h"
 
 class nsIFile;
 class nsIInputStream;
 class nsIClassInfo;
 class nsIBlobBuilder;
 
 nsresult NS_NewBlobBuilder(nsISupports* *aSupports);
 
@@ -321,32 +323,48 @@ protected:
     }
     void* mData;
   };
 
   // Used when backed by a memory store
   nsRefPtr<DataOwner> mDataOwner;
 };
 
-class nsDOMFileList : public nsIDOMFileList
+class nsDOMFileList MOZ_FINAL : public nsIDOMFileList,
+                                public nsWrapperCache
 {
 public:
-  NS_DECL_ISUPPORTS
+  nsDOMFileList(nsISupports *aParent) : mParent(aParent)
+  {
+    SetIsProxy();
+  }
+
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMFileList)
+
   NS_DECL_NSIDOMFILELIST
 
+  virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                               bool *triedToWrap);
+
+  nsISupports* GetParentObject()
+  {
+    return mParent;
+  }
+
+  void Disconnect()
+  {
+    mParent = nsnull;
+  }
+
   bool Append(nsIDOMFile *aFile) { return mFiles.AppendObject(aFile); }
 
   bool Remove(PRUint32 aIndex) { return mFiles.RemoveObjectAt(aIndex); }
   void Clear() { return mFiles.Clear(); }
 
-  nsIDOMFile* GetItemAt(PRUint32 aIndex)
-  {
-    return mFiles.SafeObjectAt(aIndex);
-  }
-
   static nsDOMFileList* FromSupports(nsISupports* aSupports)
   {
 #ifdef DEBUG
     {
       nsCOMPtr<nsIDOMFileList> list_qi = do_QueryInterface(aSupports);
 
       // If this assertion fires the QI implementation for the object in
       // question doesn't use the nsIDOMFileList pointer as the nsISupports
@@ -356,16 +374,17 @@ public:
     }
 #endif
 
     return static_cast<nsDOMFileList*>(aSupports);
   }
 
 private:
   nsCOMArray<nsIDOMFile> mFiles;
+  nsISupports *mParent;
 };
 
 class NS_STACK_CLASS nsDOMFileInternalUrlHolder {
 public:
   nsDOMFileInternalUrlHolder(nsIDOMBlob* aFile, nsIPrincipal* aPrincipal
                              MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
   ~nsDOMFileInternalUrlHolder();
   nsAutoString mUrl;
--- a/content/base/public/nsIDOMFileList.idl
+++ b/content/base/public/nsIDOMFileList.idl
@@ -38,10 +38,11 @@
 #include "domstubs.idl"
 
 interface nsIDOMFile;
 
 [scriptable, uuid(3bfef9fa-8ad3-4e49-bd62-d6cd75b29298)]
 interface nsIDOMFileList : nsISupports
 {
   readonly attribute unsigned long length;
-  nsIDOMFile item(in unsigned long index);
+  [getter,forward(getItemAt)] nsIDOMFile item(in unsigned long index);
+  [noscript,notxpcom,nostdcall] nsIDOMFile getItemAt(in unsigned long index);
 };
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -62,16 +62,17 @@
 #include "nsBlobProtocolHandler.h"
 #include "nsStringStream.h"
 #include "CheckedInt.h"
 #include "nsJSUtils.h"
 #include "mozilla/Preferences.h"
 
 #include "plbase64.h"
 #include "prmem.h"
+#include "dombindings.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 // XXXkhuey the input stream that we pass out of a DOMFile
 // can outlive the actual DOMFile object.  Thus, we must
 // ensure that the buffer underlying the stream we get
 // from NS_NewByteInputStream is held alive as long as the
@@ -602,37 +603,62 @@ nsDOMMemoryFile::GetInternalStream(nsIIn
   return DataOwnerAdapter::Create(mDataOwner, mStart, mLength, aStream);
 }
 
 ////////////////////////////////////////////////////////////////////////////
 // nsDOMFileList implementation
 
 DOMCI_DATA(FileList, nsDOMFileList)
 
-NS_INTERFACE_MAP_BEGIN(nsDOMFileList)
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMFileList)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMFileList)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMFileList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMFileList)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMFileList)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFileList)
   NS_INTERFACE_MAP_ENTRY(nsIDOMFileList)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(FileList)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_ADDREF(nsDOMFileList)
-NS_IMPL_RELEASE(nsDOMFileList)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMFileList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMFileList)
+
+JSObject*
+nsDOMFileList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                          bool *triedToWrap)
+{
+  return mozilla::dom::binding::FileList::create(cx, scope, this, triedToWrap);
+}
+
+nsIDOMFile*
+nsDOMFileList::GetItemAt(PRUint32 aIndex)
+{
+  return mFiles.SafeObjectAt(aIndex);
+}
 
 NS_IMETHODIMP
 nsDOMFileList::GetLength(PRUint32* aLength)
 {
   *aLength = mFiles.Count();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMFileList::Item(PRUint32 aIndex, nsIDOMFile **aFile)
 {
-  NS_IF_ADDREF(*aFile = GetItemAt(aIndex));
+  NS_IF_ADDREF(*aFile = nsDOMFileList::GetItemAt(aIndex));
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////
 // nsDOMFileInternalUrlHolder implementation
 
 nsDOMFileInternalUrlHolder::nsDOMFileInternalUrlHolder(nsIDOMBlob* aFile,
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -8460,17 +8460,18 @@ nsDocument::CreateTouch(nsIDOMWindow* aV
                                       aForce));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocument::CreateTouchList(nsIVariant* aPoints,
                             nsIDOMTouchList** aRetVal)
 {
-  nsRefPtr<nsDOMTouchList> retval = new nsDOMTouchList();
+  nsRefPtr<nsDOMTouchList> retval =
+    new nsDOMTouchList(static_cast<nsIDocument*>(this));
   if (aPoints) {
     PRUint16 type;
     aPoints->GetDataType(&type);
     if (type == nsIDataType::VTYPE_INTERFACE ||
         type == nsIDataType::VTYPE_INTERFACE_IS) {
       nsCOMPtr<nsISupports> data;
       aPoints->GetAsISupports(getter_AddRefs(data));
       nsCOMPtr<nsIDOMTouch> point = do_QueryInterface(data);
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -2309,17 +2309,17 @@ nsGenericElement::GetElementsByClassName
   return nsContentUtils::GetElementsByClassName(this, aClasses, aReturn);
 }
 
 NS_IMETHODIMP
 nsGenericElement::GetClientRects(nsIDOMClientRectList** aResult)
 {
   *aResult = nsnull;
 
-  nsRefPtr<nsClientRectList> rectList = new nsClientRectList();
+  nsRefPtr<nsClientRectList> rectList = new nsClientRectList(this);
 
   nsIFrame* frame = GetPrimaryFrame(Flush_Layout);
   if (!frame) {
     // display:none, perhaps? Return an empty list
     *aResult = rectList.forget().get();
     return NS_OK;
   }
 
--- a/content/base/src/nsRange.cpp
+++ b/content/base/src/nsRange.cpp
@@ -2494,17 +2494,18 @@ nsRange::GetBoundingClientRect(nsIDOMCli
 NS_IMETHODIMP
 nsRange::GetClientRects(nsIDOMClientRectList** aResult)
 {
   *aResult = nsnull;
 
   if (!mStartParent)
     return NS_OK;
 
-  nsRefPtr<nsClientRectList> rectList = new nsClientRectList();
+  nsRefPtr<nsClientRectList> rectList =
+    new nsClientRectList(static_cast<nsIDOMRange*>(this));
   if (!rectList)
     return NS_ERROR_OUT_OF_MEMORY;
 
   nsLayoutUtils::RectListBuilder builder(rectList);
 
   CollectClientRects(&builder, this, mStartParent, mStartOffset, 
     mEndParent, mEndOffset);
 
--- a/content/events/src/nsDOMDataTransfer.cpp
+++ b/content/events/src/nsDOMDataTransfer.cpp
@@ -53,17 +53,30 @@
 #include "nsIScriptableRegion.h"
 #include "nsContentUtils.h"
 #include "nsIContent.h"
 #include "nsCRT.h"
 #include "nsIScriptObjectPrincipal.h"
 
 using namespace mozilla;
 
-NS_IMPL_CYCLE_COLLECTION_2(nsDOMDataTransfer, mDragTarget, mDragImage)
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMDataTransfer)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMDataTransfer)
+  if (tmp->mFiles) {
+    tmp->mFiles->Disconnect();
+    NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFiles)
+  }
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDragTarget)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDragImage)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMDataTransfer)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFiles)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDragTarget)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDragImage)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMDataTransfer)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMDataTransfer)
 
 DOMCI_DATA(DataTransfer, nsDOMDataTransfer)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMDataTransfer)
   NS_INTERFACE_MAP_ENTRY(nsIDOMDataTransfer)
@@ -230,17 +243,17 @@ NS_IMETHODIMP
 nsDOMDataTransfer::GetFiles(nsIDOMFileList** aFileList)
 {
   *aFileList = nsnull;
 
   if (mEventType != NS_DRAGDROP_DROP && mEventType != NS_DRAGDROP_DRAGDROP)
     return NS_OK;
 
   if (!mFiles) {
-    mFiles = new nsDOMFileList();
+    mFiles = new nsDOMFileList(static_cast<nsIDOMDataTransfer*>(this));
     NS_ENSURE_TRUE(mFiles, NS_ERROR_OUT_OF_MEMORY);
 
     PRUint32 count = mItems.Length();
 
     for (PRUint32 i = 0; i < count; i++) {
       nsCOMPtr<nsIVariant> variant;
       nsresult rv = MozGetDataAt(NS_ConvertUTF8toUTF16(kFileMime), i, getter_AddRefs(variant));
       NS_ENSURE_SUCCESS(rv, rv);
--- a/content/events/src/nsDOMDataTransfer.h
+++ b/content/events/src/nsDOMDataTransfer.h
@@ -100,16 +100,23 @@ protected:
                     bool aCursorState,
                     bool aIsExternal,
                     bool aUserCancelled,
                     nsTArray<nsTArray<TransferItem> >& aItems,
                     nsIDOMElement* aDragImage,
                     PRUint32 aDragImageX,
                     PRUint32 aDragImageY);
 
+  ~nsDOMDataTransfer()
+  {
+    if (mFiles) {
+      mFiles->Disconnect();
+    }
+  }
+
   static const char sEffects[8][9];
 
 public:
 
   void GetDragTarget(nsIDOMElement** aDragTarget)
   {
     *aDragTarget = mDragTarget;
     NS_IF_ADDREF(*aDragTarget);
--- a/content/events/src/nsDOMNotifyPaintEvent.cpp
+++ b/content/events/src/nsDOMNotifyPaintEvent.cpp
@@ -98,17 +98,18 @@ nsDOMNotifyPaintEvent::GetBoundingClient
 
   rect->SetLayoutRect(GetRegion().GetBounds());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMNotifyPaintEvent::GetClientRects(nsIDOMClientRectList** aResult)
 {
-  nsRefPtr<nsClientRectList> rectList = new nsClientRectList();
+  nsRefPtr<nsClientRectList> rectList =
+    new nsClientRectList(static_cast<nsIDOMEvent*>(static_cast<nsDOMEvent*>(this)));
   if (!rectList)
     return NS_ERROR_OUT_OF_MEMORY;
 
   nsRegion r = GetRegion();
   nsRegionRectIterator iter(r);
   for (const nsRect* rgnRect = iter.Next(); rgnRect; rgnRect = iter.Next()) {
     nsRefPtr<nsClientRect> rect = new nsClientRect();
     if (!rect)
@@ -120,17 +121,18 @@ nsDOMNotifyPaintEvent::GetClientRects(ns
 
   rectList.forget(aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMNotifyPaintEvent::GetPaintRequests(nsIDOMPaintRequestList** aResult)
 {
-  nsRefPtr<nsPaintRequestList> requests = new nsPaintRequestList();
+  nsRefPtr<nsPaintRequestList> requests =
+    new nsPaintRequestList(static_cast<nsDOMEvent*>(this));
   if (!requests)
     return NS_ERROR_OUT_OF_MEMORY;
 
   bool isTrusted = nsContentUtils::IsCallerTrustedForRead();
   for (PRUint32 i = 0; i < mInvalidateRequests.Length(); ++i) {
     if (!isTrusted &&
         (mInvalidateRequests[i].mFlags & nsIFrame::INVALIDATE_CROSS_DOC))
       continue;
--- a/content/events/src/nsDOMTouchEvent.cpp
+++ b/content/events/src/nsDOMTouchEvent.cpp
@@ -155,53 +155,56 @@ nsDOMTouch::Equals(nsIDOMTouch* aTouch)
   aTouch->GetRadiusY(&radiusY);
   return mRefPoint != aTouch->mRefPoint ||
          (mForce != force) ||
          (mRotationAngle != orientation) ||
          (mRadius.x != radiusX) || (mRadius.y != radiusY);
 }
 
 // TouchList
-nsDOMTouchList::nsDOMTouchList(nsTArray<nsCOMPtr<nsIDOMTouch> > &aTouches)
-{
-  mPoints.AppendElements(aTouches);
-}
 
 DOMCI_DATA(TouchList, nsDOMTouchList)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMTouchList)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMTouchList)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIDOMTouchList)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TouchList)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMTouchList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(mPoints)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMTouchList)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMTouchList)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mPoints)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMTouchList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMTouchList)
 
 NS_IMETHODIMP
 nsDOMTouchList::GetLength(PRUint32* aLength)
 {
   *aLength = mPoints.Length();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMTouchList::Item(PRUint32 aIndex, nsIDOMTouch** aRetVal)
 {
-  NS_IF_ADDREF(*aRetVal = mPoints.SafeElementAt(aIndex, nsnull));
+  NS_IF_ADDREF(*aRetVal = nsDOMTouchList::GetItemAt(aIndex));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMTouchList::IdentifiedTouch(PRInt32 aIdentifier, nsIDOMTouch** aRetVal)
 {
   *aRetVal = nsnull;
   for (PRUint32 i = 0; i < mPoints.Length(); ++i) {
@@ -211,16 +214,22 @@ nsDOMTouchList::IdentifiedTouch(PRInt32 
         aIdentifier == identifier) {
       point.swap(*aRetVal);
       break;
     }
   }
   return NS_OK;
 }
 
+nsIDOMTouch*
+nsDOMTouchList::GetItemAt(PRUint32 aIndex)
+{
+  return mPoints.SafeElementAt(aIndex, nsnull);
+}
+
 // TouchEvent
 
 nsDOMTouchEvent::nsDOMTouchEvent(nsPresContext* aPresContext,
                                  nsTouchEvent* aEvent)
   : nsDOMUIEvent(aPresContext, aEvent ? aEvent :
                                         new nsTouchEvent(false, 0, nsnull))
 {
   if (aEvent) {
@@ -317,19 +326,21 @@ nsDOMTouchEvent::GetTouches(nsIDOMTouchL
     // for touchend events, remove any changed touches from the touches array
     nsTArray<nsCOMPtr<nsIDOMTouch> > unchangedTouches;
     nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
     for (PRUint32 i = 0; i < touches.Length(); ++i) {
       if (!touches[i]->mChanged) {
         unchangedTouches.AppendElement(touches[i]);
       }
     }
-    t = new nsDOMTouchList(unchangedTouches);
+    t = new nsDOMTouchList(static_cast<nsIDOMTouchEvent*>(this),
+                           unchangedTouches);
   } else {
-    t = new nsDOMTouchList(touchEvent->touches);
+    t = new nsDOMTouchList(static_cast<nsIDOMTouchEvent*>(this),
+                           touchEvent->touches);
   }
   mTouches = t;
   return CallQueryInterface(mTouches, aTouches);
 }
 
 NS_IMETHODIMP
 nsDOMTouchEvent::GetTargetTouches(nsIDOMTouchList** aTargetTouches)
 {
@@ -349,17 +360,18 @@ nsDOMTouchEvent::GetTargetTouches(nsIDOM
     if ((mEvent->message != NS_TOUCH_END &&
          mEvent->message != NS_TOUCH_CANCEL) || !touches[i]->mChanged) {
       nsIDOMEventTarget* targetPtr = touches[i]->GetTarget();
       if (targetPtr == mEvent->target) {
         targetTouches.AppendElement(touches[i]);
       }
     }
   }
-  mTargetTouches = new nsDOMTouchList(targetTouches);
+  mTargetTouches = new nsDOMTouchList(static_cast<nsIDOMTouchEvent*>(this),
+                                      targetTouches);
   return CallQueryInterface(mTargetTouches, aTargetTouches);
 }
 
 NS_IMETHODIMP
 nsDOMTouchEvent::GetChangedTouches(nsIDOMTouchList** aChangedTouches)
 {
   NS_ENSURE_ARG_POINTER(aChangedTouches);
   NS_ENSURE_STATE(mEvent);
@@ -371,17 +383,18 @@ nsDOMTouchEvent::GetChangedTouches(nsIDO
   nsTArray<nsCOMPtr<nsIDOMTouch> > changedTouches;
   nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(mEvent);
   nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
   for (PRUint32 i = 0; i < touches.Length(); ++i) {
     if (touches[i]->mChanged) {
       changedTouches.AppendElement(touches[i]);
     }
   }
-  mChangedTouches = new nsDOMTouchList(changedTouches);
+  mChangedTouches = new nsDOMTouchList(static_cast<nsIDOMTouchEvent*>(this),
+                                       changedTouches);
   return CallQueryInterface(mChangedTouches, aChangedTouches);
 }
 
 NS_IMETHODIMP
 nsDOMTouchEvent::GetAltKey(bool* aAltKey)
 {
   *aAltKey = static_cast<nsInputEvent*>(mEvent)->isAlt;
   return NS_OK;
--- a/content/events/src/nsDOMTouchEvent.h
+++ b/content/events/src/nsDOMTouchEvent.h
@@ -36,16 +36,18 @@
  * ***** END LICENSE BLOCK ***** */
 #ifndef nsDOMTouchEvent_h_
 #define nsDOMTouchEvent_h_
 
 #include "nsDOMUIEvent.h"
 #include "nsIDOMTouchEvent.h"
 #include "nsString.h"
 #include "nsTArray.h"
+#include "nsIDocument.h"
+#include "dombindings.h"
 
 class nsDOMTouch : public nsIDOMTouch
 {
 public:
   nsDOMTouch(nsIDOMEventTarget* aTarget,
              PRInt32 aIdentifier,
              PRInt32 aPageX,
              PRInt32 aPageY,
@@ -122,37 +124,56 @@ protected:
   nsIntPoint mPagePoint;
   nsIntPoint mClientPoint;
   nsIntPoint mScreenPoint;
   nsIntPoint mRadius;
   float mRotationAngle;
   float mForce;
 };
 
-class nsDOMTouchList : public nsIDOMTouchList
+class nsDOMTouchList MOZ_FINAL : public nsIDOMTouchList,
+                                 public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMTouchList)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMTouchList)
   NS_DECL_NSIDOMTOUCHLIST
 
-  nsDOMTouchList() { }
-  nsDOMTouchList(nsTArray<nsCOMPtr<nsIDOMTouch> > &aTouches);
-  
+  nsDOMTouchList(nsISupports *aParent) : mParent(aParent)
+  {
+    SetIsProxy();
+  }
+  nsDOMTouchList(nsISupports *aParent,
+                 nsTArray<nsCOMPtr<nsIDOMTouch> > &aTouches)
+   : mPoints(aTouches),
+     mParent(aParent)
+  {
+    SetIsProxy();
+  }
+
+  virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                               bool *triedToWrap)
+  {
+    return mozilla::dom::binding::TouchList::create(cx, scope, this,
+                                                    triedToWrap);
+  }
+
+  nsISupports *GetParentObject()
+  {
+    return mParent;
+  }
+
   void Append(nsIDOMTouch* aPoint)
   {
     mPoints.AppendElement(aPoint);
   }
 
-  nsIDOMTouch* GetItemAt(PRUint32 aIndex)
-  {
-    return mPoints.SafeElementAt(aIndex, nsnull);
-  }
 protected:
   nsTArray<nsCOMPtr<nsIDOMTouch> > mPoints;
+  nsCOMPtr<nsISupports> mParent;
 };
 
 class nsDOMTouchEvent : public nsDOMUIEvent,
                         public nsIDOMTouchEvent
 {
 public:
   nsDOMTouchEvent(nsPresContext* aPresContext, nsTouchEvent* aEvent);
   virtual ~nsDOMTouchEvent();
--- a/content/events/src/nsPaintRequest.cpp
+++ b/content/events/src/nsPaintRequest.cpp
@@ -36,16 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsPaintRequest.h"
 
 #include "nsDOMClassInfoID.h"
 #include "nsClientRect.h"
 #include "nsIFrame.h"
+#include "nsContentUtils.h"
 
 DOMCI_DATA(PaintRequest, nsPaintRequest)
 
 NS_INTERFACE_TABLE_HEAD(nsPaintRequest)
   NS_INTERFACE_TABLE1(nsPaintRequest, nsIDOMPaintRequest)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(PaintRequest)
 NS_INTERFACE_MAP_END
@@ -78,31 +79,50 @@ nsPaintRequest::GetReason(nsAString& aRe
     aResult.Truncate();
     break;
   }
   return NS_OK;
 }
 
 DOMCI_DATA(PaintRequestList, nsPaintRequestList)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsPaintRequestList)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsPaintRequestList)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPaintRequestList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsPaintRequestList)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
 NS_INTERFACE_TABLE_HEAD(nsPaintRequestList)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_TABLE1(nsPaintRequestList, nsIDOMPaintRequestList)
-  NS_INTERFACE_TABLE_TO_MAP_SEGUE
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsPaintRequestList)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(PaintRequestList)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_ADDREF(nsPaintRequestList)
-NS_IMPL_RELEASE(nsPaintRequestList)
-
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPaintRequestList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPaintRequestList)
 
 NS_IMETHODIMP    
 nsPaintRequestList::GetLength(PRUint32* aLength)
 {
   *aLength = mArray.Count();
   return NS_OK;
 }
 
 NS_IMETHODIMP    
 nsPaintRequestList::Item(PRUint32 aIndex, nsIDOMPaintRequest** aReturn)
 {
-  NS_IF_ADDREF(*aReturn = GetItemAt(aIndex));
+  NS_IF_ADDREF(*aReturn = nsPaintRequestList::GetItemAt(aIndex));
   return NS_OK;
 }
+
+nsIDOMPaintRequest*
+nsPaintRequestList::GetItemAt(PRUint32 aIndex)
+{
+  return mArray.SafeObjectAt(aIndex);
+}
--- a/content/events/src/nsPaintRequest.h
+++ b/content/events/src/nsPaintRequest.h
@@ -37,17 +37,18 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef NSPAINTREQUEST_H_
 #define NSPAINTREQUEST_H_
 
 #include "nsIDOMPaintRequest.h"
 #include "nsIDOMPaintRequestList.h"
 #include "nsPresContext.h"
-#include "nsClientRect.h"
+#include "nsIDOMEvent.h"
+#include "dombindings.h"
 
 class nsPaintRequest : public nsIDOMPaintRequest
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMPAINTREQUEST
 
   nsPaintRequest() { mRequest.mFlags = 0; }
@@ -56,31 +57,43 @@ public:
   { mRequest = aRequest; }
 
 private:
   ~nsPaintRequest() {}
 
   nsInvalidateRequestList::Request mRequest;
 };
 
-class nsPaintRequestList : public nsIDOMPaintRequestList
+class nsPaintRequestList MOZ_FINAL : public nsIDOMPaintRequestList,
+                                     public nsWrapperCache
 {
 public:
-  nsPaintRequestList() {}
+  nsPaintRequestList(nsIDOMEvent *aParent) : mParent(aParent)
+  {
+    SetIsProxy();
+  }
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsPaintRequestList)
   NS_DECL_NSIDOMPAINTREQUESTLIST
   
-  void Append(nsIDOMPaintRequest* aElement) { mArray.AppendObject(aElement); }
+  virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                               bool *triedToWrap)
+  {
+    return mozilla::dom::binding::PaintRequestList::create(cx, scope, this,
+                                                           triedToWrap);
+  }
 
-  nsIDOMPaintRequest* GetItemAt(PRUint32 aIndex)
+  nsISupports* GetParentObject()
   {
-    return mArray.SafeObjectAt(aIndex);
+    return mParent;
   }
 
+  void Append(nsIDOMPaintRequest* aElement) { mArray.AppendObject(aElement); }
+
   static nsPaintRequestList* FromSupports(nsISupports* aSupports)
   {
 #ifdef DEBUG
     {
       nsCOMPtr<nsIDOMPaintRequestList> list_qi = do_QueryInterface(aSupports);
 
       // If this assertion fires the QI implementation for the object in
       // question doesn't use the nsIDOMClientRectList pointer as the nsISupports
@@ -92,11 +105,12 @@ public:
 
     return static_cast<nsPaintRequestList*>(aSupports);
   }
 
 private:
   ~nsPaintRequestList() {}
 
   nsCOMArray<nsIDOMPaintRequest> mArray;
+  nsCOMPtr<nsIDOMEvent> mParent;
 };
 
 #endif /*NSPAINTREQUEST_H_*/
--- a/content/html/content/src/nsClientRect.cpp
+++ b/content/html/content/src/nsClientRect.cpp
@@ -36,16 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsClientRect.h"
 #include "nsContentUtils.h"
 #include "nsDOMClassInfoID.h"
 
 #include "nsPresContext.h"
+#include "dombindings.h"
 
 DOMCI_DATA(ClientRect, nsClientRect)
 
 NS_INTERFACE_TABLE_HEAD(nsClientRect)
   NS_INTERFACE_TABLE1(nsClientRect, nsIDOMClientRect)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ClientRect)
 NS_INTERFACE_MAP_END
@@ -97,40 +98,68 @@ NS_IMETHODIMP
 nsClientRect::GetHeight(float* aResult)
 {
   *aResult = mHeight;
   return NS_OK;
 }
 
 DOMCI_DATA(ClientRectList, nsClientRectList)
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsClientRectList)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsClientRectList)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsClientRectList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsClientRectList)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
 NS_INTERFACE_TABLE_HEAD(nsClientRectList)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_TABLE1(nsClientRectList, nsIDOMClientRectList)
-  NS_INTERFACE_TABLE_TO_MAP_SEGUE
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsClientRectList)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ClientRectList)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_ADDREF(nsClientRectList)
-NS_IMPL_RELEASE(nsClientRectList)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsClientRectList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsClientRectList)
 
 
 NS_IMETHODIMP    
 nsClientRectList::GetLength(PRUint32* aLength)
 {
   *aLength = mArray.Count();
   return NS_OK;
 }
 
 NS_IMETHODIMP    
 nsClientRectList::Item(PRUint32 aIndex, nsIDOMClientRect** aReturn)
 {
-  NS_IF_ADDREF(*aReturn = GetItemAt(aIndex));
+  NS_IF_ADDREF(*aReturn = nsClientRectList::GetItemAt(aIndex));
   return NS_OK;
 }
 
+nsIDOMClientRect*
+nsClientRectList::GetItemAt(PRUint32 aIndex)
+{
+  return mArray.SafeObjectAt(aIndex);
+}
+
+JSObject*
+nsClientRectList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                             bool *triedToWrap)
+{
+  return mozilla::dom::binding::ClientRectList::create(cx, scope, this,
+                                                       triedToWrap);
+}
+
 static double
 RoundFloat(double aValue)
 {
   return floor(aValue + 0.5);
 }
 
 void
 nsClientRect::SetLayoutRect(const nsRect& aLayoutRect)
--- a/content/html/content/src/nsClientRect.h
+++ b/content/html/content/src/nsClientRect.h
@@ -39,16 +39,18 @@
 #ifndef NSCLIENTRECT_H_
 #define NSCLIENTRECT_H_
 
 #include "nsIDOMClientRect.h"
 #include "nsIDOMClientRectList.h"
 #include "nsCOMArray.h"
 #include "nsRect.h"
 #include "nsCOMPtr.h"
+#include "nsWrapperCache.h"
+#include "nsCycleCollectionParticipant.h"
 
 class nsClientRect : public nsIDOMClientRect
 {
 public:
   NS_DECL_ISUPPORTS
 
   nsClientRect();
   void SetRect(float aX, float aY, float aWidth, float aHeight) {
@@ -59,32 +61,40 @@ public:
   NS_DECL_NSIDOMCLIENTRECT
 
   void SetLayoutRect(const nsRect& aLayoutRect);
 
 protected:
   float mX, mY, mWidth, mHeight;
 };
 
-class nsClientRectList : public nsIDOMClientRectList
+class nsClientRectList MOZ_FINAL : public nsIDOMClientRectList,
+                                   public nsWrapperCache
 {
 public:
-  nsClientRectList() {}
+  nsClientRectList(nsISupports *aParent) : mParent(aParent)
+  {
+    SetIsProxy();
+  }
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsClientRectList)
 
   NS_DECL_NSIDOMCLIENTRECTLIST
   
-  void Append(nsIDOMClientRect* aElement) { mArray.AppendObject(aElement); }
+  virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                               bool *triedToWrap);
 
-  nsIDOMClientRect* GetItemAt(PRUint32 aIndex)
+  nsISupports* GetParentObject()
   {
-    return mArray.SafeObjectAt(aIndex);
+    return mParent;
   }
 
+  void Append(nsIDOMClientRect* aElement) { mArray.AppendObject(aElement); }
+
   static nsClientRectList* FromSupports(nsISupports* aSupports)
   {
 #ifdef DEBUG
     {
       nsCOMPtr<nsIDOMClientRectList> list_qi = do_QueryInterface(aSupports);
 
       // If this assertion fires the QI implementation for the object in
       // question doesn't use the nsIDOMClientRectList pointer as the nsISupports
@@ -96,11 +106,12 @@ public:
 
     return static_cast<nsClientRectList*>(aSupports);
   }
 
 protected:
   virtual ~nsClientRectList() {}
 
   nsCOMArray<nsIDOMClientRect> mArray;
+  nsCOMPtr<nsISupports> mParent;
 };
 
 #endif /*NSCLIENTRECT_H_*/
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -582,16 +582,19 @@ nsHTMLInputElement::nsHTMLInputElement(a
   // by default we don't have to show validity UI and so forth.
   AddStatesSilently(NS_EVENT_STATE_ENABLED |
                     NS_EVENT_STATE_OPTIONAL |
                     NS_EVENT_STATE_VALID);
 }
 
 nsHTMLInputElement::~nsHTMLInputElement()
 {
+  if (mFileList) {
+    mFileList->Disconnect();
+  }
   DestroyImageLoadingContent();
   FreeData();
 }
 
 void
 nsHTMLInputElement::FreeData()
 {
   if (!IsSingleLineTextControl(false)) {
@@ -629,17 +632,20 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mFiles)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFileList)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLInputElement,
                                                   nsGenericHTMLFormElement)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mControllers)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mFiles)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFileList);
+  if (tmp->mFileList) {
+    tmp->mFileList->Disconnect();
+    tmp->mFileList = nsnull;
+  }
   //XXX should unlink more?
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
                                                               
 NS_IMPL_ADDREF_INHERITED(nsHTMLInputElement, nsGenericElement) 
 NS_IMPL_RELEASE_INHERITED(nsHTMLInputElement, nsGenericElement) 
 
 
 DOMCI_NODE_DATA(HTMLInputElement, nsHTMLInputElement)
@@ -2768,17 +2774,17 @@ nsHTMLInputElement::GetFiles(nsIDOMFileL
 {
   *aFileList = nsnull;
 
   if (mType != NS_FORM_INPUT_FILE) {
     return NS_OK;
   }
 
   if (!mFileList) {
-    mFileList = new nsDOMFileList();
+    mFileList = new nsDOMFileList(static_cast<nsIContent*>(this));
     if (!mFileList) return NS_ERROR_OUT_OF_MEMORY;
 
     UpdateFileList();
   }
 
   NS_ADDREF(*aFileList = mFileList);
 
   return NS_OK;
--- a/content/media/nsBuiltinDecoderReader.cpp
+++ b/content/media/nsBuiltinDecoderReader.cpp
@@ -32,19 +32,16 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include "nsISeekableStream.h"
-#include "nsClassHashtable.h"
-#include "nsTArray.h"
 #include "nsBuiltinDecoder.h"
 #include "nsBuiltinDecoderReader.h"
 #include "nsBuiltinDecoderStateMachine.h"
 #include "VideoUtils.h"
 
 #include "mozilla/mozalloc.h"
 #include "mozilla/StandardInteger.h"
 
--- a/content/media/nsBuiltinDecoderReader.h
+++ b/content/media/nsBuiltinDecoderReader.h
@@ -35,26 +35,20 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #if !defined(nsBuiltinDecoderReader_h_)
 #define nsBuiltinDecoderReader_h_
 
 #include <nsDeque.h>
-#include "Layers.h"
 #include "ImageLayers.h"
-#include "nsClassHashtable.h"
-#include "mozilla/TimeStamp.h"
 #include "nsSize.h"
-#include "nsRect.h"
 #include "mozilla/ReentrantMonitor.h"
 
-class nsBuiltinDecoderStateMachine;
-
 // Stores info relevant to presenting media frames.
 class nsVideoInfo {
 public:
   nsVideoInfo()
     : mAudioRate(0),
       mAudioChannels(0),
       mDisplay(0,0),
       mStereoMode(mozilla::layers::STEREO_MODE_MONO),
--- a/content/media/nsMediaDecoder.cpp
+++ b/content/media/nsMediaDecoder.cpp
@@ -34,30 +34,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsMediaDecoder.h"
 #include "MediaResource.h"
 
-#include "prlog.h"
-#include "prmem.h"
-#include "nsIFrame.h"
-#include "nsIDocument.h"
-#include "nsThreadUtils.h"
-#include "nsIDOMHTMLMediaElement.h"
-#include "nsNetUtil.h"
 #include "nsHTMLMediaElement.h"
-#include "gfxContext.h"
-#include "nsPresContext.h"
 #include "nsDOMError.h"
-#include "nsDisplayList.h"
-#include "nsSVGEffects.h"
-#include "VideoUtils.h"
 
 using namespace mozilla;
 
 // Number of milliseconds between progress events as defined by spec
 static const PRUint32 PROGRESS_MS = 350;
 
 // Number of milliseconds of no data before a stall event is fired as defined by spec
 static const PRUint32 STALL_MS = 3000;
--- a/content/media/nsMediaDecoder.h
+++ b/content/media/nsMediaDecoder.h
@@ -33,32 +33,26 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #if !defined(nsMediaDecoder_h_)
 #define nsMediaDecoder_h_
 
-#include "mozilla/XPCOM.h"
-
-#include "nsIPrincipal.h"
-#include "nsSize.h"
-#include "prlog.h"
-#include "gfxContext.h"
-#include "gfxRect.h"
-#include "nsITimer.h"
 #include "ImageLayers.h"
 #include "mozilla/ReentrantMonitor.h"
-#include "nsIMemoryReporter.h"
 #include "VideoFrameContainer.h"
 
 class nsHTMLMediaElement;
 class nsIStreamListener;
 class nsTimeRanges;
+class nsIMemoryReporter;
+class nsIPrincipal;
+class nsITimer;
 
 namespace mozilla {
 class MediaResource;
 }
 
 // The size to use for audio data frames in MozAudioAvailable events.
 // This value is per channel, and is chosen to give ~43 fps of events,
 // for example, 44100 with 2 channels, 2*1024 = 2048.
--- a/content/media/wave/nsWaveReader.cpp
+++ b/content/media/wave/nsWaveReader.cpp
@@ -31,17 +31,16 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #include "nsError.h"
-#include "nsBuiltinDecoderStateMachine.h"
 #include "nsBuiltinDecoder.h"
 #include "MediaResource.h"
 #include "nsWaveReader.h"
 #include "nsTimeRanges.h"
 #include "VideoUtils.h"
 
 #include "mozilla/StandardInteger.h"
 
--- a/content/media/wave/nsWaveReader.h
+++ b/content/media/wave/nsWaveReader.h
@@ -35,17 +35,18 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #if !defined(nsWaveReader_h_)
 #define nsWaveReader_h_
 
 #include "nsBuiltinDecoderReader.h"
 
-class nsMediaDecoder;
+class nsBuiltinDecoder;
+class nsTimeRanges;
 
 class nsWaveReader : public nsBuiltinDecoderReader
 {
 public:
   nsWaveReader(nsBuiltinDecoder* aDecoder);
   ~nsWaveReader();
 
   virtual nsresult Init(nsBuiltinDecoderReader* aCloneDonor);
--- a/content/media/webm/nsWebMReader.cpp
+++ b/content/media/webm/nsWebMReader.cpp
@@ -36,20 +36,25 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #include "nsError.h"
 #include "nsBuiltinDecoderStateMachine.h"
 #include "nsBuiltinDecoder.h"
 #include "MediaResource.h"
 #include "nsWebMReader.h"
+#include "nsWebMBufferedParser.h"
 #include "VideoUtils.h"
 #include "nsTimeRanges.h"
 #include "mozilla/Preferences.h"
 
+#define VPX_DONT_DEFINE_STDINT_TYPES
+#include "vpx/vp8dx.h"
+#include "vpx/vpx_decoder.h"
+
 using namespace mozilla;
 using namespace mozilla::layers;
 
 // Un-comment to enable logging of seek bisections.
 //#define SEEK_LOGGING
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gBuiltinDecoderLog;
--- a/content/media/webm/nsWebMReader.h
+++ b/content/media/webm/nsWebMReader.h
@@ -38,31 +38,29 @@
  * ***** END LICENSE BLOCK ***** */
 #if !defined(nsWebMReader_h_)
 #define nsWebMReader_h_
 
 #include "mozilla/StandardInteger.h"
 
 #include "nsDeque.h"
 #include "nsBuiltinDecoderReader.h"
-#include "nsWebMBufferedParser.h"
 #include "nsAutoRef.h"
 #include "nestegg/nestegg.h"
 
 #define VPX_DONT_DEFINE_STDINT_TYPES
-#include "vpx/vpx_decoder.h"
-#include "vpx/vp8dx.h"
+#include "vpx/vpx_codec.h"
 
 #ifdef MOZ_TREMOR
 #include "tremor/ivorbiscodec.h"
 #else
 #include "vorbis/codec.h"
 #endif
 
-class nsMediaDecoder;
+class nsWebMBufferedState;
 
 // Holds a nestegg_packet, and its file offset. This is needed so we
 // know the offset in the file we've played up to, in order to calculate
 // whether it's likely we can play through to the end without needing
 // to stop to buffer, given the current download rate.
 class NesteggPacketHolder {
 public:
   NesteggPacketHolder(nestegg_packet* aPacket, PRInt64 aOffset)
--- a/content/svg/content/src/DOMSVGLengthList.cpp
+++ b/content/svg/content/src/DOMSVGLengthList.cpp
@@ -35,16 +35,18 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsSVGElement.h"
 #include "DOMSVGLengthList.h"
 #include "DOMSVGLength.h"
 #include "nsDOMError.h"
 #include "SVGAnimatedLengthList.h"
 #include "nsCOMPtr.h"
+#include "nsContentUtils.h"
+#include "dombindings.h"
 
 // See the comment in this file's header.
 
 // local helper functions
 namespace {
 
 using mozilla::DOMSVGLength;
 
@@ -67,38 +69,51 @@ namespace mozilla {
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our DOMSVGAnimatedLengthList's weak ref to us to be safe. (The other
 // option would be to not unlink and rely on the breaking of the other edges in
 // the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
 NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGLengthList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGLengthList)
   // No need to null check tmp - script/SMIL can't detach us from mAList
   ( tmp->IsAnimValList() ? tmp->mAList->mAnimVal : tmp->mAList->mBaseVal ) = nsnull;
-NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGLengthList)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGLengthList)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGLengthList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGLengthList)
 
 } // namespace mozilla
 DOMCI_DATA(SVGLengthList, mozilla::DOMSVGLengthList)
 namespace mozilla {
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGLengthList)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGLengthList)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGLengthList)
 NS_INTERFACE_MAP_END
 
+JSObject*
+DOMSVGLengthList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                             bool *triedToWrap)
+{
+  return mozilla::dom::binding::SVGLengthList::create(cx, scope, this,
+                                                      triedToWrap);
+}
 
 nsIDOMSVGLength*
-DOMSVGLengthList::GetItemWithoutAddRef(PRUint32 aIndex)
+DOMSVGLengthList::GetItemAt(PRUint32 aIndex)
 {
   if (IsAnimValList()) {
     Element()->FlushAnimations();
   }
   if (aIndex < Length()) {
     EnsureItemAt(aIndex);
     return mItems[aIndex];
   }
@@ -215,17 +230,17 @@ DOMSVGLengthList::Initialize(nsIDOMSVGLe
   Clear();
   return InsertItemBefore(newItem, 0, _retval);
 }
 
 NS_IMETHODIMP
 DOMSVGLengthList::GetItem(PRUint32 index,
                           nsIDOMSVGLength **_retval)
 {
-  *_retval = GetItemWithoutAddRef(index);
+  *_retval = GetItemAt(index);
   if (!*_retval) {
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
   NS_ADDREF(*_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/content/svg/content/src/DOMSVGLengthList.h
+++ b/content/svg/content/src/DOMSVGLengthList.h
@@ -64,29 +64,32 @@ class DOMSVGLength;
  * DOMSVGLength. We are a friend of DOMSVGAnimatedLengthList, and are
  * responsible for nulling out our DOMSVGAnimatedLengthList's pointer to us
  * when we die, essentially making its pointer to us a weak pointer. Similarly,
  * our DOMSVGLength items are friends of us and responsible for nulling out our
  * pointers to them.
  *
  * Our DOM items are created lazily on demand as and when script requests them.
  */
-class DOMSVGLengthList : public nsIDOMSVGLengthList
+class DOMSVGLengthList : public nsIDOMSVGLengthList,
+                         public nsWrapperCache
 {
   friend class DOMSVGLength;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGLengthList)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGLengthList)
   NS_DECL_NSIDOMSVGLENGTHLIST
 
   DOMSVGLengthList(DOMSVGAnimatedLengthList *aAList,
                    const SVGLengthList &aInternalList)
     : mAList(aAList)
   {
+    SetIsProxy();
+
     // aInternalList must be passed in explicitly because we can't use
     // InternalList() here. (Because it depends on IsAnimValList, which depends
     // on this object having been assigned to aAList's mBaseVal or mAnimVal,
     // which hasn't happend yet.)
     
     InternalListLengthWillChange(aInternalList.Length()); // Sync mItems
   }
 
@@ -94,29 +97,35 @@ public:
     // Our mAList's weak ref to us must be nulled out when we die. If GC has
     // unlinked us using the cycle collector code, then that has already
     // happened, and mAList is null.
     if (mAList) {
       ( IsAnimValList() ? mAList->mAnimVal : mAList->mBaseVal ) = nsnull;
     }
   };
 
+  virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                               bool *triedToWrap);
+
+  nsISupports* GetParentObject()
+  {
+    return static_cast<nsIContent*>(Element());
+  }
+
   /**
    * This will normally be the same as InternalList().Length(), except if we've
    * hit OOM in which case our length will be zero.
    */
   PRUint32 Length() const {
     NS_ABORT_IF_FALSE(mItems.Length() == 0 ||
                       mItems.Length() == InternalList().Length(),
                       "DOM wrapper's list length is out of sync");
     return mItems.Length();
   }
 
-  nsIDOMSVGLength* GetItemWithoutAddRef(PRUint32 aIndex);
-
   /// Called to notify us to syncronize our length and detach excess items.
   void InternalListLengthWillChange(PRUint32 aNewLength);
 
 private:
 
   nsSVGElement* Element() const {
     return mAList->mElement;
   }
--- a/content/svg/content/src/DOMSVGNumberList.cpp
+++ b/content/svg/content/src/DOMSVGNumberList.cpp
@@ -35,16 +35,18 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsSVGElement.h"
 #include "DOMSVGNumberList.h"
 #include "DOMSVGNumber.h"
 #include "nsDOMError.h"
 #include "SVGAnimatedNumberList.h"
 #include "nsCOMPtr.h"
+#include "nsContentUtils.h"
+#include "dombindings.h"
 
 // See the comment in this file's header.
 
 namespace mozilla {
 
 // local helper functions
 namespace {
 
@@ -67,38 +69,52 @@ void UpdateListIndicesFromIndex(nsTArray
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our DOMSVGAnimatedNumberList's weak ref to us to be safe. (The other
 // option would be to not unlink and rely on the breaking of the other edges in
 // the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
 NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGNumberList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGNumberList)
   // No need to null check tmp - script/SMIL can't detach us from mAList
   ( tmp->IsAnimValList() ? tmp->mAList->mAnimVal : tmp->mAList->mBaseVal ) = nsnull;
-NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGNumberList)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGNumberList)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGNumberList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGNumberList)
 
 } // namespace mozilla
 DOMCI_DATA(SVGNumberList, mozilla::DOMSVGNumberList)
 namespace mozilla {
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGNumberList)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGNumberList)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGNumberList)
 NS_INTERFACE_MAP_END
 
 
+JSObject*
+DOMSVGNumberList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                             bool *triedToWrap)
+{
+  return mozilla::dom::binding::SVGNumberList::create(cx, scope, this,
+                                                      triedToWrap);
+}
+
 nsIDOMSVGNumber*
-DOMSVGNumberList::GetItemWithoutAddRef(PRUint32 aIndex)
+DOMSVGNumberList::GetItemAt(PRUint32 aIndex)
 {
   if (IsAnimValList()) {
     Element()->FlushAnimations();
   }
   if (aIndex < Length()) {
     EnsureItemAt(aIndex);
     return mItems[aIndex];
   }
@@ -215,17 +231,17 @@ DOMSVGNumberList::Initialize(nsIDOMSVGNu
   Clear();
   return InsertItemBefore(newItem, 0, _retval);
 }
 
 NS_IMETHODIMP
 DOMSVGNumberList::GetItem(PRUint32 index,
                           nsIDOMSVGNumber **_retval)
 {
-  *_retval = GetItemWithoutAddRef(index);
+  *_retval = GetItemAt(index);
   if (!*_retval) {
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
   NS_ADDREF(*_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/content/svg/content/src/DOMSVGNumberList.h
+++ b/content/svg/content/src/DOMSVGNumberList.h
@@ -63,29 +63,32 @@ class DOMSVGNumber;
  * DOMSVGNumber. We are a friend of DOMSVGAnimatedNumberList, and are
  * responsible for nulling out our DOMSVGAnimatedNumberList's pointer to us
  * when we die, essentially making its pointer to us a weak pointer. Similarly,
  * our DOMSVGNumber items are friends of us and responsible for nulling out our
  * pointers to them.
  *
  * Our DOM items are created lazily on demand as and when script requests them.
  */
-class DOMSVGNumberList : public nsIDOMSVGNumberList
+class DOMSVGNumberList : public nsIDOMSVGNumberList,
+                         public nsWrapperCache
 {
   friend class DOMSVGNumber;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGNumberList)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGNumberList)
   NS_DECL_NSIDOMSVGNUMBERLIST
 
   DOMSVGNumberList(DOMSVGAnimatedNumberList *aAList,
                    const SVGNumberList &aInternalList)
     : mAList(aAList)
   {
+    SetIsProxy();
+
     // aInternalList must be passed in explicitly because we can't use
     // InternalList() here. (Because it depends on IsAnimValList, which depends
     // on this object having been assigned to aAList's mBaseVal or mAnimVal,
     // which hasn't happend yet.)
 
     InternalListLengthWillChange(aInternalList.Length()); // Sync mItems
   }
 
@@ -93,29 +96,35 @@ public:
     // Our mAList's weak ref to us must be nulled out when we die. If GC has
     // unlinked us using the cycle collector code, then that has already
     // happened, and mAList is null.
     if (mAList) {
       ( IsAnimValList() ? mAList->mAnimVal : mAList->mBaseVal ) = nsnull;
     }
   }
 
+  virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                               bool *triedToWrap);
+
+  nsISupports* GetParentObject()
+  {
+    return static_cast<nsIContent*>(Element());
+  }
+
   /**
    * This will normally be the same as InternalList().Length(), except if we've
    * hit OOM in which case our length will be zero.
    */
   PRUint32 Length() const {
     NS_ABORT_IF_FALSE(mItems.Length() == 0 ||
                       mItems.Length() == InternalList().Length(),
                       "DOM wrapper's list length is out of sync");
     return mItems.Length();
   }
 
-  nsIDOMSVGNumber* GetItemWithoutAddRef(PRUint32 aIndex);
-
   /// Called to notify us to syncronize our length and detach excess items.
   void InternalListLengthWillChange(PRUint32 aNewLength);
 
 private:
 
   nsSVGElement* Element() const {
     return mAList->mElement;
   }
--- a/content/svg/content/src/DOMSVGPathSegList.cpp
+++ b/content/svg/content/src/DOMSVGPathSegList.cpp
@@ -37,34 +37,49 @@
 #include "nsSVGElement.h"
 #include "DOMSVGPathSegList.h"
 #include "DOMSVGPathSeg.h"
 #include "nsDOMError.h"
 #include "SVGAnimatedPathSegList.h"
 #include "nsCOMPtr.h"
 #include "nsSVGAttrTearoffTable.h"
 #include "SVGPathSegUtils.h"
+#include "dombindings.h"
+#include "nsContentUtils.h"
 
 // See the comment in this file's header.
 
 namespace mozilla {
 
 static nsSVGAttrTearoffTable<void, DOMSVGPathSegList>
   sSVGPathSegListTearoffTable;
 
-NS_SVG_VAL_IMPL_CYCLE_COLLECTION(DOMSVGPathSegList, mElement)
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPathSegList)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPathSegList)
+  // No unlinking of mElement, we'd need to null out the value pointer (the
+  // object it points to is held by the element) and null-check it everywhere.
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPathSegList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mElement, nsIContent)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGPathSegList)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGPathSegList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGPathSegList)
 
 } // namespace mozilla
 DOMCI_DATA(SVGPathSegList, mozilla::DOMSVGPathSegList)
 namespace mozilla {
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGPathSegList)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGPathSegList)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGPathSegList)
 NS_INTERFACE_MAP_END
 
 
 /* static */ already_AddRefed<DOMSVGPathSegList>
 DOMSVGPathSegList::GetDOMWrapper(void *aList,
@@ -92,18 +107,26 @@ DOMSVGPathSegList::~DOMSVGPathSegList()
   // There are now no longer any references to us held by script or list items.
   // Note we must use GetAnimValKey/GetBaseValKey here, NOT InternalList()!
   void *key = mIsAnimValList ?
     InternalAList().GetAnimValKey() :
     InternalAList().GetBaseValKey();
   sSVGPathSegListTearoffTable.RemoveTearoff(key);
 }
 
+JSObject*
+DOMSVGPathSegList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                              bool *triedToWrap)
+{
+  return mozilla::dom::binding::SVGPathSegList::create(cx, scope, this,
+                                                       triedToWrap);
+}
+
 nsIDOMSVGPathSeg*
-DOMSVGPathSegList::GetItemWithoutAddRef(PRUint32 aIndex)
+DOMSVGPathSegList::GetItemAt(PRUint32 aIndex)
 {
   if (IsAnimValList()) {
     Element()->FlushAnimations();
   }
   if (aIndex < Length()) {
     EnsureItemAt(aIndex);
     return ItemAt(aIndex);
   }
@@ -322,17 +345,17 @@ DOMSVGPathSegList::Initialize(nsIDOMSVGP
   Clear();
   return InsertItemBefore(aNewItem, 0, _retval);
 }
 
 NS_IMETHODIMP
 DOMSVGPathSegList::GetItem(PRUint32 aIndex,
                            nsIDOMSVGPathSeg **_retval)
 {
-  *_retval = GetItemWithoutAddRef(aIndex);
+  *_retval = GetItemAt(aIndex);
   if (!*_retval) {
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
   NS_ADDREF(*_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/content/svg/content/src/DOMSVGPathSegList.h
+++ b/content/svg/content/src/DOMSVGPathSegList.h
@@ -73,25 +73,34 @@ class SVGAnimatedPathSegList;
  * DOMSVGAnimatedLengthList) is contained in this class.
  *
  * This class is strongly intertwined with DOMSVGPathSeg. Our DOMSVGPathSeg
  * items are friends of us and responsible for nulling out our pointers to
  * them when they die.
  *
  * Our DOM items are created lazily on demand as and when script requests them.
  */
-class DOMSVGPathSegList : public nsIDOMSVGPathSegList
+class DOMSVGPathSegList : public nsIDOMSVGPathSegList,
+                          public nsWrapperCache
 {
   friend class DOMSVGPathSeg;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGPathSegList)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGPathSegList)
   NS_DECL_NSIDOMSVGPATHSEGLIST
 
+  virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                               bool *triedToWrap);
+
+  nsISupports* GetParentObject()
+  {
+    return static_cast<nsIContent*>(mElement);
+  }
+
   /**
    * Factory method to create and return a DOMSVGPathSegList wrapper
    * for a given internal SVGPathData object. The factory takes care
    * of caching the object that it returns so that the same object can be
    * returned for the given SVGPathData each time it is requested.
    * The cached object is only removed from the cache when it is destroyed due
    * to there being no more references to it or to any of its descendant
    * objects. If that happens, any subsequent call requesting the DOM wrapper
@@ -123,18 +132,16 @@ public:
    */
   PRUint32 Length() const {
     NS_ABORT_IF_FALSE(mItems.Length() == 0 ||
                       mItems.Length() == InternalList().CountItems(),
                       "DOM wrapper's list length is out of sync");
     return mItems.Length();
   }
 
-  nsIDOMSVGPathSeg* GetItemWithoutAddRef(PRUint32 aIndex);
-
   /**
    * WATCH OUT! If you add code to call this on a baseVal wrapper, then you
    * must also call it on the animVal wrapper too if necessary!! See other
    * callers!
    *
    * Called by internal code to notify us when we need to sync the length of
    * this DOM list with its internal list. This is called immediately prior to
    * the length of the internal list being changed so that any DOM list items
@@ -159,16 +166,18 @@ private:
   /**
    * Only our static GetDOMWrapper() factory method may create objects of our
    * type.
    */
   DOMSVGPathSegList(nsSVGElement *aElement, bool aIsAnimValList)
     : mElement(aElement)
     , mIsAnimValList(aIsAnimValList)
   {
+    SetIsProxy();
+
     InternalListWillChangeTo(InternalList()); // Sync mItems
   }
 
   ~DOMSVGPathSegList();
 
   nsSVGElement* Element() {
     return mElement.get();
   }
--- a/content/svg/content/src/DOMSVGPointList.cpp
+++ b/content/svg/content/src/DOMSVGPointList.cpp
@@ -36,16 +36,18 @@
 
 #include "nsSVGElement.h"
 #include "DOMSVGPointList.h"
 #include "DOMSVGPoint.h"
 #include "nsDOMError.h"
 #include "SVGAnimatedPointList.h"
 #include "nsCOMPtr.h"
 #include "nsSVGAttrTearoffTable.h"
+#include "nsContentUtils.h"
+#include "dombindings.h"
 
 // See the comment in this file's header.
 
 // local helper functions
 namespace {
 
 using mozilla::DOMSVGPoint;
 
@@ -64,26 +66,39 @@ UpdateListIndicesFromIndex(nsTArray<DOMS
 
 } // namespace
 
 namespace mozilla {
 
 static nsSVGAttrTearoffTable<void, DOMSVGPointList>
   sSVGPointListTearoffTable;
 
-NS_SVG_VAL_IMPL_CYCLE_COLLECTION(DOMSVGPointList, mElement)
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPointList)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPointList)
+  // No unlinking of mElement, we'd need to null out the value pointer (the
+  // object it points to is held by the element) and null-check it everywhere.
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPointList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mElement, nsIContent)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGPointList)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGPointList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGPointList)
 
 } // namespace mozilla
 DOMCI_DATA(SVGPointList, mozilla::DOMSVGPointList)
 namespace mozilla {
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGPointList)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGPointList)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGPointList)
 NS_INTERFACE_MAP_END
 
 
 /* static */ already_AddRefed<DOMSVGPointList>
 DOMSVGPointList::GetDOMWrapper(void *aList,
@@ -111,18 +126,26 @@ DOMSVGPointList::~DOMSVGPointList()
   // There are now no longer any references to us held by script or list items.
   // Note we must use GetAnimValKey/GetBaseValKey here, NOT InternalList()!
   void *key = mIsAnimValList ?
     InternalAList().GetAnimValKey() :
     InternalAList().GetBaseValKey();
   sSVGPointListTearoffTable.RemoveTearoff(key);
 }
 
+JSObject*
+DOMSVGPointList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                            bool *triedToWrap)
+{
+  return mozilla::dom::binding::SVGPointList::create(cx, scope, this,
+                                                     triedToWrap);
+}
+
 nsIDOMSVGPoint*
-DOMSVGPointList::GetItemWithoutAddRef(PRUint32 aIndex)
+DOMSVGPointList::GetItemAt(PRUint32 aIndex)
 {
   if (IsAnimValList()) {
     Element()->FlushAnimations();
   }
   if (aIndex < Length()) {
     EnsureItemAt(aIndex);
     return mItems[aIndex];
   }
@@ -266,17 +289,17 @@ DOMSVGPointList::Initialize(nsIDOMSVGPoi
   Clear();
   return InsertItemBefore(aNewItem, 0, _retval);
 }
 
 NS_IMETHODIMP
 DOMSVGPointList::GetItem(PRUint32 aIndex,
                          nsIDOMSVGPoint **_retval)
 {
-  *_retval = GetItemWithoutAddRef(aIndex);
+  *_retval = GetItemAt(aIndex);
   if (!*_retval) {
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
   NS_ADDREF(*_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/content/svg/content/src/DOMSVGPointList.h
+++ b/content/svg/content/src/DOMSVGPointList.h
@@ -73,25 +73,34 @@ class SVGAnimatedPointList;
  * DOMSVGAnimatedLengthList) is contained in this class.
  *
  * This class is strongly intertwined with DOMSVGPoint. Our DOMSVGPoint
  * items are friends of us and responsible for nulling out our pointers to
  * them when they die.
  *
  * Our DOM items are created lazily on demand as and when script requests them.
  */
-class DOMSVGPointList : public nsIDOMSVGPointList
+class DOMSVGPointList : public nsIDOMSVGPointList,
+                        public nsWrapperCache
 {
   friend class DOMSVGPoint;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGPointList)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGPointList)
   NS_DECL_NSIDOMSVGPOINTLIST
 
+  virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                               bool *triedToWrap);
+
+  nsISupports* GetParentObject()
+  {
+    return static_cast<nsIContent*>(mElement);
+  }
+
   /**
    * Factory method to create and return a DOMSVGPointList wrapper
    * for a given internal SVGPointList object. The factory takes care
    * of caching the object that it returns so that the same object can be
    * returned for the given SVGPointList each time it is requested.
    * The cached object is only removed from the cache when it is destroyed due
    * to there being no more references to it or to any of its descendant
    * objects. If that happens, any subsequent call requesting the DOM wrapper
@@ -123,18 +132,16 @@ public:
    */
   PRUint32 Length() const {
     NS_ABORT_IF_FALSE(mItems.Length() == 0 ||
                       mItems.Length() == InternalList().Length(),
                       "DOM wrapper's list length is out of sync");
     return mItems.Length();
   }
 
-  nsIDOMSVGPoint* GetItemWithoutAddRef(PRUint32 aIndex);
-
   /**
    * WATCH OUT! If you add code to call this on a baseVal wrapper, then you
    * must also call it on the animVal wrapper too if necessary!! See other
    * callers!
    *
    * Called by internal code to notify us when we need to sync the length of
    * this DOM list with its internal list. This is called immediately prior to
    * the length of the internal list being changed so that any DOM list items
@@ -159,16 +166,18 @@ private:
   /**
    * Only our static GetDOMWrapper() factory method may create objects of our
    * type.
    */
   DOMSVGPointList(nsSVGElement *aElement, bool aIsAnimValList)
     : mElement(aElement)
     , mIsAnimValList(aIsAnimValList)
   {
+    SetIsProxy();
+
     InternalListWillChangeTo(InternalList()); // Sync mItems
   }
 
   ~DOMSVGPointList();
 
   nsSVGElement* Element() {
     return mElement.get();
   }
--- a/content/svg/content/src/DOMSVGTransformList.cpp
+++ b/content/svg/content/src/DOMSVGTransformList.cpp
@@ -37,16 +37,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "DOMSVGTransformList.h"
 #include "DOMSVGTransform.h"
 #include "DOMSVGMatrix.h"
 #include "SVGAnimatedTransformList.h"
 #include "nsSVGElement.h"
+#include "nsContentUtils.h"
+#include "dombindings.h"
 
 // local helper functions
 namespace {
 
 void UpdateListIndicesFromIndex(
   nsTArray<mozilla::DOMSVGTransform*>& aItemsArray,
   PRUint32 aStartingIndex)
 {
@@ -67,40 +69,54 @@ namespace mozilla {
 // clear our DOMSVGAnimatedTransformList's weak ref to us to be safe. (The other
 // option would be to not unlink and rely on the breaking of the other edges in
 // the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
 NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGTransformList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGTransformList)
   // No need to null check tmp - script/SMIL can't detach us from mAList
   ( tmp->IsAnimValList() ? tmp->mAList->mAnimVal : tmp->mAList->mBaseVal ) =
     nsnull;
-NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGTransformList)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGTransformList)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGTransformList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGTransformList)
 
 } // namespace mozilla
 DOMCI_DATA(SVGTransformList, mozilla::DOMSVGTransformList)
 namespace mozilla {
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGTransformList)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGTransformList)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGTransformList)
 NS_INTERFACE_MAP_END
 
 //----------------------------------------------------------------------
 // DOMSVGTransformList methods:
 
+JSObject*
+DOMSVGTransformList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                                bool *triedToWrap)
+{
+  return mozilla::dom::binding::SVGTransformList::create(cx, scope, this,
+                                                         triedToWrap);
+}
+
 nsIDOMSVGTransform*
-DOMSVGTransformList::GetItemWithoutAddRef(PRUint32 aIndex)
+DOMSVGTransformList::GetItemAt(PRUint32 aIndex)
 {
   if (IsAnimValList()) {
     Element()->FlushAnimations();
   }
   if (aIndex < Length()) {
     EnsureItemAt(aIndex);
     return mItems[aIndex];
   }
@@ -229,17 +245,17 @@ DOMSVGTransformList::Initialize(nsIDOMSV
   Clear();
   return InsertItemBefore(newItem, 0, _retval);
 }
 
 /* nsIDOMSVGTransform getItem (in unsigned long index); */
 NS_IMETHODIMP
 DOMSVGTransformList::GetItem(PRUint32 index, nsIDOMSVGTransform **_retval)
 {
-  *_retval = GetItemWithoutAddRef(index);
+  *_retval = GetItemAt(index);
   if (!*_retval) {
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
   NS_ADDREF(*_retval);
   return NS_OK;
 }
 
 /* nsIDOMSVGTransform insertItemBefore (in nsIDOMSVGTransform newItem,
--- a/content/svg/content/src/DOMSVGTransformList.h
+++ b/content/svg/content/src/DOMSVGTransformList.h
@@ -59,29 +59,32 @@ class DOMSVGTransform;
 /**
  * Class DOMSVGTransformList
  *
  * This class is used to create the DOM tearoff objects that wrap internal
  * SVGTransformList objects.
  *
  * See the architecture comment in DOMSVGAnimatedTransformList.h.
  */
-class DOMSVGTransformList : public nsIDOMSVGTransformList
+class DOMSVGTransformList : public nsIDOMSVGTransformList,
+                            public nsWrapperCache
 {
   friend class DOMSVGTransform;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGTransformList)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGTransformList)
   NS_DECL_NSIDOMSVGTRANSFORMLIST
 
   DOMSVGTransformList(DOMSVGAnimatedTransformList *aAList,
                       const SVGTransformList &aInternalList)
     : mAList(aAList)
   {
+    SetIsProxy();
+
     // aInternalList must be passed in explicitly because we can't use
     // InternalList() here. (Because it depends on IsAnimValList, which depends
     // on this object having been assigned to aAList's mBaseVal or mAnimVal,
     // which hasn't happend yet.)
 
     InternalListLengthWillChange(aInternalList.Length()); // Sync mItems
   }
 
@@ -89,29 +92,35 @@ public:
     // Our mAList's weak ref to us must be nulled out when we die. If GC has
     // unlinked us using the cycle collector code, then that has already
     // happened, and mAList is null.
     if (mAList) {
       ( IsAnimValList() ? mAList->mAnimVal : mAList->mBaseVal ) = nsnull;
     }
   }
 
+  virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
+                               bool *triedToWrap);
+
+  nsISupports* GetParentObject()
+  {
+    return static_cast<nsIContent*>(Element());
+  }
+
   /**
    * This will normally be the same as InternalList().Length(), except if we've
    * hit OOM in which case our length will be zero.
    */
   PRUint32 Length() const {
     NS_ABORT_IF_FALSE(mItems.IsEmpty() ||
       mItems.Length() == InternalList().Length(),
       "DOM wrapper's list length is out of sync");
     return mItems.Length();
   }
 
-  nsIDOMSVGTransform* GetItemWithoutAddRef(PRUint32 aIndex);
-
   /// Called to notify us to synchronize our length and detach excess items.
   void InternalListLengthWillChange(PRUint32 aNewLength);
 
 private:
 
   nsSVGElement* Element() const {
     return mAList->mElement;
   }
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -10635,17 +10635,17 @@ nsSVGListSH<ListInterfaceType, ListType>
 
     // If this assertion fires the QI implementation for the object in
     // question doesn't use the nsIDOMSVGXXXList pointer as the nsISupports
     // pointer. That must be fixed, or we'll crash...
     NS_ABORT_IF_FALSE(list_qi == list, "Uh, fix QI!");
   }
 #endif
 
-  return list->GetItemWithoutAddRef(aIndex);
+  return list->GetItemAt(aIndex);
 }
 
 
 // SVGStringList helper
 
 nsresult
 nsSVGStringListSH::GetStringAt(nsISupports *aNative, PRInt32 aIndex,
                                nsAString& aResult)
--- a/dom/interfaces/base/nsIDOMClientRectList.idl
+++ b/dom/interfaces/base/nsIDOMClientRectList.idl
@@ -37,10 +37,11 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "domstubs.idl"
 
 [scriptable, uuid(917da19d-62f5-441d-b47e-9e35f05639c9)]
 interface nsIDOMClientRectList : nsISupports
 {
   readonly attribute unsigned long length;
-  nsIDOMClientRect              item(in unsigned long index);
+  [getter,forward(getItemAt)] nsIDOMClientRect        item(in unsigned long index);
+  [noscript,notxpcom,nostdcall] nsIDOMClientRect getItemAt(in unsigned long index);
 };
--- a/dom/interfaces/events/nsIDOMPaintRequestList.idl
+++ b/dom/interfaces/events/nsIDOMPaintRequestList.idl
@@ -39,10 +39,11 @@
 #include "domstubs.idl"
 
 interface nsIDOMPaintRequest;
 
 [scriptable, uuid(01627136-fdd8-44b4-aac0-7d613608a3d4)]
 interface nsIDOMPaintRequestList : nsISupports
 {
   readonly attribute unsigned long length;
-  nsIDOMPaintRequest item(in unsigned long index);
+  [getter,forward(getItemAt)] nsIDOMPaintRequest        item(in unsigned long index);
+  [noscript,notxpcom,nostdcall] nsIDOMPaintRequest getItemAt(in unsigned long index);
 };
--- a/dom/interfaces/events/nsIDOMTouchEvent.idl
+++ b/dom/interfaces/events/nsIDOMTouchEvent.idl
@@ -68,17 +68,18 @@ interface nsIDOMTouch : nsISupports {
     bool mChanged;
     PRUint32 mMessage;
   %}
 };
 
 [scriptable, uuid(60706eb7-d50d-4379-b01c-e78e6af84213)]
 interface nsIDOMTouchList : nsISupports {
   readonly attribute unsigned long length;
-  nsIDOMTouch item(in unsigned long index);
+  [getter,forward(getItemAt)] nsIDOMTouch item(in unsigned long index);
+  [noscript,notxpcom,nostdcall] nsIDOMTouch getItemAt(in unsigned long index);
   nsIDOMTouch identifiedTouch(in long identifier);
 };
 
 [scriptable, uuid(0cc687df-0ed5-4b7f-b89d-cbb99b21d23a)]
 interface nsIDOMTouchEvent : nsIDOMUIEvent {
   readonly attribute nsIDOMTouchList touches;
   readonly attribute nsIDOMTouchList targetTouches;
   readonly attribute nsIDOMTouchList changedTouches;
--- a/dom/interfaces/svg/nsIDOMSVGLengthList.idl
+++ b/dom/interfaces/svg/nsIDOMSVGLengthList.idl
@@ -47,16 +47,17 @@ interface nsIDOMSVGLengthList : nsISuppo
   readonly attribute unsigned long length;  // synonym for numberOfItems
 
   void clear();
           // raises(nsIDOMDOMException);
   nsIDOMSVGLength initialize(in nsIDOMSVGLength newItem );
                     // raises(nsIDOMDOMException, nsIDOMSVGException);
   nsIDOMSVGLength getItem(in unsigned long index);
                     // raises(nsIDOMDOMException);
+  [getter,noscript,notxpcom,nostdcall] nsIDOMSVGLength getItemAt(in unsigned long index);
   nsIDOMSVGLength insertItemBefore(in nsIDOMSVGLength newItem, in unsigned long index);
                     // raises(nsIDOMDOMException, nsIDOMSVGException);
   nsIDOMSVGLength replaceItem(in nsIDOMSVGLength newItem, in unsigned long index);
                     // raises(nsIDOMDOMException, nsIDOMSVGException);
   nsIDOMSVGLength removeItem(in unsigned long index);
                     // raises(nsIDOMDOMException);
   nsIDOMSVGLength appendItem(in nsIDOMSVGLength newItem);
                     // raises(nsIDOMDOMException, nsIDOMSVGException);
--- a/dom/interfaces/svg/nsIDOMSVGNumberList.idl
+++ b/dom/interfaces/svg/nsIDOMSVGNumberList.idl
@@ -47,16 +47,17 @@ interface nsIDOMSVGNumberList : nsISuppo
   readonly attribute unsigned long length;  // synonym for numberOfItems
 
   void clear();
           // raises(nsIDOMDOMException);
   nsIDOMSVGNumber initialize(in nsIDOMSVGNumber newItem );
                     // raises(nsIDOMDOMException, nsIDOMSVGException);
   nsIDOMSVGNumber getItem(in unsigned long index);
                     // raises(nsIDOMDOMException);
+  [getter,noscript,notxpcom,nostdcall] nsIDOMSVGNumber getItemAt(in unsigned long index);
   nsIDOMSVGNumber insertItemBefore(in nsIDOMSVGNumber newItem, in unsigned long index);
                     // raises(nsIDOMDOMException, nsIDOMSVGException);
   nsIDOMSVGNumber replaceItem(in nsIDOMSVGNumber newItem, in unsigned long index);
                     // raises(nsIDOMDOMException, nsIDOMSVGException);
   nsIDOMSVGNumber removeItem(in unsigned long index);
                     // raises(nsIDOMDOMException);
   nsIDOMSVGNumber appendItem(in nsIDOMSVGNumber newItem);
                     // raises(nsIDOMDOMException, nsIDOMSVGException);
--- a/dom/interfaces/svg/nsIDOMSVGPathSegList.idl
+++ b/dom/interfaces/svg/nsIDOMSVGPathSegList.idl
@@ -47,16 +47,17 @@ interface nsIDOMSVGPathSegList : nsISupp
   readonly attribute unsigned long length;  // synonym for numberOfItems
 
   void clear();
           // raises(nsIDOMDOMException);
   nsIDOMSVGPathSeg initialize(in nsIDOMSVGPathSeg newItem );
                     // raises(nsIDOMDOMException, nsIDOMSVGException);
   nsIDOMSVGPathSeg getItem(in unsigned long index);
                     // raises(nsIDOMDOMException);
+  [getter,noscript,notxpcom,nostdcall] nsIDOMSVGPathSeg getItemAt(in unsigned long index);
   nsIDOMSVGPathSeg insertItemBefore(in nsIDOMSVGPathSeg newItem, in unsigned long index);
                     // raises(nsIDOMDOMException, nsIDOMSVGException);
   nsIDOMSVGPathSeg replaceItem(in nsIDOMSVGPathSeg newItem, in unsigned long index);
                     // raises(nsIDOMDOMException, nsIDOMSVGException);
   nsIDOMSVGPathSeg removeItem(in unsigned long index);
                     // raises(nsIDOMDOMException);
   nsIDOMSVGPathSeg appendItem(in nsIDOMSVGPathSeg newItem);
                     // raises(nsIDOMDOMException, nsIDOMSVGException);
--- a/dom/interfaces/svg/nsIDOMSVGPointList.idl
+++ b/dom/interfaces/svg/nsIDOMSVGPointList.idl
@@ -47,16 +47,17 @@ interface nsIDOMSVGPointList : nsISuppor
   readonly attribute unsigned long length;  // synonym for numberOfItems
 
   void clear();
       // raises( DOMException );
   nsIDOMSVGPoint initialize(in nsIDOMSVGPoint newItem);
       // raises( DOMException, SVGException );
   nsIDOMSVGPoint getItem (in unsigned long index);
       // raises( DOMException );
+  [getter,noscript,notxpcom,nostdcall] nsIDOMSVGPoint getItemAt(in unsigned long index);
   nsIDOMSVGPoint insertItemBefore(in nsIDOMSVGPoint newItem, in unsigned long index);
       // raises( DOMException, SVGException );
   nsIDOMSVGPoint replaceItem(in nsIDOMSVGPoint newItem, in unsigned long index);
       // raises( DOMException, SVGException );
   nsIDOMSVGPoint removeItem(in unsigned long index);
       // raises( DOMException );
   nsIDOMSVGPoint appendItem(in nsIDOMSVGPoint newItem);
       //  raises( DOMException, SVGException );
--- a/dom/interfaces/svg/nsIDOMSVGTransformList.idl
+++ b/dom/interfaces/svg/nsIDOMSVGTransformList.idl
@@ -48,16 +48,17 @@ interface nsIDOMSVGTransformList : nsISu
   readonly attribute unsigned long length; // synonym for numberOfItems
 
   void clear();
       // raises( DOMException );
   nsIDOMSVGTransform initialize(in nsIDOMSVGTransform newItem);
       // raises( DOMException, SVGException );
   nsIDOMSVGTransform getItem(in unsigned long index);
       // raises( DOMException );
+  [getter,noscript,notxpcom,nostdcall] nsIDOMSVGTransform getItemAt(in unsigned long index);
   nsIDOMSVGTransform insertItemBefore(in nsIDOMSVGTransform newItem,
                                       in unsigned long index);
       //  raises( DOMException, SVGException );
   nsIDOMSVGTransform replaceItem(in nsIDOMSVGTransform newItem,
                                  in unsigned long index);
       // raises( DOMException, SVGException );
   nsIDOMSVGTransform removeItem(in unsigned long index);
       //  raises( DOMException );
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -1483,26 +1483,26 @@ nsNPAPIPluginInstance::URLRedirectRespon
 
 NPError
 nsNPAPIPluginInstance::InitAsyncSurface(NPSize *size, NPImageFormat format,
                                         void *initData, NPAsyncSurface *surface)
 {
   if (mOwner)
     return mOwner->InitAsyncSurface(size, format, initData, surface);
 
-  return NS_ERROR_FAILURE;
+  return NPERR_GENERIC_ERROR;
 }
 
 NPError
 nsNPAPIPluginInstance::FinalizeAsyncSurface(NPAsyncSurface *surface)
 {
   if (mOwner)
     return mOwner->FinalizeAsyncSurface(surface);
 
-  return NS_ERROR_FAILURE;
+  return NPERR_GENERIC_ERROR;
 }
 
 void
 nsNPAPIPluginInstance::SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed)
 {
   if (mOwner)
     mOwner->SetCurrentAsyncSurface(surface, changed);
 }
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -799,22 +799,22 @@ NPBool nsPluginInstanceOwner::ConvertPoi
   // we should implement this for all platforms
   return false;
 #endif
 }
 
 NPError nsPluginInstanceOwner::InitAsyncSurface(NPSize *size, NPImageFormat format,
                                                 void *initData, NPAsyncSurface *surface)
 {
-  return NPERR_GENERIC_ERROR;
+  return NPERR_INCOMPATIBLE_VERSION_ERROR;
 }
 
 NPError nsPluginInstanceOwner::FinalizeAsyncSurface(NPAsyncSurface *)
 {
-  return NPERR_GENERIC_ERROR;
+  return NPERR_INCOMPATIBLE_VERSION_ERROR;
 }
 
 void nsPluginInstanceOwner::SetCurrentAsyncSurface(NPAsyncSurface *, NPRect*)
 {
 }
 
 NS_IMETHODIMP nsPluginInstanceOwner::GetTagType(nsPluginTagType *result)
 {
--- a/gfx/thebes/gfxQtPlatform.cpp
+++ b/gfx/thebes/gfxQtPlatform.cpp
@@ -88,16 +88,18 @@ static QPaintEngine::Type sDefaultQtPain
 gfxFontconfigUtils *gfxQtPlatform::sFontconfigUtils = nsnull;
 static cairo_user_data_key_t cairo_qt_pixmap_key;
 static void do_qt_pixmap_unref (void *data)
 {
     QPixmap *pmap = (QPixmap*)data;
     delete pmap;
 }
 
+static gfxImageFormat sOffscreenFormat = gfxASurface::ImageFormatRGB24;
+
 #ifndef MOZ_PANGO
 typedef nsDataHashtable<nsStringHashKey, nsRefPtr<FontFamily> > FontTable;
 typedef nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<FontEntry> > > PrefFontTable;
 static FontTable *gPlatformFonts = NULL;
 static FontTable *gPlatformFontAliases = NULL;
 static PrefFontTable *gPrefFonts = NULL;
 static gfxSparseBitSet *gCodepointsWithNoFonts = NULL;
 static FT_Library gPlatformFTLibrary = NULL;
@@ -146,16 +148,19 @@ gfxQtPlatform::gfxQtPlatform()
             break;
         default:
             mRenderMode = RENDER_QPAINTER;
     }
 
     // Qt doesn't provide a public API to detect the graphicssystem type. We hack
     // around this by checking what type of graphicssystem a test QPixmap uses.
     QPixmap pixmap(1, 1);
+    if (pixmap.depth() == 16) {
+        sOffscreenFormat = gfxASurface::ImageFormatRGB16_565;
+    }
 #if (QT_VERSION < QT_VERSION_CHECK(4,8,0))
     if (pixmap.paintEngine())
         sDefaultQtPaintEngineType = pixmap.paintEngine()->type();
 #endif
 }
 
 gfxQtPlatform::~gfxQtPlatform()
 {
@@ -584,14 +589,10 @@ gfxQtPlatform::GetDPI()
     QDesktopWidget* rootWindow = qApp->desktop();
     PRInt32 dpi = rootWindow->logicalDpiY(); // y-axis DPI for fonts
     return dpi <= 0 ? 96 : dpi;
 }
 
 gfxImageFormat
 gfxQtPlatform::GetOffscreenFormat()
 {
-    if (qApp->desktop()->depth() == 16) {
-        return gfxASurface::ImageFormatRGB16_565;
-    }
-
-    return gfxASurface::ImageFormatRGB24;
+    return sOffscreenFormat;
 }
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -1906,19 +1906,16 @@ echo-tier-dirs:
 	@$(foreach tier,$(TIERS),echo '$(tier):'; echo '  dirs: $(tier_$(tier)_dirs)'; echo '  staticdirs: $(tier_$(tier)_staticdirs)'; )
 
 echo-dirs:
 	@echo $(DIRS)
 
 echo-module:
 	@echo $(MODULE)
 
-echo-requires:
-	@echo $(REQUIRES)
-
 echo-depth-path:
 	@$(topsrcdir)/build/unix/print-depth-path.sh
 
 echo-module-name:
 	@$(topsrcdir)/build/package/rpm/print-module-name.sh
 
 echo-module-filelist:
 	@$(topsrcdir)/build/package/rpm/print-module-filelist.sh
@@ -2015,17 +2012,16 @@ endif
 FREEZE_VARIABLES = \
   CSRCS \
   CPPSRCS \
   EXPORTS \
   XPIDLSRCS \
   DIRS \
   LIBRARY \
   MODULE \
-  REQUIRES \
   SHORT_LIBNAME \
   TIERS \
   EXTRA_COMPONENTS \
   EXTRA_PP_COMPONENTS \
   $(NULL)
 
 $(foreach var,$(FREEZE_VARIABLES),$(eval $(var)_FROZEN := '$($(var))'))
 
--- a/js/xpconnect/src/Makefile.in
+++ b/js/xpconnect/src/Makefile.in
@@ -92,16 +92,17 @@ CPPSRCS		= \
 
 include $(topsrcdir)/config/config.mk
 
 LOCAL_INCLUDES = \
 		-I$(srcdir)/../wrappers \
 		-I$(srcdir)/../loader \
 		-I$(topsrcdir)/caps/include \
 		-I$(topsrcdir)/content/base/src \
+		-I$(topsrcdir)/content/events/src \
 		-I$(topsrcdir)/content/html/content/src \
 		-I$(topsrcdir)/content/html/document/src \
 		-I$(topsrcdir)/content/svg/content/src \
 		-I$(topsrcdir)/layout/style \
 		-I$(topsrcdir)/layout/base \
 		-I$(topsrcdir)/dom/base \
 		-I$(topsrcdir)/xpcom/ds \
 		$(NULL)
--- a/js/xpconnect/src/codegen.py
+++ b/js/xpconnect/src/codegen.py
@@ -264,17 +264,17 @@ def writeArgumentUnboxing(f, i, name, ty
                     % (type.name, argVal, name, name, argPtr))
             f.write("    if (NS_FAILED(rv)) {\n")
             if isSetter:
                 f.write("        xpc_qsThrowBadSetterValue("
                         "cx, rv, JSVAL_TO_OBJECT(*tvr.jsval_addr()), id);\n")
             elif haveCcx:
                 f.write("        xpc_qsThrowBadArgWithCcx(ccx, rv, %d);\n" % i)
             else:
-                f.write("        xpc_qsThrowBadArg(cx, rv, vp, %d);\n" % i)
+                f.write("        xpc_qsThrowBadArgWithDetails(cx, rv, %d, %s, %s);\n" % (i, "\"\"", "\"\""))
             f.write("        return JS_FALSE;\n"
                     "    }\n")
             return True
 
     warn("Unable to unbox argument of type %s (native type %s)" % (type.name, typeName))
     if i is None:
         src = '*vp'
     else:
--- a/js/xpconnect/src/dombindings.conf
+++ b/js/xpconnect/src/dombindings.conf
@@ -1,17 +1,32 @@
 classes = {
     'NodeList': 'nsINodeList',
     'HTMLCollection': 'nsIHTMLCollection',
     'HTMLOptionsCollection': 'nsHTMLOptionCollection',
     }
 prefableClasses = {
     'DOMTokenList': 'nsDOMTokenList',
     'DOMSettableTokenList': 'nsDOMSettableTokenList',
+    'ClientRectList': 'nsClientRectList',
+    'PaintRequestList': 'nsPaintRequestList',
+    'TouchList': 'nsDOMTouchList',
+    'FileList': 'nsDOMFileList',
+    'SVGLengthList': 'mozilla::DOMSVGLengthList',
+    'SVGNumberList': 'mozilla::DOMSVGNumberList',
+    'SVGPathSegList': 'mozilla::DOMSVGPathSegList',
+    'SVGPointList': 'mozilla::DOMSVGPointList',
+    'SVGTransformList': 'mozilla::DOMSVGTransformList',
     }
 
 irregularFilenames = {
     'nsHTMLOptionCollection': 'nsHTMLSelectElement',
+    'nsClientRectList': 'nsClientRect',
+    'nsPaintRequestList': 'nsPaintRequest',
+    'nsIDOMTouch': 'nsIDOMTouchEvent',
+    'nsIDOMTouchList': 'nsIDOMTouchEvent',
+    'nsDOMTouchList': 'nsDOMTouchEvent',
+    'nsDOMFileList': 'nsDOMFile',
     }
 
 customInheritance = {
     'nsIDOMHTMLOptionsCollection': 'nsIDOMHTMLCollection',
     }
--- a/js/xpconnect/src/dombindingsgen.py
+++ b/js/xpconnect/src/dombindingsgen.py
@@ -321,33 +321,38 @@ def completeConfiguration(conf, includeP
     for iface in stubbedInterfaces:
         for member in iface.stubMembers:
             checkStubMember(member)
 
     return interfaces
 
 # === Generating the header file
 
-def needsForwardDeclaration(type):
-    return isInterfaceType(type) or (type.kind == 'native' and type.specialtype is None)
-
-def getTypes(classes, map={}):
+def addType(types, type, map):
     def getTranslatedType(type):
         return map.get(type, type)
 
+    type = xpidl.unaliasType(type)
+    if isInterfaceType(type) or (type.kind == 'native' and type.specialtype is None):
+        types.add(getTranslatedType(type.name))
+
+
+def getTypes(classes, map):
     types = set()
     for clazz in classes.itervalues():
-        types.add(getTranslatedType(clazz.nativeClass))
-        if clazz.indexGetter and needsForwardDeclaration(clazz.realIndexGetter.realtype):
-            types.add(getTranslatedType(clazz.realIndexGetter.realtype.name))
-        if clazz.indexSetter and needsForwardDeclaration(clazz.realIndexSetter.realtype):
-            types.add(getTranslatedType(clazz.realIndexSetter.realtype.name))
-        if clazz.nameGetter and needsForwardDeclaration(clazz.realNameGetter.realtype):
-            types.add(getTranslatedType(clazz.realNameGetter.realtype.name))
-    return sorted(types)
+        types.add(map.get(clazz.nativeClass, clazz.nativeClass))
+        if clazz.indexGetter:
+            addType(types, clazz.realIndexGetter.realtype, map)
+        if clazz.indexSetter:
+            addType(types, clazz.realIndexSetter.realtype, map)
+        if clazz.nameGetter:
+            addType(types, clazz.realNameGetter.realtype, map)
+        if clazz.nameSetter:
+            addType(types, clazz.realNameSetter.realtype, map)
+    return types
 
 listDefinitionTemplate = (
 "class ${name} {\n"
 "public:\n"
 "    template<typename I>\n"
 "    static JSObject *create(JSContext *cx, XPCWrappedNativeScope *scope, I *list, bool *triedToWrap)\n"
 "    {\n"
 "        return create(cx, scope, list, GetWrapperCache(list), triedToWrap);\n"
@@ -368,17 +373,17 @@ def writeHeaderFile(filename, config):
     headerMacro = '__gen_%s__' % filename.replace('.', '_')
     f = open(filename, 'w')
     try:
         f.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n"
                 "#ifndef " + headerMacro + "\n"
                 "#define " + headerMacro + "\n\n")
 
         namespaces = []
-        for type in getTypes(config.classes, {}):
+        for type in sorted(getTypes(config.classes, {})):
             newNamespaces = type.split('::')
             type = newNamespaces.pop()
             j = 0
             for i in range(min(len(namespaces), len(newNamespaces))):
                 if namespaces[i] != newNamespaces[i]:
                     break
                 j += 1
             for i in range(j, len(namespaces)):
@@ -628,40 +633,30 @@ def writeMethodStub(f, classname, method
 
 def writeStubFile(filename, config, interfaces):
     print "Creating stub file", filename
     make_targets.append(filename)
 
     f = open(filename, 'w')
     filesIncluded = set()
 
-    def includeType(type):
-        type = unaliasType(type)
-        if type.kind in ('builtin', 'native'):
-            return None
-        file = conf.irregularFilenames.get(type.name, type.name) + '.h'
-        if file not in filesIncluded:
-            f.write('#include "%s"\n' % file)
-            filesIncluded.add(file)
-        return type
-
-    def writeIncludesForMember(member):
-        assert member.kind in ('attribute', 'method')
-        resulttype = includeType(member.realtype)
-        if member.kind == 'method':
-            for p in member.params:
-                includeType(p.realtype)
-        return resulttype
-
     headerFilename = re.sub(r'(\.cpp)?$', '.h', filename)
 
     try:
         f.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n")
 
-        f.write("".join([("#include \"%s.h\"\n" % re.sub(r'(([^:]+::)*)', '', type)) for type in getTypes(config.classes, config.irregularFilenames)]))
+        types = getTypes(config.classes, config.irregularFilenames)
+        for clazz in config.classes.itervalues():
+            for member in clazz.members:
+                addType(types, member.realtype, config.irregularFilenames)
+                if member.kind == 'method':
+                    for p in member.params:
+                        addType(types, p.realtype, config.irregularFilenames)
+
+        f.write("".join([("#include \"%s.h\"\n" % re.sub(r'(([^:]+::)*)', '', type)) for type in sorted(types)]))
         f.write("\n")
 
         f.write("namespace mozilla {\n"
                 "namespace dom {\n"
                 "namespace binding {\n\n")
 
         f.write("// Property name ids\n\n")
 
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -2446,36 +2446,34 @@ gfxPoint3D GetDeltaToMozTransformOrigin(
 }
 
 /* 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.
  */
 static
 gfxPoint3D GetDeltaToMozPerspectiveOrigin(const nsIFrame* aFrame,
-                                          float aAppUnitsPerPixel,
-                                          const nsRect* aBoundsOverride)
+                                          float aAppUnitsPerPixel)
 {
   NS_PRECONDITION(aFrame, "Can't get delta for a null frame!");
   NS_PRECONDITION(aFrame->GetStyleDisplay()->HasTransform(),
                   "Can't get a delta for an untransformed frame!");
   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?
   // How do we handle aBoundsOverride in the latter case?
   nsIFrame* parent = aFrame->GetParentStyleContextFrame();
   const nsStyleDisplay* display = aFrame->GetParent()->GetStyleDisplay();
-  nsRect boundingRect = (aBoundsOverride ? *aBoundsOverride :
-                         nsDisplayTransform::GetFrameBoundsForTransform(parent));
+  nsRect boundingRect = nsDisplayTransform::GetFrameBoundsForTransform(parent);
 
   /* Allows us to access named variables by index. */
   gfxPoint3D result;
   result.z = 0.0f;
   gfxFloat* coords[2] = {&result.x, &result.y};
   const nscoord* dimensions[2] =
     {&boundingRect.width, &boundingRect.height};
 
@@ -2549,18 +2547,19 @@ nsDisplayTransform::GetResultingTransfor
   gfx3DMatrix result;
   /* Transformed frames always have a transform, or are preserving 3d (and might still have perspective!) */
   if (disp->mSpecifiedTransform) {
     result = nsStyleTransformMatrix::ReadTransforms(disp->mSpecifiedTransform,
                                                     aFrame->GetStyleContext(),
                                                     aFrame->PresContext(),
                                                     dummy, bounds, aAppUnitsPerPixel);
   } else {
-     NS_ASSERTION(aFrame->GetStyleDisplay()->mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D,
-                  "If we don't have a transform, then we must be at least attempting to preserve the transforms of our children");
+     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");
   }
 
   const nsStyleDisplay* parentDisp = nsnull;
   nsStyleContext* parentStyleContext = aFrame->GetStyleContext()->GetParent();
   if (parentStyleContext) {
     parentDisp = parentStyleContext->GetStyleDisplay();
   }
   if (nsLayoutUtils::Are3DTransformsEnabled() &&
@@ -2568,17 +2567,17 @@ nsDisplayTransform::GetResultingTransfor
       parentDisp->mChildPerspective.GetCoordValue() > 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, aBoundsOverride);
+    gfxPoint3D toPerspectiveOrigin = GetDeltaToMozPerspectiveOrigin(aFrame, aAppUnitsPerPixel);
     result = result * nsLayoutUtils::ChangeMatrixBasis(toPerspectiveOrigin - toMozOrigin, perspective);
   }
 
   if (aFrame->Preserves3D() && nsLayoutUtils::Are3DTransformsEnabled()) {
       // Include the transform set on our parent
       NS_ASSERTION(aFrame->GetParent() &&
                    aFrame->GetParent()->IsTransformed() &&
                    aFrame->GetParent()->Preserves3DChildren(),
--- a/layout/base/tests/Makefile.in
+++ b/layout/base/tests/Makefile.in
@@ -180,16 +180,17 @@ DEFINES += -D_IMPL_NS_LAYOUT
 		bug583889_inner2.html \
 		test_bug582771.html \
 		test_bug603550.html \
 		test_bug629838.html \
 		test_bug646757.html \
 		test_bug718809.html \
 		test_font_inflation_reftests.html \
 		test_bug725426.html \
+		test_bug731777.html \
 		$(NULL)
 
 # Tests for bugs 441782, 467672 and 570378 don't pass reliably on Windows, because of bug 469208
 ifeq (,$(filter windows,$(MOZ_WIDGET_TOOLKIT)))
 # THESE TESTS (BELOW) DO NOT RUN ON WINDOWS
 _TEST_FILES += \
 		bidi_numeral_test.js \
 		$(NULL)
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/test_bug731777.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Bug 731777</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <style>
+    #container {
+      position: relative;
+      height: 300px;
+      width: 300px;
+      margin: 50px 100px;
+      border: 2px solid blue;
+      background-color: #044B0A;
+      
+      -moz-perspective: 500px;
+      overflow:hidden;
+  }
+
+  #inner {
+      margin: 0px;
+      width: 480px;
+      border: 2px solid blue;
+      height: 220px;
+      background-color: #844BCA;
+      
+      -moz-transform: rotateY(91deg) translateX(0px) translateZ(0px);
+      -moz-transition: 5s;
+  }
+    
+  </style>
+</head>
+<body>
+<div id="container">
+  <div id="inner"></div>
+</div>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 731777 **/
+
+is(document.elementFromPoint(325,170), document.getElementById("inner"), "Able to hit transformed object");
+is(document.elementFromPoint(405,170), document.getElementById("inner"), "Able to hit transformed object");
+
+</script>
+</pre>
+</body>
+</html>
--- a/layout/forms/nsFileControlFrame.cpp
+++ b/layout/forms/nsFileControlFrame.cpp
@@ -154,67 +154,16 @@ nsFileControlFrame::DestroyFrom(nsIFrame
   }
   nsContentUtils::DestroyAnonymousContent(&mTextContent);
 
   mCaptureMouseListener->ForgetFrame();
   mMouseListener->ForgetFrame();
   nsBlockFrame::DestroyFrom(aDestructRoot);
 }
 
-struct CaptureCallbackData {
-  nsICapturePicker* picker;
-  PRUint32* mode;
-};
-
-typedef struct CaptureCallbackData CaptureCallbackData;
-
-bool CapturePickerAcceptCallback(const nsAString& aAccept, void* aClosure)
-{
-  nsresult rv;
-  bool captureEnabled;
-  CaptureCallbackData* closure = (CaptureCallbackData*)aClosure;
-
-  if (StringBeginsWith(aAccept,
-                       NS_LITERAL_STRING("image/"))) {
-    rv = closure->picker->ModeMayBeAvailable(nsICapturePicker::MODE_STILL,
-                                             &captureEnabled);
-    NS_ENSURE_SUCCESS(rv, true);
-    if (captureEnabled) {
-      *closure->mode = nsICapturePicker::MODE_STILL;
-      return false;
-    }
-  } else if (StringBeginsWith(aAccept,
-                              NS_LITERAL_STRING("audio/"))) {
-    rv = closure->picker->ModeMayBeAvailable(nsICapturePicker::MODE_AUDIO_CLIP,
-                                             &captureEnabled);
-    NS_ENSURE_SUCCESS(rv, true);
-    if (captureEnabled) {
-      *closure->mode = nsICapturePicker::MODE_AUDIO_CLIP;
-      return false;
-    }
-  } else if (StringBeginsWith(aAccept,
-                              NS_LITERAL_STRING("video/"))) {
-    rv = closure->picker->ModeMayBeAvailable(nsICapturePicker::MODE_VIDEO_CLIP,
-                                             &captureEnabled);
-    NS_ENSURE_SUCCESS(rv, true);
-    if (captureEnabled) {
-      *closure->mode = nsICapturePicker::MODE_VIDEO_CLIP;
-      return false;
-    }
-    rv = closure->picker->ModeMayBeAvailable(nsICapturePicker::MODE_VIDEO_NO_SOUND_CLIP,
-                                             &captureEnabled);
-    NS_ENSURE_SUCCESS(rv, true);
-    if (captureEnabled) {
-      *closure->mode = nsICapturePicker::MODE_VIDEO_NO_SOUND_CLIP;
-      return false;
-    }
-  }
-  return true;
-}
-
 nsresult
 nsFileControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
 {
   // Get the NodeInfoManager and tag necessary to create input elements
   nsCOMPtr<nsIDocument> doc = mContent->GetDocument();
 
   nsCOMPtr<nsINodeInfo> nodeInfo;
   nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::input, nsnull,
@@ -277,25 +226,22 @@ nsFileControlFrame::CreateAnonymousConte
 
   mBrowse->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
                    NS_LITERAL_STRING("button"), false);
 
   // Create the capture button
   nsCOMPtr<nsICapturePicker> capturePicker;
   capturePicker = do_GetService("@mozilla.org/capturepicker;1");
   if (capturePicker) {
-    PRUint32 mode = 0;
-
     CaptureCallbackData data;
     data.picker = capturePicker;
-    data.mode = &mode;
-    ParseAcceptAttribute(&CapturePickerAcceptCallback, (void*)&data);
+    data.mode = GetCaptureMode(data);
 
-    if (mode != 0) {
-      mCaptureMouseListener->mMode = mode;
+    if (data.mode != 0) {
+      mCaptureMouseListener->mMode = data.mode;
       nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::input, nsnull,
                                                      kNameSpaceID_XHTML,
                                                      nsIDOMNode::ELEMENT_NODE);
       NS_NewHTMLElement(getter_AddRefs(mCapture), nodeInfo.forget(),
                         dom::NOT_FROM_PARSER);
       if (!mCapture)
         return NS_ERROR_OUT_OF_MEMORY;
 
@@ -742,26 +688,58 @@ nsFileControlFrame::CreateAccessible()
   if (!accService)
     return nsnull;
 
   return accService->CreateHTMLFileInputAccessible(mContent,
                                                    PresContext()->PresShell());
 }
 #endif
 
-void 
-nsFileControlFrame::ParseAcceptAttribute(AcceptAttrCallback aCallback,
-                                         void* aClosure) const
+PRUint32
+nsFileControlFrame::GetCaptureMode(const CaptureCallbackData& aData)
 {
-  nsAutoString accept;
-  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accept, accept);
+  PRInt32 filters = nsHTMLInputElement::FromContent(mContent)->GetFilterFromAccept();
+  nsresult rv;
+  bool captureEnabled;
+
+  if (filters == nsIFilePicker::filterImages) {
+    rv = aData.picker->ModeMayBeAvailable(nsICapturePicker::MODE_STILL,
+                                             &captureEnabled);
+    NS_ENSURE_SUCCESS(rv, 0);
+    if (captureEnabled) {
+      return nsICapturePicker::MODE_STILL;
+    }
+    return 0;
+  }
 
-  HTMLSplitOnSpacesTokenizer tokenizer(accept, ',');
-  // Empty loop body because aCallback is doing the work
-  while (tokenizer.hasMoreTokens() &&
-         (*aCallback)(tokenizer.nextToken(), aClosure));
+  if (filters == nsIFilePicker::filterAudio) {
+    rv = aData.picker->ModeMayBeAvailable(nsICapturePicker::MODE_AUDIO_CLIP,
+                                             &captureEnabled);
+    NS_ENSURE_SUCCESS(rv, 0);
+    if (captureEnabled) {
+      return nsICapturePicker::MODE_AUDIO_CLIP;
+    }
+    return 0;
+  }
+
+  if (filters == nsIFilePicker::filterVideo) {
+    rv = aData.picker->ModeMayBeAvailable(nsICapturePicker::MODE_VIDEO_CLIP,
+                                             &captureEnabled);
+    NS_ENSURE_SUCCESS(rv, 0);
+    if (captureEnabled) {
+      return nsICapturePicker::MODE_VIDEO_CLIP;
+    }
+    rv = aData.picker->ModeMayBeAvailable(nsICapturePicker::MODE_VIDEO_NO_SOUND_CLIP,
+                                             &captureEnabled);
+    NS_ENSURE_SUCCESS(rv, 0);
+    if (captureEnabled) {
+      return nsICapturePicker::MODE_VIDEO_NO_SOUND_CLIP;
+    }
+    return 0;
+  }
+  
+  return 0;
 }
-
 ////////////////////////////////////////////////////////////
 // Mouse listener implementation
 
 NS_IMPL_ISUPPORTS1(nsFileControlFrame::MouseListener,
                    nsIDOMEventListener)
--- a/layout/forms/nsFileControlFrame.h
+++ b/layout/forms/nsFileControlFrame.h
@@ -89,23 +89,29 @@ public:
 
   // nsIAnonymousContentCreator
   virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements);
   virtual void AppendAnonymousContentTo(nsBaseContentList& aElements,
                                         PRUint32 aFilter);
 
 #ifdef ACCESSIBILITY
   virtual already_AddRefed<nsAccessible> CreateAccessible();
-#endif
+#endif  
 
   typedef bool (*AcceptAttrCallback)(const nsAString&, void*);
-  void ParseAcceptAttribute(AcceptAttrCallback aCallback, void* aClosure) const;
 
 protected:
-
+  
+  struct CaptureCallbackData {
+    nsICapturePicker* picker;
+    PRUint32 mode;
+  };
+  
+  PRUint32 GetCaptureMode(const CaptureCallbackData& aData);
+  
   class MouseListener;
   friend class MouseListener;
   class MouseListener : public nsIDOMEventListener {
   public:
     NS_DECL_ISUPPORTS
     
     MouseListener(nsFileControlFrame* aFrame) :
       mFrame(aFrame)
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -990,16 +990,28 @@ nsIFrame::HasPerspective() const
   if (parentDisp &&
       parentDisp->mChildPerspective.GetUnit() == eStyleUnit_Coord &&
       parentDisp->mChildPerspective.GetCoordValue() > 0.0) {
     return true;
   }
   return false;
 }
 
+bool
+nsIFrame::ChildrenHavePerspective() const
+{
+  const nsStyleDisplay *disp = GetStyleContext()->GetStyleDisplay();
+  if (disp &&
+      disp->mChildPerspective.GetUnit() == eStyleUnit_Coord &&
+      disp->mChildPerspective.GetCoordValue() > 0.0) {
+    return true;
+  }
+  return false;
+}
+
 nsRect
 nsIFrame::GetContentRectRelativeToSelf() const
 {
   nsMargin bp(GetUsedBorderAndPadding());
   ApplySkipSides(bp);
   nsRect r(0, 0, mRect.width, mRect.height);
   r.Deflate(bp);
   return r;
@@ -6766,22 +6778,27 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
     nsRect newBounds(nsPoint(0, 0), aNewSize);
     // Transform affects both overflow areas.
     NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
       nsRect& o = aOverflowAreas.Overflow(otype);
       o = nsDisplayTransform::TransformRect(o, this, nsPoint(0, 0), &newBounds);
     }
     if (Preserves3DChildren()) {
       ComputePreserve3DChildrenOverflow(aOverflowAreas, newBounds);
-    } else if (HasPerspective()) {
-      RecomputePerspectiveChildrenOverflow(this, &newBounds);
+    } else if (ChildrenHavePerspective()) {
+      RecomputePerspectiveChildrenOverflow(this->GetStyleContext(), &newBounds);
     }
   } else {
     Properties().Delete(nsIFrame::PreTransformOverflowAreasProperty());
-  }
+    if (ChildrenHavePerspective()) {
+      nsRect newBounds(nsPoint(0, 0), aNewSize);
+      RecomputePerspectiveChildrenOverflow(this->GetStyleContext(), &newBounds);
+    }
+  }
+    
 
   bool anyOverflowChanged;
   if (aOverflowAreas != nsOverflowAreas(bounds, bounds)) {
     anyOverflowChanged = SetOverflowAreas(aOverflowAreas);
   } else {
     anyOverflowChanged = ClearOverflowRects();
   }
 
@@ -6828,17 +6845,17 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
     InvalidateLayer(aOverflowAreas.VisualOverflow(),
                     nsDisplayItem::TYPE_TRANSFORM);
   }
 
   return anyOverflowChanged;
 }
 
 void
-nsIFrame::RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame, const nsRect* aBounds)
+nsIFrame::RecomputePerspectiveChildrenOverflow(const nsStyleContext* aStartStyle, const nsRect* aBounds)
 {
   // Children may check our size when getting our transform, make sure it's valid.
   nsSize oldSize = GetSize();
   if (aBounds) {
     SetSize(aBounds->Size());
   }
   nsIFrame::ChildListIterator lists(this);
   for (; !lists.IsDone(); lists.Next()) {
@@ -6851,18 +6868,21 @@ nsIFrame::RecomputePerspectiveChildrenOv
         nsRect bounds(nsPoint(0, 0), child->GetSize());
         if (overflow) {
           child->FinishAndStoreOverflow(*overflow, bounds.Size());
         } else {
           nsOverflowAreas boundsOverflow;
           boundsOverflow.SetAllTo(bounds);
           child->FinishAndStoreOverflow(boundsOverflow, bounds.Size());
         }
-      } else if (child->GetParentStyleContextFrame() != aStartFrame) {
-        child->RecomputePerspectiveChildrenOverflow(aStartFrame, nsnull);
+      } else if (child->GetStyleContext()->GetParent() == aStartStyle ||
+                 child->GetStyleContext() == aStartStyle) {
+        // Recurse into frames with the same style context, or a direct
+        // child style context.
+        child->RecomputePerspectiveChildrenOverflow(aStartStyle, nsnull);
       }
     }
   }
   // Restore our old size just in case something depends on this elesewhere.
   SetSize(oldSize);
 }
 
 /* The overflow rects for leaf nodes in a preserve-3d hierarchy depends on
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1240,20 +1240,22 @@ public:
   /**
    * Returns whether this frame has a parent that Preserves3DChildren() and
    * can respect this. Returns false if the frame is clipped.
    */
   bool Preserves3D() const;
 
   bool HasPerspective() const;
 
+  bool ChildrenHavePerspective() const;
+
   // Calculate the overflow size of all child frames, taking preserve-3d into account
   void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas, const nsRect& aBounds);
 
-  void RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame, const nsRect* aBounds);
+  void RecomputePerspectiveChildrenOverflow(const nsStyleContext* aStartStyle, const nsRect* aBounds);
 
   /**
    * Event handling of GUI events.
    *
    * @param   aEvent event structure describing the type of event and rge widget
    *            where the event originated
    *          The |point| member of this is in the coordinate system of the
    *          view returned by GetOffsetFromView.
new file mode 100644
--- /dev/null
+++ b/layout/reftests/transform-3d/backface-visibility-2-ref.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<body>
+	<style>
+	#container {
+		position: relative;
+		margin: 10px auto;
+		width: 450px;
+		height: 281px;
+		z-index: 1;
+		-moz-perspective: 1000px;
+	}
+	#card {
+		width: 100%;
+		height: 100%;
+		-moz-transform-style: preserve-3d;
+        -moz-transform: rotateY(165deg);
+	}
+	.face {
+		position: absolute;
+		width: 100%;
+		height: 100%;
+        -moz-backface-visibility: hidden;
+        background: red;
+	}
+	.face.back {
+		display: block;
+		-moz-transform: rotateY(180deg);
+		-moz-box-sizing: border-box;
+		padding: 10px;
+		color: white;
+		text-align: center;
+		background: green;
+	}
+	</style>
+	
+	<div id="container" class="hover">
+		<div id="card">
+			<div class="back face">
+			</div>
+  		</div>
+    </div>
+</body></html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/transform-3d/backface-visibility-2.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<body>
+	<style>
+	#container {
+		position: relative;
+		margin: 10px auto;
+		width: 450px;
+		height: 281px;
+		z-index: 1;
+		-moz-perspective: 1000px;
+	}
+	#card {
+		width: 100%;
+		height: 100%;
+		-moz-transform-style: preserve-3d;
+        -moz-transform: rotateY(165deg);
+	}
+	.face {
+		position: absolute;
+		width: 100%;
+		height: 100%;
+        -moz-backface-visibility: hidden;
+        background: red;
+	}
+	.face.back {
+		display: block;
+		-moz-transform: rotateY(180deg);
+		-moz-box-sizing: border-box;
+		padding: 10px;
+		color: white;
+		text-align: center;
+		background: green;
+	}
+	</style>
+	
+	<div id="container" class="hover">
+		<div id="card">
+			<div class="front face">
+			</div>
+			<div class="back face">
+			</div>
+  		</div>
+    </div>
+</body></html>
--- a/layout/reftests/transform-3d/reftest.list
+++ b/layout/reftests/transform-3d/reftest.list
@@ -29,16 +29,17 @@ fails-if(Android) == scale3d-all-separat
 == translate3d-1a.html translate3d-1-ref.html
 == matrix3d-1a.html matrix3d-1-ref.html
 == matrix3d-2a.html matrix3d-2-ref.html
 == rotate3d-1a.html rotatex-1-ref.html
 == rotate3d-2a.html rotatey-1-ref.html
 != backface-visibility-1a.html about:blank
 == backface-visibility-1b.html about:blank
 == backface-visibility-1c.html about:blank
+== backface-visibility-2.html backface-visibility-2-ref.html
 != perspective-origin-1a.html rotatex-perspective-1a.html
 == perspective-origin-1b.html perspective-origin-1a.html
 == perspective-origin-2a.html perspective-origin-2-ref.html
 != sorting-1a.html sorting-1-ref.html
 # Parallel planes, different z depth
 == sorting-2a.html sorting-2-ref.html
 # Parallel planes, same z depth (shouldn't be sorted!)
 == sorting-2b.html sorting-2-ref.html
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1661,17 +1661,19 @@ struct nsStyleDisplay {
     // mOverflowX and mOverflowY always match when one of them is
     // NS_STYLE_OVERFLOW_VISIBLE or NS_STYLE_OVERFLOW_CLIP.
     return mOverflowX != NS_STYLE_OVERFLOW_VISIBLE &&
            mOverflowX != NS_STYLE_OVERFLOW_CLIP;
   }
 
   /* Returns whether the element has the -moz-transform property. */
   bool HasTransform() const {
-    return mSpecifiedTransform != nsnull || mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D;
+    return mSpecifiedTransform != nsnull || 
+           mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
+           mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN;
   }
 };
 
 struct nsStyleTable {
   nsStyleTable(void);
   nsStyleTable(const nsStyleTable& aOther);
   ~nsStyleTable(void);
 
--- a/mobile/android/base/AwesomeBar.java
+++ b/mobile/android/base/AwesomeBar.java
@@ -47,16 +47,17 @@ import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.Configuration;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.os.Build;
 import android.os.Bundle;
 import android.text.Editable;
+import android.text.Spanned;
 import android.text.TextWatcher;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.KeyEvent;
 import android.view.MenuInflater;
 import android.view.MenuItem;
@@ -190,30 +191,42 @@ public class AwesomeBar extends Activity
                 }
 
                 return false;
             }
         });
 
         mText.addTextChangedListener(new TextWatcher() {
             public void afterTextChanged(Editable s) {
-                // do nothing
+                String text = s.toString();
+                mAwesomeTabs.filter(text);
+
+                // If awesome bar has compositing string, don't call updateGoButton().
+                // Since that method resets IME, composing state will be borken.
+                Object[] spans = s.getSpans(0, s.length(), Object.class);
+                if (spans != null) {
+                    for (Object span : spans) {
+                        if ((s.getSpanFlags(span) & Spanned.SPAN_COMPOSING) != 0) {
+                            // Found composition string.
+                            return;
+                        }
+                    }
+                }
+                // no composition string. It is safe to update IME flags.
+                updateGoButton(text);
             }
 
             public void beforeTextChanged(CharSequence s, int start, int count,
                                           int after) {
                 // do nothing
             }
 
             public void onTextChanged(CharSequence s, int start, int before,
                                       int count) {
-                String text = s.toString();
-
-                mAwesomeTabs.filter(text);
-                updateGoButton(text);
+                // do nothing
             }
         });
 
         mText.setOnKeyListener(new View.OnKeyListener() {
             public boolean onKey(View v, int keyCode, KeyEvent event) {
                 if (keyCode == KeyEvent.KEYCODE_ENTER) {
                     if (event.getAction() != KeyEvent.ACTION_DOWN)
                         return true;
--- a/mobile/android/components/build/Makefile.in
+++ b/mobile/android/components/build/Makefile.in
@@ -48,22 +48,16 @@ MODULE          = browsercomps
 LIBRARY_NAME    = browsercomps
 LIBXUL_LIBRARY  = 1
 
 IS_COMPONENT	= 1
 EXPORT_LIBRARY  = 1
 
 EXPORTS = nsBrowserComponents.h
 
-REQUIRES	= \
-		  xpcom \
-		  string \
-		  pref \
-		  $(NULL)
-
 XPIDL_MODULE = browsercomps
 
 XPIDLSRCS = nsIShellService.idl
 
 CPPSRCS = \
 	nsBrowserModule.cpp \
 	nsShellService.cpp \
 	$(NULL)
--- a/mobile/xul/components/build/Makefile.in
+++ b/mobile/xul/components/build/Makefile.in
@@ -48,22 +48,16 @@ MODULE          = browsercomps
 LIBRARY_NAME    = browsercomps
 LIBXUL_LIBRARY  = 1
 
 IS_COMPONENT	= 1
 EXPORT_LIBRARY  = 1
 
 EXPORTS = nsBrowserComponents.h
 
-REQUIRES	= \
-		  xpcom \
-		  string \
-		  pref \
-		  $(NULL)
-
 XPIDL_MODULE = browsercomps
 
 XPIDLSRCS = nsIShellService.idl
 
 CPPSRCS = \
 	nsBrowserModule.cpp \
 	nsShellService.cpp \
 	$(NULL)
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -128,22 +128,30 @@ public:
   ~TelemetryImpl();
   
   static bool CanRecord();
   static already_AddRefed<nsITelemetry> CreateTelemetryInstance();
   static void ShutdownTelemetry();
   static void RecordSlowStatement(const nsACString &statement,
                                   const nsACString &dbName,
                                   PRUint32 delay);
+  static void RecordChromeHang(PRUint32 duration,
+                               const Telemetry::HangStack &callStack,
+                               SharedLibraryInfo &moduleMap);
   static nsresult GetHistogramEnumId(const char *name, Telemetry::ID *id);
   struct StmtStats {
     PRUint32 hitCount;
     PRUint32 totalTime;
   };
   typedef nsBaseHashtableET<nsCStringHashKey, StmtStats> SlowSQLEntryType;
+  struct HangReport {
+    PRUint32 duration;
+    Telemetry::HangStack callStack;
+    SharedLibraryInfo moduleMap;
+  };
 
 private:
   static bool StatementReflector(SlowSQLEntryType *entry, JSContext *cx,
                                  JSObject *obj);
   bool AddSQLInfo(JSContext *cx, JSObject *rootObj, bool mainThread);
 
   // Like GetHistogramById, but returns the underlying C++ object, not the JS one.
   nsresult GetHistogramByName(const nsACString &name, Histogram **ret);
@@ -176,16 +184,18 @@ private:
   bool mCanRecord;
   static TelemetryImpl *sTelemetry;
   AutoHashtable<SlowSQLEntryType> mSlowSQLOnMainThread;
   AutoHashtable<SlowSQLEntryType> mSlowSQLOnOtherThread;
   // This gets marked immutable in debug builds, so we can't use
   // AutoHashtable here.
   nsTHashtable<nsCStringHashKey> mTrackedDBs;
   Mutex mHashMutex;
+  nsTArray<HangReport> mHangReports;
+  Mutex mHangReportsMutex;
 };
 
 TelemetryImpl*  TelemetryImpl::sTelemetry = NULL;
 
 // A initializer to initialize histogram collection
 StatisticsRecorder gStatisticsRecorder;
 
 // Hardcoded probes
@@ -455,17 +465,18 @@ WrapAndReturnHistogram(Histogram *h, JSC
   *ret = OBJECT_TO_JSVAL(obj);
   JS_SetPrivate(obj, h);
   return NS_OK;
 }
 
 TelemetryImpl::TelemetryImpl():
 mHistogramMap(Telemetry::HistogramCount),
 mCanRecord(XRE_GetProcessType() == GeckoProcessType_Default),
-mHashMutex("Telemetry::mHashMutex")
+mHashMutex("Telemetry::mHashMutex"),
+mHangReportsMutex("Telemetry::mHangReportsMutex")
 {
   // A whitelist to prevent Telemetry reporting on Addon & Thunderbird DBs
   const char *trackedDBs[] = {
     "addons.sqlite", "chromeappsstore.sqlite", "content-prefs.sqlite",
     "cookies.sqlite", "downloads.sqlite", "extensions.sqlite",
     "formhistory.sqlite", "index.sqlite", "permissions.sqlite", "places.sqlite",
     "search.sqlite", "signons.sqlite", "urlclassifier3.sqlite",
     "webappsstore.sqlite"
@@ -938,16 +949,154 @@ TelemetryImpl::GetSlowSQL(JSContext *cx,
   // Add info about slow SQL queries on other threads
   if (!AddSQLInfo(cx, root_obj, false))
     return NS_ERROR_FAILURE;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+TelemetryImpl::GetChromeHangs(JSContext *cx, jsval *ret)
+{
+  MutexAutoLock hangReportMutex(mHangReportsMutex);
+  JSObject *reportArray = JS_NewArrayObject(cx, 0, nsnull);
+  if (!reportArray) {
+    return NS_ERROR_FAILURE;
+  }
+  *ret = OBJECT_TO_JSVAL(reportArray);
+
+  // Each hang report is an object in the 'chromeHangs' array
+  for (size_t i = 0; i < mHangReports.Length(); ++i) {
+    JSObject *reportObj = JS_NewObject(cx, NULL, NULL, NULL);
+    if (!reportObj) {
+      return NS_ERROR_FAILURE;
+    }
+    jsval reportObjVal = OBJECT_TO_JSVAL(reportObj);
+    if (!JS_SetElement(cx, reportArray, i, &reportObjVal)) {
+      return NS_ERROR_FAILURE;
+    }
+
+    // Record the hang duration (expressed in seconds)
+    JSBool ok = JS_DefineProperty(cx, reportObj, "duration",
+                                  INT_TO_JSVAL(mHangReports[i].duration),
+                                  NULL, NULL, JSPROP_ENUMERATE);
+    if (!ok) {
+      return NS_ERROR_FAILURE;
+    }
+
+    // Represent call stack PCs as strings
+    // (JS can't represent all 64-bit integer values)
+    JSObject *pcArray = JS_NewArrayObject(cx, 0, nsnull);
+    if (!pcArray) {
+      return NS_ERROR_FAILURE;
+    }
+    ok = JS_DefineProperty(cx, reportObj, "stack", OBJECT_TO_JSVAL(pcArray),
+                           NULL, NULL, JSPROP_ENUMERATE);
+    if (!ok) {
+      return NS_ERROR_FAILURE;
+    }
+
+    const PRUint32 pcCount = mHangReports[i].callStack.Length();
+    for (size_t pcIndex = 0; pcIndex < pcCount; ++pcIndex) {
+      nsCAutoString pcString;
+      pcString.AppendPrintf("0x%p", mHangReports[i].callStack[pcIndex]);
+      JSString *str = JS_NewStringCopyZ(cx, pcString.get());
+      if (!str) {
+        return NS_ERROR_FAILURE;
+      }
+      jsval v = STRING_TO_JSVAL(str);
+      if (!JS_SetElement(cx, pcArray, pcIndex, &v)) {
+        return NS_ERROR_FAILURE;
+      }
+    }
+
+    // Record memory map info
+    JSObject *moduleArray = JS_NewArrayObject(cx, 0, nsnull);
+    if (!moduleArray) {
+      return NS_ERROR_FAILURE;
+    }
+    ok = JS_DefineProperty(cx, reportObj, "memoryMap",
+                           OBJECT_TO_JSVAL(moduleArray),
+                           NULL, NULL, JSPROP_ENUMERATE);
+    if (!ok) {
+      return NS_ERROR_FAILURE;
+    }
+
+    const PRUint32 moduleCount = mHangReports[i].moduleMap.GetSize();
+    for (size_t moduleIndex = 0; moduleIndex < moduleCount; ++moduleIndex) {
+      // Current module
+      const SharedLibrary &module =
+        mHangReports[i].moduleMap.GetEntry(moduleIndex);
+
+      JSObject *moduleInfoArray = JS_NewArrayObject(cx, 0, nsnull);
+      if (!moduleInfoArray) {
+        return NS_ERROR_FAILURE;
+      }
+      jsval val = OBJECT_TO_JSVAL(moduleInfoArray);
+      if (!JS_SetElement(cx, moduleArray, moduleIndex, &val)) {
+        return NS_ERROR_FAILURE;
+      }
+
+      // Start address
+      nsCAutoString addressString;
+      addressString.AppendPrintf("0x%p", module.GetStart());
+      JSString *str = JS_NewStringCopyZ(cx, addressString.get());
+      if (!str) {
+        return NS_ERROR_FAILURE;
+      }
+      val = STRING_TO_JSVAL(str);
+      if (!JS_SetElement(cx, moduleInfoArray, 0, &val)) {
+        return NS_ERROR_FAILURE;
+      }
+
+      // Module name
+      str = JS_NewStringCopyZ(cx, module.GetName());
+      if (!str) {
+        return NS_ERROR_FAILURE;
+      }
+      val = STRING_TO_JSVAL(str);
+      if (!JS_SetElement(cx, moduleInfoArray, 1, &val)) {
+        return NS_ERROR_FAILURE;
+      }
+
+      // Module size in memory
+      val = INT_TO_JSVAL(int32_t(module.GetEnd() - module.GetStart()));
+      if (!JS_SetElement(cx, moduleInfoArray, 2, &val)) {
+        return NS_ERROR_FAILURE;
+      }
+
+      // "PDB Age" identifier
+      val = INT_TO_JSVAL(0);
+#if defined(MOZ_PROFILING) && defined(XP_WIN)
+      val = INT_TO_JSVAL(module.GetPdbAge());
+#endif
+      if (!JS_SetElement(cx, moduleInfoArray, 3, &val)) {
+        return NS_ERROR_FAILURE;
+      }
+
+      // "PDB Signature" GUID
+      char guidString[NSID_LENGTH] = { 0 };
+#if defined(MOZ_PROFILING) && defined(XP_WIN)
+      module.GetPdbSignature().ToProvidedString(guidString);
+#endif
+      str = JS_NewStringCopyZ(cx, guidString);
+      if (!str) {
+        return NS_ERROR_FAILURE;
+      }
+      val = STRING_TO_JSVAL(str);
+      if (!JS_SetElement(cx, moduleInfoArray, 4, &val)) {
+        return NS_ERROR_FAILURE;
+      }
+    }
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 TelemetryImpl::GetRegisteredHistograms(JSContext *cx, jsval *ret)
 {
   size_t count = ArrayLength(gHistograms);
   JSObject *info = JS_NewObject(cx, NULL, NULL, NULL);
   if (!info)
     return NS_ERROR_FAILURE;
   JS::AutoObjectRooter root(cx, info);
 
@@ -1373,16 +1522,44 @@ TelemetryImpl::RecordSlowStatement(const
       return;
     entry->mData.hitCount = 0;
     entry->mData.totalTime = 0;
   }
   entry->mData.hitCount++;
   entry->mData.totalTime += delay;
 }
 
+void
+TelemetryImpl::RecordChromeHang(PRUint32 duration,
+                                const Telemetry::HangStack &callStack,
+                                SharedLibraryInfo &moduleMap)
+{
+  MOZ_ASSERT(sTelemetry);
+  if (!sTelemetry->mCanRecord) {
+    return;
+  }
+
+  MutexAutoLock hangReportMutex(sTelemetry->mHangReportsMutex);
+
+  // Only report the modules which changed since the first hang report
+  if (sTelemetry->mHangReports.Length()) {
+    SharedLibraryInfo &firstModuleMap =
+      sTelemetry->mHangReports[0].moduleMap;
+    for (size_t i = 0; i < moduleMap.GetSize(); ++i) {
+      if (firstModuleMap.Contains(moduleMap.GetEntry(i))) {
+        moduleMap.RemoveEntries(i, i + 1);
+        --i;
+      }
+    }
+  }
+
+  HangReport newReport = { duration, callStack, moduleMap };
+  sTelemetry->mHangReports.AppendElement(newReport);
+}
+
 NS_IMPL_THREADSAFE_ISUPPORTS1(TelemetryImpl, nsITelemetry)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsITelemetry, TelemetryImpl::CreateTelemetryInstance)
 
 #define NS_TELEMETRY_CID \
   {0xaea477f2, 0xb3a2, 0x469c, {0xaa, 0x29, 0x0a, 0x82, 0xd1, 0x32, 0xb8, 0x29}}
 NS_DEFINE_NAMED_CID(NS_TELEMETRY_CID);
 
 const Module::CIDEntry kTelemetryCIDs[] = {
@@ -1454,16 +1631,23 @@ RecordSlowSQLStatement(const nsACString 
 void Init()
 {
   // Make the service manager hold a long-lived reference to the service
   nsCOMPtr<nsITelemetry> telemetryService =
     do_GetService("@mozilla.org/base/telemetry;1");
   MOZ_ASSERT(telemetryService);
 }
 
+void RecordChromeHang(PRUint32 duration,
+                      const Telemetry::HangStack &callStack,
+                      SharedLibraryInfo &moduleMap)
+{
+  TelemetryImpl::RecordChromeHang(duration, callStack, moduleMap);
+}
+
 } // namespace Telemetry
 } // namespace mozilla
 
 NSMODULE_DEFN(nsTelemetryModule) = &kTelemetryModule;
 
 /**
  * The XRE_TelemetryAdd function is to be used by embedding applications
  * that can't use mozilla::Telemetry::Accumulate() directly.
--- a/toolkit/components/telemetry/Telemetry.h
+++ b/toolkit/components/telemetry/Telemetry.h
@@ -37,16 +37,19 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef Telemetry_h__
 #define Telemetry_h__
 
 #include "mozilla/GuardObjects.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/StartupTimeline.h"
+#include "nsTArray.h"
+#include "nsStringGlue.h"
+#include "shared-libraries.h"
 
 namespace base {
   class Histogram;
 }
 
 namespace mozilla {
 namespace Telemetry {
 
@@ -151,11 +154,27 @@ void RecordSlowSQLStatement(const nsACSt
                             const nsACString &dbName,
                             PRUint32 delay);
 
 /**
  * Threshold for a statement to be considered slow, in milliseconds
  */
 const PRUint32 kSlowStatementThreshold = 100;
 
+/**
+ * nsTArray of pointers representing PCs on a call stack
+ */
+typedef nsTArray<uintptr_t> HangStack;
+
+/**
+ * Record the main thread's call stack after it hangs.
+ *
+ * @param duration - Approximate duration of main thread hang in seconds
+ * @param callStack - Array of PCs from the hung call stack
+ * @param moduleMap - Array of info about modules in memory (for symbolication)
+ */
+void RecordChromeHang(PRUint32 duration,
+                      const HangStack &callStack,
+                      SharedLibraryInfo &moduleMap);
+
 } // namespace Telemetry
 } // namespace mozilla
 #endif // Telemetry_h__
--- a/toolkit/components/telemetry/TelemetryPing.js
+++ b/toolkit/components/telemetry/TelemetryPing.js
@@ -448,16 +448,17 @@ TelemetryPing.prototype = {
 
     if (havePreviousSession) {
       payloadObj.histograms = this.getHistograms(this._prevSession.snapshots);
     }
     else {
       payloadObj.simpleMeasurements = getSimpleMeasurements();
       payloadObj.histograms = this.getHistograms(Telemetry.histogramSnapshots);
       payloadObj.slowSQL = Telemetry.slowSQL;
+      payloadObj.chromeHangs = Telemetry.chromeHangs;
       payloadObj.addonHistograms = this.getAddonHistograms();
     }
     if (Object.keys(this._slowSQLStartup.mainThread).length
 	|| Object.keys(this._slowSQLStartup.otherThreads).length) {
       payloadObj.slowSQLStartup = this._slowSQLStartup;
     }
 
     return { previous: !!havePreviousSession,
--- a/toolkit/components/telemetry/nsITelemetry.idl
+++ b/toolkit/components/telemetry/nsITelemetry.idl
@@ -65,17 +65,17 @@ interface nsITelemetryLoadSessionDataCal
 };
 
 [scriptable, function, uuid(40065f26-afd2-4417-93de-c1de9adb1548)]
 interface nsITelemetrySaveSessionDataCallback : nsISupports
 {
   void handle(in bool success);
 };
 
-[scriptable, uuid(db854295-478d-4de9-8211-d73ed7d81cd0)]
+[scriptable, uuid(f23a2c8d-9286-42e9-ab1b-ed287eeade6d)]
 interface nsITelemetry : nsISupports
 {
   /**
    * Histogram types:
    * HISTOGRAM_EXPONENTIAL - buckets increase exponentially
    * HISTOGRAM_LINEAR - buckets increase linearly
    * HISTOGRAM_BOOLEAN - For storing 0/1 values
    * HISTOGRAM_FLAG - For storing a single value; its count is always == 1.
@@ -113,16 +113,24 @@ interface nsITelemetry : nsISupports
    *   otherThreads: Slow statements that executed on a non-main thread
    *   sqlString - String of the offending prepared statement
    *   hit count - The number of times this statement required longer than the threshold time to execute
    *   total time - The sum of all execution times above the threshold time for this statement
    */
   [implicit_jscontext]
   readonly attribute jsval slowSQL;
 
+  /*
+   * An array of chrome hang reports. Each element is a hang report represented
+   * as an object containing the hang duration, call stack PCs and information
+   * about modules in memory.
+   */
+  [implicit_jscontext]
+  readonly attribute jsval chromeHangs;
+
   /**
    * An object whose properties are the names of histograms defined in
    * TelemetryHistograms.h and whose corresponding values are the textual
    * comments associated with said histograms.
    */
   [implicit_jscontext]
   readonly attribute jsval registeredHistograms;
 
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -51,17 +51,16 @@ SHARED_LIBRARY_LIBS += \
   $(foreach lib,$(STATIC_LIBS),$(DEPTH)/staticlib/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX)) \
   $(NULL)
 
 CPPSRCS += \
   nsStaticXULComponents.cpp \
   $(NULL)
 
 ifeq ($(OS_ARCH),WINNT)
-REQUIRES += widget gfx
 CPPSRCS += \
   nsDllMain.cpp \
   $(NULL)
 endif
 
 ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_)
 CPPSRCS += \
   nsGFXDeps.cpp \
@@ -77,17 +76,16 @@ LOCAL_INCLUDES += -I$(topsrcdir)/widget/
 LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/base
 endif
 
 ifneq (,$(filter WINNT OS2,$(OS_ARCH)))
 DEFINES += -DZLIB_DLL=1
 endif
 
 ifeq ($(OS_ARCH),OS2)
-REQUIRES += widget gfx
 
 CPPSRCS += \
   nsGFXDeps.cpp \
   $(NULL)
 
 ifndef MOZ_NATIVE_ZLIB
 CPPSRCS += dlldeps-zlib.cpp
 endif
--- a/toolkit/mozapps/installer/packager.mk
+++ b/toolkit/mozapps/installer/packager.mk
@@ -822,20 +822,22 @@ ifdef NO_PKG_FILES
 endif
 ifdef MOZ_PKG_REMOVALS
 	$(SYSINSTALL) $(IFLAGS1) $(MOZ_PKG_REMOVALS_GEN) $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH)
 endif # MOZ_PKG_REMOVALS
 ifdef MOZ_POST_STAGING_CMD
 	cd $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH) && $(MOZ_POST_STAGING_CMD)
 endif # MOZ_POST_STAGING_CMD
 ifndef LIBXUL_SDK
+ifdef MOZ_PACKAGE_JSSHELL
 # Package JavaScript Shell
 	@echo "Packaging JavaScript Shell..."
 	$(RM) $(PKG_JSSHELL)
 	$(MAKE_JSSHELL)
+endif # MOZ_PACKAGE_JSSHELL
 endif # LIBXUL_SDK
 
 make-package: stage-package $(PACKAGE_XULRUNNER) make-sourcestamp-file
 	@echo "Compressing..."
 	cd $(DIST) && $(MAKE_PACKAGE)
 
 make-sourcestamp-file::
 	$(NSINSTALL) -D $(DIST)/$(PKG_PATH)
--- a/tools/profiler/Makefile.in
+++ b/tools/profiler/Makefile.in
@@ -43,16 +43,17 @@ srcdir      = @srcdir@
 VPATH       = $(srcdir)
 
 include $(DEPTH)/config/autoconf.mk
 
 EXPORTS = \
   sampler.h \
   sps_sampler.h \
   thread_helper.h \
+  shared-libraries.h \
   $(NULL)
 
 LOCAL_INCLUDES += \
   -I$(topsrcdir)/ipc/chromium/src \
   $(NULL)
 
 MODULE          = profiler
 MODULE_NAME     = nsProfilerModule
--- a/tools/profiler/nsIProfiler.idl
+++ b/tools/profiler/nsIProfiler.idl
@@ -49,12 +49,16 @@ interface nsIProfiler : nsISupports
   void GetResponsivenessTimes(out PRUint32 aCount, [retval, array, size_is(aCount)] out double aResult);
   void GetFeatures(out PRUint32 aCount, [retval, array, size_is(aCount)] out string aFeatures);
 
   /**
    * Returns a JSON string of an array of shared library objects.
    * Every object has three properties: start, end, and name.
    * start and end are integers describing the address range that the library
    * occupies in memory. name is the path of the library as a string.
+   *
+   * On Windows profiling builds, the shared library objects will have
+   * additional pdbSignature and pdbAge properties for uniquely identifying
+   * shared library versions for stack symbolication.
    */
   AString getSharedLibraryInformation();
 };
 
--- a/tools/profiler/nsProfiler.cpp
+++ b/tools/profiler/nsProfiler.cpp
@@ -91,16 +91,20 @@ nsProfiler::GetProfile(char **aProfile)
 
 static void
 AddSharedLibraryInfoToStream(std::ostream& aStream, SharedLibrary& aLib)
 {
   aStream << "{";
   aStream << "\"start\":" << aLib.GetStart();
   aStream << ",\"end\":" << aLib.GetEnd();
   aStream << ",\"name\":\"" << aLib.GetName() << "\"";
+#ifdef XP_WIN
+  aStream << ",\"pdbSignature\":\"" << aLib.GetPdbSignature().ToString() << "\"";
+  aStream << ",\"pdbAge\":" << aLib.GetPdbAge();
+#endif
   aStream << "}";
 }
 
 static std::string
 GetSharedLibraryInfoString()
 {
   SharedLibraryInfo info = SharedLibraryInfo::GetInfoForSelf();
   if (info.GetSize() == 0)
--- a/tools/profiler/shared-libraries-win32.cc
+++ b/tools/profiler/shared-libraries-win32.cc
@@ -16,16 +16,17 @@
  *
  * The Initial Developer of the Original Code is
  * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2011
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *  Jeff Muizelaar <jmuizelaar@mozilla.com>
+ *  Vladan Djeric <vdjeric@mozilla.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -33,33 +34,94 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include <windows.h>
 #include <tlhelp32.h>
+#include <Dbghelp.h>
 
 #include "shared-libraries.h"
 #include "nsWindowsHelpers.h"
 
+#define CV_SIGNATURE 0x53445352 // 'SDSR'
+
+struct CodeViewRecord70
+{
+  uint32_t signature;
+  GUID pdbSignature;
+  uint32_t pdbAge;
+  uint8_t pdbFileName[1];
+};
+
+static bool GetPdbInfo(uintptr_t aStart, nsID& aSignature, uint32_t& aAge)
+{
+  if (!aStart) {
+    return false;
+  }
+
+  PIMAGE_DOS_HEADER dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(aStart);
+  if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
+    return false;
+  }
+
+  PIMAGE_NT_HEADERS ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(
+      aStart + dosHeader->e_lfanew);
+  if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) {
+    return false;
+  }
+
+  uint32_t relativeVirtualAddress =
+    ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+  if (!relativeVirtualAddress) {
+    return false;
+  }
+
+  PIMAGE_DEBUG_DIRECTORY debugDirectory =
+    reinterpret_cast<PIMAGE_DEBUG_DIRECTORY>(aStart + relativeVirtualAddress);
+  if (!debugDirectory || debugDirectory->Type != IMAGE_DEBUG_TYPE_CODEVIEW) {
+    return false;
+  }
+
+  CodeViewRecord70 *debugInfo = reinterpret_cast<CodeViewRecord70 *>(
+      aStart + debugDirectory->AddressOfRawData);
+  if (!debugInfo || debugInfo->signature != CV_SIGNATURE) {
+    return false;
+  }
+
+  aAge = debugInfo->pdbAge;
+  GUID& pdbSignature = debugInfo->pdbSignature;
+  aSignature.m0 = pdbSignature.Data1;
+  aSignature.m1 = pdbSignature.Data2;
+  aSignature.m2 = pdbSignature.Data3;
+  memcpy(aSignature.m3, pdbSignature.Data4, sizeof(pdbSignature.Data4));
+  return true;
+}
+
 SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf()
 {
   SharedLibraryInfo sharedLibraryInfo;
 
   nsAutoHandle snap(CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()));
 
   MODULEENTRY32 module = {0};
   module.dwSize = sizeof(MODULEENTRY32);
   if (Module32First(snap, &module)) {
     do {
-      SharedLibrary shlib((uintptr_t)module.modBaseAddr,
-                          (uintptr_t)module.modBaseAddr+module.modBaseSize,
-                          0, // DLLs are always mapped at offset 0 on Windows
-                          module.szModule);
-      sharedLibraryInfo.AddSharedLibrary(shlib);
+      nsID pdbSig;
+      uint32_t pdbAge;
+      if (GetPdbInfo((uintptr_t)module.modBaseAddr, pdbSig, pdbAge)) {
+        SharedLibrary shlib((uintptr_t)module.modBaseAddr,
+                            (uintptr_t)module.modBaseAddr+module.modBaseSize,
+                            0, // DLLs are always mapped at offset 0 on Windows
+                            pdbSig,
+                            pdbAge,
+                            module.szModule);
+        sharedLibraryInfo.AddSharedLibrary(shlib);
+      }
     } while (Module32Next(snap, &module));
   }
 
   return sharedLibraryInfo;
 }
 
--- a/tools/profiler/shared-libraries.h
+++ b/tools/profiler/shared-libraries.h
@@ -31,83 +31,159 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include <algorithm>
 #include <vector>
 #include <string.h>
 #include <stdlib.h>
 #include <mozilla/StandardInteger.h>
+#include <nsID.h>
 
 class SharedLibrary {
 public:
-  SharedLibrary(unsigned long aStart, unsigned long aEnd, unsigned long aOffset, char *aName)
+
+  SharedLibrary(unsigned long aStart,
+                unsigned long aEnd,
+                unsigned long aOffset,
+#ifdef XP_WIN
+                nsID aPdbSignature,
+                unsigned long aPdbAge,
+#endif
+                char *aName)
     : mStart(aStart)
     , mEnd(aEnd)
     , mOffset(aOffset)
+#ifdef XP_WIN
+    , mPdbSignature(aPdbSignature)
+    , mPdbAge(aPdbAge)
+#endif
     , mName(strdup(aName))
   {}
 
   SharedLibrary(const SharedLibrary& aEntry)
     : mStart(aEntry.mStart)
     , mEnd(aEntry.mEnd)
     , mOffset(aEntry.mOffset)
+#ifdef XP_WIN
+    , mPdbSignature(aEntry.mPdbSignature)
+    , mPdbAge(aEntry.mPdbAge)
+#endif
     , mName(strdup(aEntry.mName))
   {}
 
   SharedLibrary& operator=(const SharedLibrary& aEntry)
   {
     // Gracefully handle self assignment
     if (this == &aEntry) return *this;
 
     mStart = aEntry.mStart;
     mEnd = aEntry.mEnd;
     mOffset = aEntry.mOffset;
+#ifdef XP_WIN
+    mPdbSignature = aEntry.mPdbSignature;
+    mPdbAge = aEntry.mPdbAge;
+#endif
     if (mName)
       free(mName);
     mName = strdup(aEntry.mName);
     return *this;
   }
 
+  bool operator==(const SharedLibrary& other) const
+  {
+    bool equal = ((mStart == other.mStart) &&
+                  (mEnd == other.mEnd) &&
+                  (mOffset == other.mOffset) &&
+                  (mName && other.mName && (strcmp(mName, other.mName) == 0)));
+#ifdef XP_WIN
+    equal = equal &&
+            (mPdbSignature.Equals(other.mPdbSignature)) &&
+            (mPdbAge == other.mPdbAge);
+#endif
+    return equal;
+  }
+
   ~SharedLibrary()
   {
     free(mName);
+    mName = NULL;
   }
 
-  uintptr_t GetStart() { return mStart; }
-  uintptr_t GetEnd() { return mEnd; }
-  char* GetName() { return mName; }
+  uintptr_t GetStart() const { return mStart; }
+  uintptr_t GetEnd() const { return mEnd; }
+#ifdef XP_WIN
+  nsID GetPdbSignature() const { return mPdbSignature; }
+  uint32_t GetPdbAge() const { return mPdbAge; }
+#endif
+  char* GetName() const { return mName; }
 
 private:
   explicit SharedLibrary() {}
 
   uintptr_t mStart;
   uintptr_t mEnd;
   uintptr_t mOffset;
+#ifdef XP_WIN
+  // Windows-specific PDB file identifiers
+  nsID mPdbSignature;
+  uint32_t mPdbAge;
+#endif
   char *mName;
 };
 
+static bool
+CompareAddresses(const SharedLibrary& first, const SharedLibrary& second)
+{
+  return first.GetStart() < second.GetStart();
+}
+
 class SharedLibraryInfo {
 public:
   static SharedLibraryInfo GetInfoForSelf();
   SharedLibraryInfo() {}
 
   void AddSharedLibrary(SharedLibrary entry)
   {
     mEntries.push_back(entry);
   }
 
   SharedLibrary& GetEntry(size_t i)
   {
     return mEntries[i];
   }
 
-  size_t GetSize()
+  // Removes items in the range [first, last)
+  // i.e. element at the "last" index is not removed
+  void RemoveEntries(size_t first, size_t last)
+  {
+    mEntries.erase(mEntries.begin() + first, mEntries.begin() + last);
+  }
+
+  bool Contains(const SharedLibrary& searchItem) const
+  {
+    return (mEntries.end() !=
+              std::find(mEntries.begin(), mEntries.end(), searchItem));
+  }
+
+  size_t GetSize() const
   {
     return mEntries.size();
   }
+
+  void SortByAddress()
+  {
+    std::sort(mEntries.begin(), mEntries.end(), CompareAddresses);
+  }
+
+  void Clear()
+  {
+    mEntries.clear();
+  }
+
 private:
   std::vector<SharedLibrary> mEntries;
 };
--- a/xpcom/threads/HangMonitor.cpp
+++ b/xpcom/threads/HangMonitor.cpp
@@ -33,37 +33,45 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/HangMonitor.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/Telemetry.h"
 #include "nsXULAppAPI.h"
 #include "nsThreadUtils.h"
+#include "nsStackWalk.h"
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
 
 #ifdef XP_WIN
 #include <windows.h>
 #endif
 
+#if defined(MOZ_PROFILING) && defined(XP_WIN)
+  #define REPORT_CHROME_HANGS
+#endif
+
 namespace mozilla { namespace HangMonitor {
 
 /**
  * A flag which may be set from within a debugger to disable the hang
  * monitor.
  */
 volatile bool gDebugDisableHangMonitor = false;
 
 const char kHangMonitorPrefName[] = "hangmonitor.timeout";
 
+const char kTelemetryPrefName[] = "toolkit.telemetry.enabled";
+
 // Monitor protects gShutdown and gTimeout, but not gTimestamp which rely on
 // being atomically set by the processor; synchronization doesn't really matter
 // in this use case.
 Monitor* gMonitor;
 
 // The timeout preference, in seconds.
 PRInt32 gTimeout;
 
@@ -71,21 +79,38 @@ PRThread* gThread;
 
 // Set when shutdown begins to signal the thread to exit immediately.
 bool gShutdown;
 
 // The timestamp of the last event notification, or PR_INTERVAL_NO_WAIT if
 // we're currently not processing events.
 volatile PRIntervalTime gTimestamp;
 
+#ifdef REPORT_CHROME_HANGS
+// Main thread ID used in reporting chrome hangs under Windows
+static HANDLE winMainThreadHandle = NULL;
+
+// Default timeout for reporting chrome hangs to Telemetry (10 seconds)
+static const PRInt32 DEFAULT_CHROME_HANG_INTERVAL = 10;
+#endif
+
 // PrefChangedFunc
 int
 PrefChanged(const char*, void*)
 {
   PRInt32 newval = Preferences::GetInt(kHangMonitorPrefName);
+#ifdef REPORT_CHROME_HANGS
+  // Monitor chrome hangs on the profiling branch if Telemetry enabled
+  if (newval == 0) {
+    PRBool telemetryEnabled = Preferences::GetBool(kTelemetryPrefName);
+    if (telemetryEnabled) {
+      newval = DEFAULT_CHROME_HANG_INTERVAL;
+    }
+  }
+#endif
   MonitorAutoLock lock(*gMonitor);
   if (newval != gTimeout) {
     gTimeout = newval;
     lock.Notify();
   }
 
   return 0;
 }
@@ -106,27 +131,100 @@ Crash()
 #ifdef MOZ_CRASHREPORTER
   CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Hang"),
                                      NS_LITERAL_CSTRING("1"));
 #endif
 
   NS_RUNTIMEABORT("HangMonitor triggered");
 }
 
+#ifdef REPORT_CHROME_HANGS
+static void
+ChromeStackWalker(void *aPC, void *aClosure)
+{
+  MOZ_ASSERT(aClosure);
+  Telemetry::HangStack *callStack =
+    reinterpret_cast< Telemetry::HangStack* >(aClosure);
+  callStack->AppendElement(reinterpret_cast<uintptr_t>(aPC));
+}
+
+static void
+GetChromeHangReport(Telemetry::HangStack &callStack, SharedLibraryInfo &moduleMap)
+{
+  MOZ_ASSERT(winMainThreadHandle);
+  moduleMap = SharedLibraryInfo::GetInfoForSelf();
+  moduleMap.SortByAddress();
+
+  DWORD ret = ::SuspendThread(winMainThreadHandle);
+  if (ret == -1) {
+    callStack.Clear();
+    moduleMap.Clear();
+    return;
+  }
+  NS_StackWalk(ChromeStackWalker, 0, &callStack,
+               reinterpret_cast<uintptr_t>(winMainThreadHandle));
+  ret = ::ResumeThread(winMainThreadHandle);
+  if (ret == -1) {
+    callStack.Clear();
+    moduleMap.Clear();
+    return;
+  }
+
+  // Remove all modules not referenced by a PC on the stack
+  Telemetry::HangStack sortedStack = callStack;
+  sortedStack.Sort();
+
+  size_t moduleIndex = 0;
+  size_t stackIndex = 0;
+  bool unreferencedModule = true;
+  while (stackIndex < sortedStack.Length() && moduleIndex < moduleMap.GetSize()) {
+    uintptr_t pc = sortedStack[stackIndex];
+    SharedLibrary& module = moduleMap.GetEntry(moduleIndex);
+    uintptr_t moduleStart = module.GetStart();
+    uintptr_t moduleEnd = module.GetEnd() - 1;
+    if (moduleStart <= pc && pc <= moduleEnd) {
+      // If the current PC is within the current module, mark module as used
+      unreferencedModule = false;
+      ++stackIndex;
+    } else if (pc > moduleEnd) {
+      if (unreferencedModule) {
+        // Remove module if no PCs within its address range
+        moduleMap.RemoveEntries(moduleIndex, moduleIndex + 1);
+      } else {
+        // Module was referenced on stack, but current PC belongs to later module
+        unreferencedModule = true;
+        ++moduleIndex;
+      }
+    } else {
+      // PC does not belong to any module
+      ++stackIndex;
+    }
+  }
+
+  // Clean up remaining unreferenced modules, i.e. module addresses > max(pc)
+  if (moduleIndex + 1 < moduleMap.GetSize()) {
+    moduleMap.RemoveEntries(moduleIndex + 1, moduleMap.GetSize());
+  }
+}
+#endif
+
 void
 ThreadMain(void*)
 {
   MonitorAutoLock lock(*gMonitor);
 
   // In order to avoid issues with the hang monitor incorrectly triggering
   // during a general system stop such as sleeping, the monitor thread must
   // run twice to trigger hang protection.
   PRIntervalTime lastTimestamp = 0;
   int waitCount = 0;
 
+  Telemetry::HangStack hangStack;
+  SharedLibraryInfo hangModuleMap;
+
   while (true) {
     if (gShutdown) {
       return; // Exit the thread
     }
 
     // avoid rereading the volatile value in this loop
     PRIntervalTime timestamp = gTimestamp;
 
@@ -138,25 +236,37 @@ ThreadMain(void*)
       timestamp = 1; // lowest legal PRInterval value
     }
 
     if (timestamp != PR_INTERVAL_NO_WAIT &&
         timestamp == lastTimestamp &&
         gTimeout > 0) {
       ++waitCount;
       if (waitCount == 2) {
+#ifdef REPORT_CHROME_HANGS
+        GetChromeHangReport(hangStack, hangModuleMap);
+#else
         PRInt32 delay =
           PRInt32(PR_IntervalToSeconds(now - timestamp));
         if (delay > gTimeout) {
           MonitorAutoUnlock unlock(*gMonitor);
           Crash();
         }
+#endif
       }
     }
     else {
+#ifdef REPORT_CHROME_HANGS
+      if (waitCount >= 2) {
+        PRUint32 hangDuration = PR_IntervalToSeconds(now - lastTimestamp);
+        Telemetry::RecordChromeHang(hangDuration, hangStack, hangModuleMap);
+        hangStack.Clear();
+        hangModuleMap.Clear();
+      }
+#endif
       lastTimestamp = timestamp;
       waitCount = 0;
     }
 
     PRIntervalTime timeout;
     if (gTimeout <= 0) {
       timeout = PR_INTERVAL_NO_TIMEOUT;
     }
@@ -177,16 +287,24 @@ Startup()
     return;
 
   NS_ASSERTION(!gMonitor, "Hang monitor already initialized");
   gMonitor = new Monitor("HangMonitor");
 
   Preferences::RegisterCallback(PrefChanged, kHangMonitorPrefName, NULL);
   PrefChanged(NULL, NULL);
 
+#ifdef REPORT_CHROME_HANGS
+  Preferences::RegisterCallback(PrefChanged, kTelemetryPrefName, NULL);
+  winMainThreadHandle =
+    OpenThread(THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId());
+  if (!winMainThreadHandle)
+    return;
+#endif
+
   // Don't actually start measuring hangs until we hit the main event loop.
   // This potentially misses a small class of really early startup hangs,
   // but avoids dealing with some xpcshell tests and other situations which
   // start XPCOM but don't ever start the event loop.
   Suspend();
 
   gThread = PR_CreateThread(PR_USER_THREAD,
                             ThreadMain,