Merge from mozilla-central.
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 19 Feb 2013 11:34:59 +0100
changeset 138266 00f552950d2c18220622750860cc16b7a3707d90
parent 138265 3ece7856128b4aa634edc96fd352f54c4e77d71a (current diff)
parent 132158 0577eb1893c44ccce6f6085603f4b12021c01d5f (diff)
child 138267 a5636acd5d79db350cc065dcfd98d415a7dd6262
child 138268 cd1eb7fe0002b9bb4f5a31a0f7e43ca5c88f182d
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone21.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge from mozilla-central.
browser/components/thumbnails/BrowserPageThumbs.manifest
browser/components/thumbnails/Makefile.in
browser/components/thumbnails/PageThumbs.jsm
browser/components/thumbnails/PageThumbsProtocol.js
browser/components/thumbnails/PageThumbsWorker.js
browser/components/thumbnails/test/Makefile.in
browser/components/thumbnails/test/background_red.html
browser/components/thumbnails/test/background_red_redirect.sjs
browser/components/thumbnails/test/browser_thumbnails_bug726727.js
browser/components/thumbnails/test/browser_thumbnails_capture.js
browser/components/thumbnails/test/browser_thumbnails_expiration.js
browser/components/thumbnails/test/browser_thumbnails_privacy.js
browser/components/thumbnails/test/browser_thumbnails_redirect.js
browser/components/thumbnails/test/browser_thumbnails_storage.js
browser/components/thumbnails/test/browser_thumbnails_storage_migrate3.js
browser/components/thumbnails/test/head.js
browser/components/thumbnails/test/privacy_cache_control.sjs
browser/modules/NewTabUtils.jsm
browser/modules/test/unit/chromeappsstore.sqlite
browser/modules/test/unit/test_newtab-migrate-v1.js
browser/modules/test/unit/xpcshell.ini
content/html/content/src/nsHTMLFrameElement.cpp
content/html/content/src/nsHTMLLegendElement.cpp
content/html/content/src/nsHTMLLegendElement.h
content/html/content/src/nsHTMLMenuElement.cpp
content/html/content/src/nsHTMLMenuElement.h
content/html/content/src/nsHTMLMenuItemElement.cpp
content/html/content/src/nsHTMLMenuItemElement.h
content/html/content/src/nsHTMLOptionElement.cpp
content/html/content/src/nsHTMLOptionElement.h
content/html/content/test/test_bug585508.html
content/svg/content/src/nsSVGFilterElement.cpp
content/svg/content/src/nsSVGFilterElement.h
dom/base/nsJSEnvironment.cpp
dom/interfaces/svg/nsIDOMSVGAElement.idl
dom/interfaces/svg/nsIDOMSVGFilterElement.idl
dom/interfaces/svg/nsIDOMSVGImageElement.idl
dom/interfaces/svg/nsIDOMSVGMarkerElement.idl
dom/interfaces/svg/nsIDOMSVGMaskElement.idl
dom/interfaces/svg/nsIDOMSVGTitleElement.idl
js/src/gc/RootMarking.cpp
js/src/ion/Bailouts.cpp
js/src/ion/IonBuilder.cpp
js/src/jsapi.h
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jsfriendapi.h
js/src/jsobj.cpp
js/src/jsscript.cpp
js/src/vm/Stack.cpp
modules/libpref/src/init/all.js
--- a/accessible/src/base/StyleInfo.cpp
+++ b/accessible/src/base/StyleInfo.cpp
@@ -22,36 +22,36 @@ StyleInfo::StyleInfo(dom::Element* aElem
                                                          aPresShell);
 }
 
 void
 StyleInfo::Display(nsAString& aValue)
 {
   aValue.Truncate();
   AppendASCIItoUTF16(
-    nsCSSProps::ValueToKeyword(mStyleContext->GetStyleDisplay()->mDisplay,
+    nsCSSProps::ValueToKeyword(mStyleContext->StyleDisplay()->mDisplay,
                                nsCSSProps::kDisplayKTable), aValue);
 }
 
 void
 StyleInfo::TextAlign(nsAString& aValue)
 {
   aValue.Truncate();
   AppendASCIItoUTF16(
-    nsCSSProps::ValueToKeyword(mStyleContext->GetStyleText()->mTextAlign,
+    nsCSSProps::ValueToKeyword(mStyleContext->StyleText()->mTextAlign,
                                nsCSSProps::kTextAlignKTable), aValue);
 }
 
 void
 StyleInfo::TextIndent(nsAString& aValue)
 {
   aValue.Truncate();
 
   const nsStyleCoord& styleCoord =
-    mStyleContext->GetStyleText()->mTextIndent;
+    mStyleContext->StyleText()->mTextIndent;
 
   nscoord coordVal = 0;
   switch (styleCoord.GetUnit()) {
     case eStyleUnit_Coord:
       coordVal = styleCoord.GetCoordValue();
       break;
 
     case eStyleUnit_Percent:
--- a/accessible/src/base/TextAttrs.cpp
+++ b/accessible/src/base/TextAttrs.cpp
@@ -344,17 +344,17 @@ TextAttrsMgr::BGColorTextAttr::
   nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::backgroundColor,
                          formattedValue);
 }
 
 bool
 TextAttrsMgr::BGColorTextAttr::
   GetColor(nsIFrame* aFrame, nscolor* aColor)
 {
-  const nsStyleBackground* styleBackground = aFrame->GetStyleBackground();
+  const nsStyleBackground* styleBackground = aFrame->StyleBackground();
 
   if (NS_GET_A(styleBackground->mBackgroundColor) > 0) {
     *aColor = styleBackground->mBackgroundColor;
     return true;
   }
 
   nsIFrame *parentFrame = aFrame->GetParent();
   if (!parentFrame) {
@@ -375,33 +375,33 @@ TextAttrsMgr::BGColorTextAttr::
 ////////////////////////////////////////////////////////////////////////////////
 // ColorTextAttr
 ////////////////////////////////////////////////////////////////////////////////
 
 TextAttrsMgr::ColorTextAttr::
   ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
   TTextAttr<nscolor>(!aFrame)
 {
-  mRootNativeValue = aRootFrame->GetStyleColor()->mColor;
+  mRootNativeValue = aRootFrame->StyleColor()->mColor;
   mIsRootDefined = true;
 
   if (aFrame) {
-    mNativeValue = aFrame->GetStyleColor()->mColor;
+    mNativeValue = aFrame->StyleColor()->mColor;
     mIsDefined = true;
   }
 }
 
 bool
 TextAttrsMgr::ColorTextAttr::
   GetValueFor(Accessible* aAccessible, nscolor* aValue)
 {
   nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
   nsIFrame* frame = elm->GetPrimaryFrame();
   if (frame) {
-    *aValue = frame->GetStyleColor()->mColor;
+    *aValue = frame->StyleColor()->mColor;
     return true;
   }
 
   return false;
 }
 
 void
 TextAttrsMgr::ColorTextAttr::
@@ -446,48 +446,50 @@ TextAttrsMgr::FontFamilyTextAttr::
 bool
 TextAttrsMgr::FontFamilyTextAttr::
   GetFontFamily(nsIFrame* aFrame, nsString& aFamily)
 {
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm));
 
   gfxFontGroup* fontGroup = fm->GetThebesFontGroup();
-  aFamily = fontGroup->GetFamilyNameAt(0);
+  gfxFont* font = fontGroup->GetFontAt(0);
+  gfxFontEntry* fontEntry = font->GetFontEntry();
+  aFamily = fontEntry->FamilyName();
   return true;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // FontSizeTextAttr
 ////////////////////////////////////////////////////////////////////////////////
 
 TextAttrsMgr::FontSizeTextAttr::
   FontSizeTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
   TTextAttr<nscoord>(!aFrame)
 {
   mDC = aRootFrame->PresContext()->DeviceContext();
 
-  mRootNativeValue = aRootFrame->GetStyleFont()->mSize;
+  mRootNativeValue = aRootFrame->StyleFont()->mSize;
   mIsRootDefined = true;
 
   if (aFrame) {
-    mNativeValue = aFrame->GetStyleFont()->mSize;
+    mNativeValue = aFrame->StyleFont()->mSize;
     mIsDefined = true;
   }
 }
 
 bool
 TextAttrsMgr::FontSizeTextAttr::
   GetValueFor(Accessible* aAccessible, nscoord* aValue)
 {
   nsIContent* content = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
   nsIFrame* frame = content->GetPrimaryFrame();
   if (frame) {
-    *aValue = frame->GetStyleFont()->mSize;
+    *aValue = frame->StyleFont()->mSize;
     return true;
   }
 
   return false;
 }
 
 void
 TextAttrsMgr::FontSizeTextAttr::
@@ -517,33 +519,33 @@ TextAttrsMgr::FontSizeTextAttr::
 ////////////////////////////////////////////////////////////////////////////////
 // FontStyleTextAttr
 ////////////////////////////////////////////////////////////////////////////////
 
 TextAttrsMgr::FontStyleTextAttr::
   FontStyleTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
   TTextAttr<nscoord>(!aFrame)
 {
-  mRootNativeValue = aRootFrame->GetStyleFont()->mFont.style;
+  mRootNativeValue = aRootFrame->StyleFont()->mFont.style;
   mIsRootDefined = true;
 
   if (aFrame) {
-    mNativeValue = aFrame->GetStyleFont()->mFont.style;
+    mNativeValue = aFrame->StyleFont()->mFont.style;
     mIsDefined = true;
   }
 }
 
 bool
 TextAttrsMgr::FontStyleTextAttr::
   GetValueFor(Accessible* aAccessible, nscoord* aValue)
 {
   nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
   nsIFrame* frame = elm->GetPrimaryFrame();
   if (frame) {
-    *aValue = frame->GetStyleFont()->mFont.style;
+    *aValue = frame->StyleFont()->mFont.style;
     return true;
   }
 
   return false;
 }
 
 void
 TextAttrsMgr::FontStyleTextAttr::
@@ -667,23 +669,23 @@ TextAttrsMgr::AutoGeneratedTextAttr::
 
 ////////////////////////////////////////////////////////////////////////////////
 // TextDecorTextAttr
 ////////////////////////////////////////////////////////////////////////////////
 
 TextAttrsMgr::TextDecorValue::
   TextDecorValue(nsIFrame* aFrame)
 {
-  const nsStyleTextReset* textReset = aFrame->GetStyleTextReset();
+  const nsStyleTextReset* textReset = aFrame->StyleTextReset();
   mStyle = textReset->GetDecorationStyle();
 
   bool isForegroundColor = false;
   textReset->GetDecorationColor(mColor, isForegroundColor);
   if (isForegroundColor)
-    mColor = aFrame->GetStyleColor()->mColor;
+    mColor = aFrame->StyleColor()->mColor;
 
   mLine = textReset->mTextDecorationLine &
     (NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE |
      NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH);
 }
 
 TextAttrsMgr::TextDecorTextAttr::
   TextDecorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
@@ -799,17 +801,17 @@ TextAttrsMgr::TextPosTextAttr::
       break;
   }
 }
 
 TextAttrsMgr::TextPosValue
 TextAttrsMgr::TextPosTextAttr::
   GetTextPosValue(nsIFrame* aFrame) const
 {
-  const nsStyleCoord& styleCoord = aFrame->GetStyleTextReset()->mVerticalAlign;
+  const nsStyleCoord& styleCoord = aFrame->StyleTextReset()->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:
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -738,17 +738,17 @@ nsAccessibilityService::GetOrCreateAcces
   if (!aNode->IsContent())
     return nullptr;
 
   nsIContent* content = aNode->AsContent();
   nsIFrame* frame = content->GetPrimaryFrame();
 
   // Check frame and its visibility. Note, hidden frame allows visible
   // elements in subtree.
-  if (!frame || !frame->GetStyleVisibility()->IsVisible()) {
+  if (!frame || !frame->StyleVisibility()->IsVisible()) {
     if (aIsSubtreeHidden && !frame)
       *aIsSubtreeHidden = true;
 
     return nullptr;
   }
 
   if (frame->GetContent() != content) {
     // Not the main content for this frame. This happens because <area>
@@ -1417,18 +1417,20 @@ nsAccessibilityService::CreateAccessible
       break;
     case eHTMLRadioButtonType:
       newAcc = new HTMLRadioButtonAccessible(aContent, document);
       break;
     case eHTMLTableType:
       newAcc = new HTMLTableAccessibleWrap(aContent, document);
       break;
     case eHTMLTableCellType:
-      // Accessible HTML table cell must be a child of accessible HTML table row.
-      if (aContext->IsHTMLTableRow())
+      // Accessible HTML table cell should be a child of accessible HTML table
+      // or its row (CSS HTML tables are polite to the used markup at
+      // certain degree).
+      if (aContext->IsHTMLTableRow() || aContext->IsHTMLTable())
         newAcc = new HTMLTableCellAccessibleWrap(aContent, document);
       break;
 
     case eHTMLTableRowType: {
       // Accessible HTML table row must be a child of tbody/tfoot/thead of
       // accessible HTML table or must be a child of accessible of HTML table.
       if (aContext->IsTable()) {
         nsIContent* parentContent = aContent->GetParent();
--- a/accessible/src/base/nsTextEquivUtils.cpp
+++ b/accessible/src/base/nsTextEquivUtils.cpp
@@ -96,17 +96,17 @@ nsTextEquivUtils::AppendTextEquivFromCon
     return NS_OK;
 
   gInitiatorAcc = aInitiatorAcc;
 
   // If the given content is not visible or isn't accessible then go down
   // through the DOM subtree otherwise go down through accessible subtree and
   // calculate the flat string.
   nsIFrame *frame = aContent->GetPrimaryFrame();
-  bool isVisible = frame && frame->GetStyleVisibility()->IsVisible();
+  bool isVisible = frame && frame->StyleVisibility()->IsVisible();
 
   nsresult rv = NS_ERROR_FAILURE;
   bool goThroughDOMSubtree = true;
 
   if (isVisible) {
     Accessible* accessible =
       gInitiatorAcc->Document()->GetAccessible(aContent);
     if (accessible) {
@@ -131,17 +131,17 @@ nsTextEquivUtils::AppendTextEquivFromTex
 
     nsIContent *parentContent = aContent->GetParent();
     if (parentContent) {
       nsIFrame *frame = parentContent->GetPrimaryFrame();
       if (frame) {
         // If this text is inside a block level frame (as opposed to span
         // level), we need to add spaces around that block's text, so we don't
         // get words jammed together in final name.
-        const nsStyleDisplay* display = frame->GetStyleDisplay();
+        const nsStyleDisplay* display = frame->StyleDisplay();
         if (display->IsBlockOutsideStyle() ||
             display->mDisplay == NS_STYLE_DISPLAY_TABLE_CELL) {
           isHTMLBlock = true;
           if (!aString->IsEmpty()) {
             aString->Append(PRUnichar(' '));
           }
         }
       }
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -615,17 +615,17 @@ uint64_t
 Accessible::VisibilityState()
 {
   nsIFrame* frame = GetFrame();
   if (!frame)
     return states::INVISIBLE;
 
   // Walk the parent frame chain to see if there's invisible parent or the frame
   // is in background tab.
-  if (!frame->GetStyleVisibility()->IsVisible())
+  if (!frame->StyleVisibility()->IsVisible())
     return states::INVISIBLE;
 
   nsIFrame* curFrame = frame;
   nsPoint framePos(0, 0);
   do {
     nsView* view = curFrame->GetView();
     if (view && view->GetVisibility() == nsViewVisibility_kHide)
       return states::INVISIBLE;
@@ -655,17 +655,17 @@ Accessible::VisibilityState()
         scrollPortRect.Deflate(kMinPixels, kMinPixels);
         if (!scrollPortRect.Intersects(frameRect))
           return states::OFFSCREEN;
       }
     }
 
     if (!parentFrame) {
       parentFrame = nsLayoutUtils::GetCrossDocParentFrame(curFrame);
-      if (parentFrame && !parentFrame->GetStyleVisibility()->IsVisible())
+      if (parentFrame && !parentFrame->StyleVisibility()->IsVisible())
         return states::INVISIBLE;
     }
 
     curFrame = parentFrame;
   } while (curFrame);
 
   // Zero area rects can occur in the first frame of a multi-frame text flow,
   // in which case the rendered text is not empty and the frame should not be
@@ -712,17 +712,17 @@ Accessible::NativeState()
   nsIFrame *frame = GetFrame();
   if (frame) {
     if (frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW)
       state |= states::FLOATING;
 
     // XXX we should look at layout for non XUL box frames, but need to decide
     // how that interacts with ARIA.
     if (HasOwnContent() && mContent->IsXUL() && frame->IsBoxFrame()) {
-      const nsStyleXUL* xulStyle = frame->GetStyleXUL();
+      const nsStyleXUL* xulStyle = frame->StyleXUL();
       if (xulStyle && frame->IsBoxFrame()) {
         // In XUL all boxes are either vertical or horizontal
         if (xulStyle->mBoxOrient == NS_STYLE_BOX_ORIENT_VERTICAL)
           state |= states::VERTICAL;
         else
           state |= states::HORIZONTAL;
       }
     }
@@ -1532,17 +1532,17 @@ Accessible::State()
     state |= states::EXPANDABLE;
 
   // For some reasons DOM node may have not a frame. We tract such accessibles
   // as invisible.
   nsIFrame *frame = GetFrame();
   if (!frame)
     return state;
 
-  const nsStyleDisplay* display = frame->GetStyleDisplay();
+  const nsStyleDisplay* display = frame->StyleDisplay();
   if (display && display->mOpacity == 1.0f &&
       !(state & states::INVISIBLE)) {
     state |= states::OPAQUE1;
   }
 
   return state;
 }
 
--- a/accessible/src/generic/Accessible.h
+++ b/accessible/src/generic/Accessible.h
@@ -482,16 +482,17 @@ public:
   bool IsHyperText() const { return HasGenericType(eHyperText); }
   HyperTextAccessible* AsHyperText();
 
   bool IsHTMLFileInput() const { return mType == eHTMLFileInputType; }
 
   bool IsHTMLListItem() const { return mType == eHTMLLiType; }
   HTMLLIAccessible* AsHTMLListItem();
 
+  bool IsHTMLTable() const { return mType == eHTMLTableType; }
   bool IsHTMLTableRow() const { return mType == eHTMLTableRowType; }
 
   bool IsImage() const { return mType == eImageType; }
   ImageAccessible* AsImage();
 
   bool IsImageMap() const { return mType == eImageMapType; }
   HTMLImageMapAccessible* AsImageMap();
 
--- a/accessible/src/html/HTMLSelectAccessible.cpp
+++ b/accessible/src/html/HTMLSelectAccessible.cpp
@@ -11,22 +11,23 @@
 #include "DocAccessible.h"
 #include "nsEventShell.h"
 #include "nsIAccessibleEvent.h"
 #include "nsTextEquivUtils.h"
 #include "Role.h"
 #include "States.h"
 
 #include "nsCOMPtr.h"
-#include "nsHTMLOptionElement.h"
+#include "mozilla/dom/HTMLOptionElement.h"
 #include "nsIComboboxControlFrame.h"
 #include "nsIFrame.h"
 #include "nsIListControlFrame.h"
 
 using namespace mozilla::a11y;
+using namespace mozilla::dom;
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLSelectListAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 HTMLSelectListAccessible::
   HTMLSelectListAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   AccessibleWrap(aContent, aDoc)
@@ -213,17 +214,17 @@ HTMLSelectOptionAccessible::NativeState(
   if (!select)
     return state;
 
   uint64_t selectState = select->State();
   if (selectState & states::INVISIBLE)
     return state;
 
   // Are we selected?
-  nsHTMLOptionElement* option = nsHTMLOptionElement::FromContent(mContent);
+  HTMLOptionElement* option = HTMLOptionElement::FromContent(mContent);
   bool selected = option && option->Selected();
   if (selected)
     state |= states::SELECTED;
 
   if (selectState & states::OFFSCREEN) {
     state |= states::OFFSCREEN;
   } else if (selectState & states::COLLAPSED) {
     // <select> is COLLAPSED: add OFFSCREEN, if not the currently
@@ -260,17 +261,17 @@ HTMLSelectOptionAccessible::NativeIntera
 {
   return NativelyUnavailable() ?
     states::UNAVAILABLE : states::FOCUSABLE | states::SELECTABLE;
 }
 
 int32_t
 HTMLSelectOptionAccessible::GetLevelInternal()
 {
-  nsIContent *parentContent = mContent->GetParent();
+  nsIContent* parentContent = mContent->GetParent();
 
   int32_t level =
     parentContent->NodeInfo()->Equals(nsGkAtoms::optgroup) ? 2 : 1;
 
   if (level == 1 && Role() != roles::HEADING)
     level = 0; // In a single level list, the level is irrelevant
 
   return level;
@@ -317,17 +318,17 @@ HTMLSelectOptionAccessible::DoAction(uin
 }
 
 NS_IMETHODIMP
 HTMLSelectOptionAccessible::SetSelected(bool aSelect)
 {
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsHTMLOptionElement* option = nsHTMLOptionElement::FromContent(mContent);
+  HTMLOptionElement* option = HTMLOptionElement::FromContent(mContent);
   return option ? option->SetSelected(aSelect) : NS_ERROR_FAILURE;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLSelectOptionAccessible: Widgets
 
 Accessible*
 HTMLSelectOptionAccessible::ContainerWidget() const
@@ -420,21 +421,21 @@ HTMLComboboxAccessible::InvalidateChildr
 
 void
 HTMLComboboxAccessible::CacheChildren()
 {
   nsIFrame* frame = GetFrame();
   if (!frame)
     return;
 
-  nsIComboboxControlFrame *comboFrame = do_QueryFrame(frame);
+  nsIComboboxControlFrame* comboFrame = do_QueryFrame(frame);
   if (!comboFrame)
     return;
 
-  nsIFrame *listFrame = comboFrame->GetDropDown();
+  nsIFrame* listFrame = comboFrame->GetDropDown();
   if (!listFrame)
     return;
 
   if (!mListAccessible) {
     mListAccessible = 
       new HTMLComboboxListAccessible(mParent, mContent, mDoc);
 
     // Initialize and put into cache.
@@ -529,21 +530,21 @@ HTMLComboboxAccessible::DoAction(uint8_t
   * Uses the frame to get the state, updated on every click
   */
 NS_IMETHODIMP
 HTMLComboboxAccessible::GetActionName(uint8_t aIndex, nsAString& aName)
 {
   if (aIndex != HTMLComboboxAccessible::eAction_Click) {
     return NS_ERROR_INVALID_ARG;
   }
-  nsIFrame *frame = GetFrame();
+  nsIFrame* frame = GetFrame();
   if (!frame) {
     return NS_ERROR_FAILURE;
   }
-  nsIComboboxControlFrame *comboFrame = do_QueryFrame(frame);
+  nsIComboboxControlFrame* comboFrame = do_QueryFrame(frame);
   if (!comboFrame) {
     return NS_ERROR_FAILURE;
   }
   if (comboFrame->IsDroppedDown())
     aName.AssignLiteral("close"); 
   else
     aName.AssignLiteral("open"); 
 
--- a/accessible/src/html/HTMLTableAccessible.cpp
+++ b/accessible/src/html/HTMLTableAccessible.cpp
@@ -338,26 +338,16 @@ HTMLTableRowAccessible::NativeRole()
 {
   return roles::ROW;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLTableAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
-HTMLTableAccessible::
-  HTMLTableAccessible(nsIContent* aContent, DocAccessible* aDoc) :
-  AccessibleWrap(aContent, aDoc), xpcAccessibleTable(this)
-{
-  mGenericTypes |= eTable;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// HTMLTableAccessible: nsISupports implementation
-
 NS_IMPL_ISUPPORTS_INHERITED1(HTMLTableAccessible, Accessible,
                              nsIAccessibleTable)
 
 ////////////////////////////////////////////////////////////////////////////////
 //nsAccessNode
 
 void
 HTMLTableAccessible::Shutdown()
@@ -1057,17 +1047,17 @@ HTMLTableAccessible::IsProbablyLayoutTab
   uint32_t childCount = ChildCount();
   nscolor rowColor = 0;
   nscolor prevRowColor;
   for (uint32_t childIdx = 0; childIdx < childCount; childIdx++) {
     Accessible* child = GetChildAt(childIdx);
     if (child->Role() == roles::ROW) {
       prevRowColor = rowColor;
       nsIFrame* rowFrame = child->GetFrame();
-      rowColor = rowFrame->GetStyleBackground()->mBackgroundColor;
+      rowColor = rowFrame->StyleBackground()->mBackgroundColor;
 
       if (childIdx > 0 && prevRowColor != rowColor)
         RETURN_LAYOUT_ANSWER(false, "2 styles of row background color, non-bordered");
     }
   }
 
   // Check for many rows
   const int32_t kMaxLayoutRows = 20;
--- a/accessible/src/html/HTMLTableAccessible.h
+++ b/accessible/src/html/HTMLTableAccessible.h
@@ -116,17 +116,22 @@ public:
 // #define SHOW_LAYOUT_HEURISTIC
 
 class HTMLTableAccessible : public AccessibleWrap,
                             public xpcAccessibleTable,
                             public nsIAccessibleTable,
                             public TableAccessible
 {
 public:
-  HTMLTableAccessible(nsIContent* aContent, DocAccessible* aDoc);
+  HTMLTableAccessible(nsIContent* aContent, DocAccessible* aDoc) :
+    AccessibleWrap(aContent, aDoc), xpcAccessibleTable(this)
+  {
+    mType = eHTMLTableType;
+    mGenericTypes |= eTable;
+  }
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessible Table
   NS_FORWARD_NSIACCESSIBLETABLE(xpcAccessibleTable::)
 
   // TableAccessible
   virtual Accessible* Caption();
--- a/accessible/src/windows/ia2/ia2AccessibleComponent.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleComponent.cpp
@@ -87,17 +87,17 @@ ia2AccessibleComponent::get_foreground(I
   A11Y_TRYBLOCK_BEGIN
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsIFrame* frame = acc->GetFrame();
   if (frame)
-    *aForeground = frame->GetStyleColor()->mColor;
+    *aForeground = frame->StyleColor()->mColor;
 
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleComponent::get_background(IA2Color* aBackground)
@@ -105,15 +105,15 @@ ia2AccessibleComponent::get_background(I
   A11Y_TRYBLOCK_BEGIN
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsIFrame* frame = acc->GetFrame();
   if (frame)
-    *aBackground = frame->GetStyleBackground()->mBackgroundColor;
+    *aBackground = frame->StyleBackground()->mBackgroundColor;
 
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
--- a/accessible/src/windows/ia2/ia2AccessibleHypertext.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleHypertext.cpp
@@ -40,17 +40,17 @@ ia2AccessibleHypertext::get_hyperlink(lo
 
   *aHyperlink = NULL;
 
   HyperTextAccessibleWrap* hyperText = static_cast<HyperTextAccessibleWrap*>(this);
   if (hyperText->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* hyperLink = hyperText->GetLinkAt(aLinkIndex);
-  if (!hyperText)
+  if (!hyperLink)
     return E_FAIL;
 
   *aHyperlink =
     static_cast<IAccessibleHyperlink*>(static_cast<AccessibleWrap*>(hyperLink));
   (*aHyperlink)->AddRef();
   return S_OK;
 
   A11Y_TRYBLOCK_END
--- a/accessible/tests/mochitest/name/test_list.html
+++ b/accessible/tests/mochitest/name/test_list.html
@@ -68,17 +68,17 @@
   </script>
 
 </head>
 
 <body>
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=634200"
-     title="crash [@ nsIFrame::GetStyleVisibility() ]">
+     title="crash [@ nsIFrame::StyleVisibility() ]">
     Mozilla Bug 634200
   </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <ol id="list">
--- a/accessible/tests/mochitest/table/test_indexes_table.html
+++ b/accessible/tests/mochitest/table/test_indexes_table.html
@@ -123,26 +123,43 @@ https://bugzilla.mozilla.org/show_bug.cg
         [-1, -1, -1, -1, -1],
         [ 3,  4,  5, -1, -1],
         [ 6,  6,  7, -1, -1],
         [ 8,  9,  7, -1, -1],
         [ 10, 9,  7, 11, 12]
       ];
       testTableIndexes("tableinsane6", idxes);
 
+      //////////////////////////////////////////////////////////////////////////
+      // csstablecrazy1 (no rows)
+      idxes = [
+        [0,  1]
+      ];
+
+      testTableIndexes("csstablecrazy1", idxes);
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
 
-  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">Mozilla Bug 410052</a>
+  <a target="_blank"
+     title="GetIndexAt and GetRowAtIndex and GetColumnAtIndex on HTML tables are inconsistent"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">
+   Bug 410052
+  </a>
+  <a target="_blank"
+     title="Table cell accessibles not exposed for CSS table without table-row "
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=834120">
+   Bug 834120
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <!--
     If you change the structure of the table please make sure to change
     the indexes count in 'for' statement in the script above.
@@ -397,10 +414,16 @@ https://bugzilla.mozilla.org/show_bug.cg
       <tr>
         <td colspan="3">10</td>
         <td>11</td>
         <td>12</td>
       </tr>
     </tbody>
   </table>
 
+  <div id="csstablecrazy1"
+       style="width: 100%; border: 1px solid red; display:table;">
+    <div style="display:table-cell;">cell1</div>
+    <div style="display:table-cell;">cell2</div>
+  </div>
+
 </body>
 </html>
--- a/b2g/app/Makefile.in
+++ b/b2g/app/Makefile.in
@@ -3,16 +3,18 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DEPTH     = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
+USE_RCS_MK := 1
+include $(topsrcdir)/config/makefiles/rcs.mk
 
 PREF_JS_EXPORTS = $(srcdir)/b2g.js
 
 ifdef ENABLE_MARIONETTE
 DEFINES += -DENABLE_MARIONETTE=1
 endif
 
 ifndef LIBXUL_SDK
@@ -71,25 +73,19 @@ include $(topsrcdir)/config/rules.mk
 APP_ICON = b2g
 
 DEFINES += \
   -DAPP_NAME=$(MOZ_APP_NAME) \
   -DAPP_VERSION=$(MOZ_APP_VERSION) \
   -DMOZ_UPDATER=$(MOZ_UPDATER) \
   $(NULL)
 
-# strip a trailing slash from the repo URL because it's not always present,
-# and we want to construct a working URL in buildconfig.html
-# make+shell+sed = awful
-_dollar=$$
-SOURCE_REPO := $(shell cd $(srcdir)/.. && hg showconfig paths.default 2>/dev/null | head -n1 | sed -e "s/^ssh:/http:/" -e "s/\/$(_dollar)//" )
-# extra sanity check for old versions of hg
-# that don't support showconfig
-ifeq (http,$(patsubst http%,http,$(SOURCE_REPO)))
-DEFINES += -DMOZ_SOURCE_REPO="$(SOURCE_REPO)"
+source_repo ?= $(call getSourceRepo,$(srcdir)/..)
+ifneq (,$(filter http%,$(source_repo)))
+  DEFINES += -DMOZ_SOURCE_REPO="$(source_repo)"
 endif
 
 ifeq ($(OS_ARCH),WINNT)
 REDIT_PATH = $(LIBXUL_DIST)/bin
 endif
 
 APP_BINARY = $(MOZ_APP_NAME)$(BIN_SUFFIX)
 
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -64,19 +64,19 @@ XPCOMUtils.defineLazyGetter(this, "ppmm"
 
 #ifdef MOZ_WIDGET_GONK
 XPCOMUtils.defineLazyGetter(this, "libcutils", function () {
   Cu.import("resource://gre/modules/systemlibs.js");
   return libcutils;
 });
 #endif
 
-#ifdef MOZ_SERVICES_CAPTIVEDETECT
+#ifdef MOZ_CAPTIVEDETECT
 XPCOMUtils.defineLazyServiceGetter(Services, 'captivePortalDetector',
-                                  '@mozilla.org/services/captive-detector;1',
+                                  '@mozilla.org/toolkit/captive-detector;1',
                                   'nsICaptivePortalDetector');
 #endif
 
 function getContentWindow() {
   return shell.contentBrowser.contentWindow;
 }
 
 function debug(str) {
--- a/b2g/components/Keyboard.jsm
+++ b/b2g/components/Keyboard.jsm
@@ -41,19 +41,53 @@ let Keyboard = {
     for (let name of this._messageNames)
       ppmm.addMessageListener('Keyboard:' + name, this);
   },
 
   observe: function keyboardObserve(subject, topic, data) {
     let frameLoader = subject.QueryInterface(Ci.nsIFrameLoader);
     let mm = frameLoader.messageManager;
     mm.addMessageListener('Forms:Input', this);
+
+    // When not running apps OOP, we need to load forms.js here since this
+    // won't happen from dom/ipc/preload.js
+    try {
+       if (Services.prefs.getBoolPref("dom.ipc.tabs.disabled") === true) {
+         mm.loadFrameScript(kFormsFrameScript, true);
+       }
+     } catch (e) {
+       dump('Error loading ' + kFormsFrameScript + ' as frame script: ' + e + '\n');
+     }
   },
 
   receiveMessage: function keyboardReceiveMessage(msg) {
+    // If we get a 'Keyboard:XXX' message, check that the sender has the
+    // keyboard permission.
+    if (msg.name != 'Forms:Input') {
+      let mm;
+      try {
+        mm = msg.target.QueryInterface(Ci.nsIFrameLoaderOwner)
+                       .frameLoader.messageManager;
+      } catch(e) {
+        mm = msg.target;
+      }
+
+      // That should never happen.
+      if (!mm) {
+        dump("!! No message manager found for " + msg.name);
+        return;
+      }
+
+      if (!mm.assertPermission("keyboard")) {
+        dump("Keyboard message " + msg.name +
+        " from a content process with no 'keyboard' privileges.");
+        return;
+      }
+    }
+
     switch (msg.name) {
       case 'Forms:Input':
         this.handleFormsInput(msg);
         break;
       case 'Keyboard:SetValue':
         this.setValue(msg);
         break;
       case 'Keyboard:RemoveFocus':
--- a/b2g/components/MozKeyboard.js
+++ b/b2g/components/MozKeyboard.js
@@ -13,17 +13,17 @@ Cu.import("resource://gre/modules/Object
 
 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
   "@mozilla.org/childprocessmessagemanager;1", "nsIMessageSender");
 
 // -----------------------------------------------------------------------
 // MozKeyboard
 // -----------------------------------------------------------------------
 
-function MozKeyboard() { } 
+function MozKeyboard() { }
 
 MozKeyboard.prototype = {
   classID: Components.ID("{397a7fdf-2254-47be-b74e-76625a1a66d5}"),
 
   QueryInterface: XPCOMUtils.generateQI([
     Ci.nsIB2GKeyboard, Ci.nsIDOMGlobalPropertyInitializer, Ci.nsIObserver
   ]),
 
@@ -31,16 +31,25 @@ MozKeyboard.prototype = {
     "classID": Components.ID("{397a7fdf-2254-47be-b74e-76625a1a66d5}"),
     "contractID": "@mozilla.org/b2g-keyboard;1",
     "interfaces": [Ci.nsIB2GKeyboard],
     "flags": Ci.nsIClassInfo.DOM_OBJECT,
     "classDescription": "B2G Virtual Keyboard"
   }),
 
   init: function mozKeyboardInit(win) {
+    let principal = win.document.nodePrincipal;
+    let perm = Services.perms
+               .testExactPermissionFromPrincipal(principal, "keyboard");
+    if (perm != Ci.nsIPermissionManager.ALLOW_ACTION) {
+      dump("No permission to use the keyboard API for " +
+           principal.origin + "\n");
+      return null;
+    }
+
     Services.obs.addObserver(this, "inner-window-destroyed", false);
     cpmm.addMessageListener('Keyboard:FocusChange', this);
 
     this._window = win;
     this._utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
                      .getInterface(Ci.nsIDOMWindowUtils);
     this.innerWindowID = this._utils.currentInnerWindowID;
     this._focusHandler = null;
--- a/b2g/components/b2g.idl
+++ b/b2g/components/b2g.idl
@@ -6,17 +6,17 @@
 
 [scriptable, uuid(3615a616-571d-4194-bf54-ccf546067b14)]
 interface nsIB2GCameraContent : nsISupports
 {
   /* temporary solution, waiting for getUserMedia */
   DOMString getCameraURI([optional] in jsval options);
 };
 
-[scriptable, uuid(53990d7a-ab2a-11e1-8543-7767e4cbcbff)]
+[scriptable, uuid(94233b76-3987-4fc0-8924-7596846f9bd3)]
 interface nsIB2GKeyboard : nsISupports
 {
   void sendKey(in long keyCode, in long charCode);
 
   // Select the <select> option specified by index.
   // If this method is called on a <select> that support multiple
   // selection, then the option specified by index will be added to
   // the selection.
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -15,20 +15,20 @@ MOZ_B2G_OS_NAME=Boot2Gecko
 
 MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
 MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
 # MOZ_APP_DISPLAYNAME is set by branding/configure.sh
 
 MOZ_SAFE_BROWSING=
 MOZ_SERVICES_COMMON=1
 MOZ_SERVICES_METRICS=1
-MOZ_SERVICES_CAPTIVEDETECT=1
+MOZ_CAPTIVEDETECT=1
 
 MOZ_WEBSMS_BACKEND=1
-MOZ_DISABLE_DOMCRYPTO=1
+MOZ_DISABLE_CRYPTOLEGACY=1
 MOZ_APP_STATIC_INI=1
 
 if test "$OS_TARGET" = "Android"; then
 MOZ_CAPTURE=1
 MOZ_RAW=1
 MOZ_AUDIO_CHANNEL_MANAGER=1
 fi
 
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -281,16 +281,19 @@
 @BINPATH@/components/rdf.xpt
 @BINPATH@/components/satchel.xpt
 @BINPATH@/components/saxparser.xpt
 @BINPATH@/components/sessionstore.xpt
 #ifdef MOZ_SERVICES_SYNC
 @BINPATH@/components/services-crypto.xpt
 #endif
 @BINPATH@/components/services-crypto-component.xpt
+#ifdef MOZ_CAPTIVEDETECT
+@BINPATH@/components/captivedetect.xpt
+#endif
 @BINPATH@/components/shellservice.xpt
 @BINPATH@/components/shistory.xpt
 @BINPATH@/components/spellchecker.xpt
 @BINPATH@/components/storage.xpt
 @BINPATH@/components/telemetry.xpt
 @BINPATH@/components/toolkitprofile.xpt
 #ifdef MOZ_ENABLE_XREMOTE
 @BINPATH@/components/toolkitremote.xpt
@@ -487,16 +490,20 @@
 @BINPATH@/components/WeaveCrypto.js
 #endif
 @BINPATH@/components/servicesComponents.manifest
 @BINPATH@/components/cryptoComponents.manifest
 #ifdef MOZ_SERVICES_HEALTHREPORT
 @BINPATH@/components/HealthReportComponents.manifest
 @BINPATH@/components/HealthReportService.js
 #endif
+#ifdef MOZ_CAPTIVEDETECT
+@BINPATH@/components/CaptivePortalDetectComponents.manifest
+@BINPATH@/components/captivedetect.js
+#endif
 @BINPATH@/components/TelemetryPing.js
 @BINPATH@/components/TelemetryPing.manifest
 @BINPATH@/components/Webapps.js
 @BINPATH@/components/Webapps.manifest
 @BINPATH@/components/AppsService.js
 @BINPATH@/components/AppsService.manifest
 
 @BINPATH@/components/nsDOMIdentity.js
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,10 +1,10 @@
 <?xml version="1.0"?>
-<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1359495205000">
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1360959670000">
   <emItems>
       <emItem  blockID="i58" id="webmaster@buzzzzvideos.info">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i41" id="{99079a25-328f-4bd4-be04-00955acaa0a7}">
                         <versionRange  minVersion="0.1" maxVersion="4.3.1.00" severity="1">
                     </versionRange>
@@ -190,30 +190,34 @@
       <emItem  blockID="i127" id="plugin@youtubeplayer.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i77" id="{fa277cfc-1d75-4949-a1f9-4ac8e41b2dfd}">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
+      <emItem  blockID="i284" id="playbryte@playbryte.com">
+                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+                    </versionRange>
+                  </emItem>
       <emItem  blockID="i59" id="ghostviewer@youtube2.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i222" id="dealcabby@jetpack">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i51" id="admin@youtubeplayer.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i258" id="helperbar@helperbar.com">
-                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+                        <versionRange  minVersion="0" maxVersion="1.0" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i46" id="{841468a1-d7f4-4bd3-84e6-bb0f13a06c64}">
                         <versionRange  minVersion="0.1" maxVersion="*">
                       <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="9.0a1" maxVersion="9.0" />
                           </targetApplication>
                     </versionRange>
@@ -313,18 +317,18 @@
       <emItem  blockID="i196" id="info@wxdownloadmanager.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i67" id="youtube2@youtube2.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i56" id="flash@adobe.com">
-                        <versionRange  minVersion="0" maxVersion="*">
+      <emItem  blockID="i282" id="{33e0daa6-3af3-d8b5-6752-10e949c61516}">
+                        <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i216" id="fdm_ffext@freedownloadmanager.org">
                         <versionRange  minVersion="1.0" maxVersion="1.3.1">
                       <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="3.0a1" maxVersion="*" />
                           </targetApplication>
                     </versionRange>
@@ -432,16 +436,20 @@
       <emItem  blockID="i90" id="videoplugin@player.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i68" id="flashupdate@adobe.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
+      <emItem  blockID="i56" id="flash@adobe.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
       <emItem  blockID="i45" id="{22119944-ED35-4ab1-910B-E619EA06A115}">
                         <versionRange  minVersion="0.1" maxVersion="7.6.1">
                       <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="8.0a1" maxVersion="*" />
                           </targetApplication>
                     </versionRange>
                   </emItem>
       <emItem  blockID="i82" id="{8f42fb8b-b6f6-45de-81c0-d6d39f54f971}">
@@ -589,26 +597,26 @@
       <pluginItem  blockID="p160">
                   <match name="filename" exp="NPSWF32\.dll" />                                    <versionRange  minVersion="0" maxVersion="10.2.9999" severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="4.0" maxVersion="16.*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p176">
-                  <match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" />                                    <versionRange  minVersion="0" maxVersion="10.3.183.18.999" severity="0" vulnerabilitystatus="1">
+                  <match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" />                                    <versionRange  minVersion="10.3" maxVersion="10.3.183.18.999" severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="19.0a1" maxVersion="*" />
+                              <versionRange  minVersion="20.0a1" maxVersion="*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p178">
                   <match name="filename" exp="(NPSWF[0-9_]*\.dll)|(Flash\ Player\.plugin)" />                                    <versionRange  minVersion="11.0" maxVersion="11.4.402.286.999" severity="0" vulnerabilitystatus="1">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="19.0a1" maxVersion="*" />
+                              <versionRange  minVersion="20.0a1" maxVersion="*" />
                           </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p180">
                   <match name="filename" exp="JavaAppletPlugin\.plugin" />                                    <versionRange  minVersion="Java 7 Update 0" maxVersion="Java 7 Update 11" severity="0" vulnerabilitystatus="2">
                                 <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="17.0" maxVersion="*" />
                           </targetApplication>
@@ -725,12 +733,32 @@
     <gfxBlacklistEntry  blockID="g200">      <os>Darwin 11</os>      <vendor>0x10de</vendor>            <feature>WEBGL_MSAA</feature>      <featureStatus>BLOCKED_DEVICE</featureStatus>    </gfxBlacklistEntry>
     <gfxBlacklistEntry  blockID="g202">      <os>Darwin 12</os>      <vendor>0x10de</vendor>            <feature>WEBGL_MSAA</feature>      <featureStatus>BLOCKED_DEVICE</featureStatus>    </gfxBlacklistEntry>
     <gfxBlacklistEntry  blockID="g204">      <os>Darwin 10</os>      <vendor>0x8086</vendor>            <feature>WEBGL_MSAA</feature>      <featureStatus>BLOCKED_DEVICE</featureStatus>    </gfxBlacklistEntry>
     <gfxBlacklistEntry  blockID="g206">      <os>Darwin 11</os>      <vendor>0x8086</vendor>            <feature>WEBGL_MSAA</feature>      <featureStatus>BLOCKED_DEVICE</featureStatus>    </gfxBlacklistEntry>
     <gfxBlacklistEntry  blockID="g208">      <os>Darwin 12</os>      <vendor>0x8086</vendor>            <feature>WEBGL_MSAA</feature>      <featureStatus>BLOCKED_DEVICE</featureStatus>    </gfxBlacklistEntry>
     <gfxBlacklistEntry  blockID="g230">      <os>Darwin 10</os>      <vendor>0x1002</vendor>            <feature>WEBGL_MSAA</feature>      <featureStatus>BLOCKED_DEVICE</featureStatus>    </gfxBlacklistEntry>
     <gfxBlacklistEntry  blockID="g232">      <os>Darwin 11</os>      <vendor>0x1002</vendor>            <feature>WEBGL_MSAA</feature>      <featureStatus>BLOCKED_DEVICE</featureStatus>    </gfxBlacklistEntry>
     <gfxBlacklistEntry  blockID="g234">      <os>Darwin 12</os>      <vendor>0x1002</vendor>            <feature>WEBGL_MSAA</feature>      <featureStatus>BLOCKED_DEVICE</featureStatus>    </gfxBlacklistEntry>
+    <gfxBlacklistEntry  blockID="g278">      <os>WINNT 6.1</os>      <vendor>0x1002</vendor>              <devices>
+                      <device>0x9802</device>
+                      <device>0x9803</device>
+                      <device>0x9803</device>
+                      <device>0x9804</device>
+                      <device>0x9805</device>
+                      <device>0x9806</device>
+                      <device>0x9807</device>
+                  </devices>
+            <feature>DIRECT2D</feature>      <featureStatus>BLOCKED_DEVICE</featureStatus>    </gfxBlacklistEntry>
+    <gfxBlacklistEntry  blockID="g280">      <os>WINNT 6.1</os>      <vendor>0x1002</vendor>              <devices>
+                      <device>0x9802</device>
+                      <device>0x9803</device>
+                      <device>0x9803</device>
+                      <device>0x9804</device>
+                      <device>0x9805</device>
+                      <device>0x9806</device>
+                      <device>0x9807</device>
+                  </devices>
+            <feature>DIRECT3D_9_LAYERS</feature>      <featureStatus>BLOCKED_DEVICE</featureStatus>    </gfxBlacklistEntry>
     </gfxItems>
 
 
 </blocklist>
\ No newline at end of file
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -301,16 +301,19 @@ pref("browser.urlbar.match.url", "@");
 // 2 = only bookmarks, 3 = visited bookmarks, 1+16 = history matching in the url
 pref("browser.urlbar.default.behavior", 0);
 
 pref("browser.urlbar.formatting.enabled", true);
 pref("browser.urlbar.trimURLs", true);
 
 pref("browser.altClickSave", false);
 
+// Enable logging downloads operations to the Error Console.
+pref("browser.download.debug", false);
+
 // Number of milliseconds to wait for the http headers (and thus
 // the Content-Disposition filename) before giving up and falling back to 
 // picking a filename without that info in hand so that the user sees some
 // feedback from their action.
 pref("browser.download.saveLinkAsFilenameTimeout", 4000);
 
 pref("browser.download.useDownloadDir", true);
 
@@ -385,16 +388,23 @@ pref("browser.link.open_newwindow", 3);
 // 1-3: see browser.link.open_newwindow for interpretation
 pref("browser.link.open_newwindow.override.external", -1);
 
 // 0: no restrictions - divert everything
 // 1: don't divert window.open at all
 // 2: don't divert window.open with features
 pref("browser.link.open_newwindow.restriction", 2);
 
+// Disable opening a new window via window.open if browser is in fullscreen mode
+#ifdef XP_MACOSX
+pref("browser.link.open_newwindow.disabled_in_fullscreen", true);
+#else
+pref("browser.link.open_newwindow.disabled_in_fullscreen", false);
+#endif
+
 // Tabbed browser
 pref("browser.tabs.autoHide", false);
 pref("browser.tabs.closeWindowWithLastTab", true);
 pref("browser.tabs.insertRelatedAfterCurrent", true);
 pref("browser.tabs.warnOnClose", true);
 pref("browser.tabs.warnOnCloseOtherTabs", true);
 pref("browser.tabs.warnOnOpen", true);
 pref("browser.tabs.maxOpenBeforeWarn", 15);
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -118,17 +118,17 @@ XPCOMUtils.defineLazyGetter(this, "Debug
   Cu.import("resource:///modules/devtools/DebuggerUI.jsm", tmp);
   return new tmp.DebuggerUI(window);
 });
 
 XPCOMUtils.defineLazyModuleGetter(this, "Social",
   "resource:///modules/Social.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs",
-  "resource:///modules/PageThumbs.jsm");
+  "resource://gre/modules/PageThumbs.jsm");
 
 #ifdef MOZ_SAFE_BROWSING
 XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
   "resource://gre/modules/SafeBrowsing.jsm");
 #endif
 
 XPCOMUtils.defineLazyModuleGetter(this, "gBrowserNewTabPreloader",
   "resource:///modules/BrowserNewTabPreloader.jsm", "BrowserNewTabPreloader");
@@ -4012,18 +4012,16 @@ function mimeTypeIsTextBased(aMimeType)
          aMimeType == "application/xml" ||
          aMimeType == "mozilla.application/cached-xul";
 }
 
 var XULBrowserWindow = {
   // Stored Status, Link and Loading values
   status: "",
   defaultStatus: "",
-  jsStatus: "",
-  jsDefaultStatus: "",
   overLink: "",
   startTime: 0,
   statusText: "",
   isBusy: false,
   inContentWhitelist: ["about:addons", "about:downloads", "about:permissions",
                        "about:sync-progress", "about:preferences"],
 
   QueryInterface: function (aIID) {
@@ -4071,24 +4069,22 @@ var XULBrowserWindow = {
     // XXXjag to avoid leaks :-/, see bug 60729
     delete this.throbberElement;
     delete this.stopCommand;
     delete this.reloadCommand;
     delete this.statusTextField;
     delete this.statusText;
   },
 
-  setJSStatus: function (status) {
-    this.jsStatus = status;
-    this.updateStatusField();
-  },
-
-  setJSDefaultStatus: function (status) {
-    this.jsDefaultStatus = status;
-    this.updateStatusField();
+  setJSStatus: function () {
+    // unsupported
+  },
+
+  setJSDefaultStatus: function () {
+    // unsupported
   },
 
   setDefaultStatus: function (status) {
     this.defaultStatus = status;
     this.updateStatusField();
   },
 
   setOverLink: function (url, anchorElt) {
@@ -4103,17 +4099,17 @@ var XULBrowserWindow = {
     this.overLink = url;
     LinkTargetDisplay.update();
   },
 
   updateStatusField: function () {
     var text, type, types = ["overLink"];
     if (this._busyUI)
       types.push("status");
-    types.push("jsStatus", "jsDefaultStatus", "defaultStatus");
+    types.push("defaultStatus");
     for (type of types) {
       text = this[type];
       if (text)
         break;
     }
 
     // check the current value so we don't trigger an attribute change
     // and cause needless (slow!) UI updates
@@ -4340,28 +4336,16 @@ var XULBrowserWindow = {
       if (gURLBar) {
         URLBarSetURI(aLocationURI);
 
         // Update starring UI
         PlacesStarButton.updateState();
         SocialShareButton.updateShareState();
       }
 
-      // Filter out anchor navigation, history.push/pop/replaceState and
-      // tab switches.
-      if (aRequest) {
-        // Only need to call locationChange if the PopupNotifications object
-        // for this window has already been initialized (i.e. its getter no
-        // longer exists)
-        // XXX bug 839445: We never tell PopupNotifications about location
-        // changes in background tabs.
-        if (!__lookupGetter__("PopupNotifications"))
-          PopupNotifications.locationChange();
-      }
-
       // Show or hide browser chrome based on the whitelist
       if (this.hideChromeForLocation(location)) {
         document.documentElement.setAttribute("disablechrome", "true");
       } else {
         let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
         if (ss.getTabValue(gBrowser.selectedTab, "appOrigin"))
           document.documentElement.setAttribute("disablechrome", "true");
         else
@@ -4728,22 +4712,26 @@ var TabsProgressListener = {
         aStateFlags & Ci.nsIWebProgressListener.STATE_START &&
         aStateFlags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT &&
         gCrashReporter.enabled) {
       gCrashReporter.annotateCrashReport("URL", aRequest.URI.spec);
     }
 #endif
 
     // Collect telemetry data about tab load times.
-    if (aWebProgress.DOMWindow == aWebProgress.DOMWindow.top &&
-        aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
-      if (aStateFlags & Ci.nsIWebProgressListener.STATE_START)
-        TelemetryStopwatch.start("FX_PAGE_LOAD_MS", aBrowser);
-      else if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP)
-        TelemetryStopwatch.finish("FX_PAGE_LOAD_MS", aBrowser);
+    if (aWebProgress.DOMWindow == aWebProgress.DOMWindow.top) {
+      if (aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
+        if (aStateFlags & Ci.nsIWebProgressListener.STATE_START)
+          TelemetryStopwatch.start("FX_PAGE_LOAD_MS", aBrowser);
+        else if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP)
+          TelemetryStopwatch.finish("FX_PAGE_LOAD_MS", aBrowser);
+      } else if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
+                 aStatus == Cr.NS_BINDING_ABORTED) {
+        TelemetryStopwatch.cancel("FX_PAGE_LOAD_MS", aBrowser);
+      }
     }
 
     // Attach a listener to watch for "click" events bubbling up from error
     // pages and other similar page. This lets us fix bugs like 401575 which
     // require error page UI to do privileged things, without letting error
     // pages have any privilege themselves.
     // We can't look for this during onLocationChange since at that point the
     // document URI is not yet the about:-uri of the error page.
@@ -4775,16 +4763,22 @@ var TabsProgressListener = {
     if (aBrowser.contentWindow == aWebProgress.DOMWindow) {
       // Filter out any onLocationChanges triggered by anchor navigation
       // or history.push/pop/replaceState.
       if (aRequest) {
         // Initialize the click-to-play state.
         aBrowser._clickToPlayPluginsActivated = new Map();
         aBrowser._clickToPlayAllPluginsActivated = false;
         aBrowser._pluginScriptedState = gPluginHandler.PLUGIN_SCRIPTED_STATE_NONE;
+
+        // Only need to call locationChange if the PopupNotifications object
+        // for this window has already been initialized (i.e. its getter no
+        // longer exists)
+        if (!Object.getOwnPropertyDescriptor(window, "PopupNotifications").get)
+          PopupNotifications.locationChange(aBrowser);
       }
       FullZoom.onLocationChange(aLocationURI, false, aBrowser);
     }
   },
 
   onRefreshAttempted: function (aBrowser, aWebProgress, aURI, aDelay, aSameURI) {
     if (gPrefService.getBoolPref("accessibility.blockautorefresh")) {
       let brandBundle = document.getElementById("bundle_brand");
@@ -6884,17 +6878,18 @@ var gIdentityHandler = {
     let nsIWebProgressListener = Ci.nsIWebProgressListener;
     if (location.protocol == "chrome:" || location.protocol == "about:") {
       this.setMode(this.IDENTITY_MODE_CHROMEUI);
     } else if (state & nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL) {
       this.setMode(this.IDENTITY_MODE_IDENTIFIED);
     } else if (state & nsIWebProgressListener.STATE_IS_SECURE) {
       this.setMode(this.IDENTITY_MODE_DOMAIN_VERIFIED);
     } else if (state & nsIWebProgressListener.STATE_IS_BROKEN) {
-      if (state & nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT) {
+      if ((state & nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT) &&
+          gPrefService.getBoolPref("security.mixed_content.block_active_content")) {
         this.setMode(this.IDENTITY_MODE_MIXED_ACTIVE_CONTENT);
       } else {
         this.setMode(this.IDENTITY_MODE_MIXED_CONTENT);
       }
     } else {
       this.setMode(this.IDENTITY_MODE_UNKNOWN);
     }
 
--- a/browser/base/content/newtab/newTab.js
+++ b/browser/base/content/newtab/newTab.js
@@ -4,18 +4,18 @@
 
 "use strict";
 
 let Cu = Components.utils;
 let Ci = Components.interfaces;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource:///modules/PageThumbs.jsm");
-Cu.import("resource:///modules/NewTabUtils.jsm");
+Cu.import("resource://gre/modules/PageThumbs.jsm");
+Cu.import("resource://gre/modules/NewTabUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Rect",
   "resource://gre/modules/Geometry.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 let {
   links: gLinks,
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1245,17 +1245,16 @@
             var uriIsNotAboutBlank = aURI && aURI != "about:blank";
 
             if (uriIsBlankPage)
               t.setAttribute("label", this.mStringBundle.getString("tabs.emptyTabTitle"));
             else
               t.setAttribute("label", aURI);
 
             t.setAttribute("crop", "end");
-            t.setAttribute("validate", "never");
             t.setAttribute("onerror", "this.removeAttribute('image');");
             t.className = "tabbrowser-tab";
 
             this.tabContainer._unlockTabSizing();
 
             // When overflowing, new tabs are scrolled into view smoothly, which
             // doesn't go well together with the width transition. So we skip the
             // transition in that case.
@@ -2878,17 +2877,16 @@
           this.mTabClipWidth = Services.prefs.getIntPref("browser.tabs.tabClipWidth");
           this.mCloseButtons = Services.prefs.getIntPref("browser.tabs.closeButtons");
           this._closeWindowWithLastTab = Services.prefs.getBoolPref("browser.tabs.closeWindowWithLastTab");
 
           var tab = this.firstChild;
           tab.setAttribute("label",
                            this.tabbrowser.mStringBundle.getString("tabs.emptyTabTitle"));
           tab.setAttribute("crop", "end");
-          tab.setAttribute("validate", "never");
           tab.setAttribute("onerror", "this.removeAttribute('image');");
           this.adjustTabstrip();
 
           Services.prefs.addObserver("browser.tabs.", this._prefObserver, false);
           window.addEventListener("resize", this, false);
           window.addEventListener("load", this, false);
 
           try {
@@ -4090,18 +4088,19 @@
                     class="tab-background-end"/>
         </xul:hbox>
         <xul:hbox xbl:inherits="pinned,selected,titlechanged"
                   class="tab-content" align="center">
           <xul:image xbl:inherits="fadein,pinned,busy,progress,selected"
                      class="tab-throbber"
                      role="presentation"
                      layer="true" />
-          <xul:image xbl:inherits="validate,src=image,fadein,pinned,selected"
+          <xul:image xbl:inherits="src=image,fadein,pinned,selected"
                      class="tab-icon-image"
+                     validate="never"
                      role="presentation"/>
           <xul:label flex="1"
                      xbl:inherits="value=label,crop,accesskey,fadein,pinned,selected"
                      class="tab-text tab-label"
                      role="presentation"/>
           <xul:toolbarbutton anonid="close-button"
                              xbl:inherits="fadein,pinned,selected"
                              class="tab-close-button"/>
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -168,16 +168,18 @@ endif
                  browser_homeDrop.js \
                  browser_keywordBookmarklets.js \
                  browser_contextSearchTabPosition.js \
                  browser_ctrlTab.js \
                  browser_customize_popupNotification.js \
                  browser_disablechrome.js \
                  browser_discovery.js \
                  browser_duplicateIDs.js \
+                 browser_fullscreen-window-open.js \
+                 file_fullscreen-window-open.html \
                  browser_gestureSupport.js \
                  browser_getshortcutoruri.js \
                  browser_hide_removing.js \
                  browser_overflowScroll.js \
                  browser_locationBarCommand.js \
                  browser_locationBarExternalLoad.js \
                  browser_page_style_menu.js \
                  browser_pinnedTabs.js \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_fullscreen-window-open.js
@@ -0,0 +1,394 @@
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+let Cc = Components.classes;
+let Ci = Components.interfaces;
+
+const PREF_DISABLE_OPEN_NEW_WINDOW = "browser.link.open_newwindow.disabled_in_fullscreen";
+const isOSX = (Services.appinfo.OS === "Darwin");
+
+const TEST_FILE = "file_fullscreen-window-open.html";
+const gHttpTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/",
+                                                          "http://127.0.0.1:8888/");
+
+function test () {
+  waitForExplicitFinish();
+
+  Services.prefs.setBoolPref(PREF_DISABLE_OPEN_NEW_WINDOW, true);
+
+  let newTab = gBrowser.addTab();
+  gBrowser.selectedTab = newTab;
+
+  let gTestBrowser = gBrowser.selectedBrowser;
+  gTestBrowser.addEventListener("load", function onLoad(){
+    gTestBrowser.removeEventListener("load", onLoad, true, true);
+
+    // Enter browser fullscreen mode.
+    BrowserFullScreen();
+
+    runNextTest();
+  }, true, true);
+  gTestBrowser.contentWindow.location.href = gHttpTestRoot + TEST_FILE;
+}
+
+registerCleanupFunction(function(){
+  // Exit browser fullscreen mode.
+  BrowserFullScreen();
+
+  gBrowser.removeCurrentTab();
+
+  Services.prefs.clearUserPref(PREF_DISABLE_OPEN_NEW_WINDOW);
+});
+
+let gTests = [
+  test_open,
+  test_open_with_size,
+  test_open_with_pos,
+  test_open_with_outerSize,
+  test_open_with_innerSize,
+  test_open_with_dialog,
+  test_open_when_open_new_window_by_pref,
+  test_open_with_pref_to_disable_in_fullscreen,
+  test_open_from_chrome,
+];
+
+function runNextTest () {
+  let test = gTests.shift();
+  if (test) {
+    executeSoon(test);
+  }
+  else {
+    finish();
+  }
+}
+
+
+// Test for window.open() with no feature.
+function test_open() {
+  waitForTabOpen({
+    message: {
+      title: "test_open",
+      param: "",
+    },
+    finalizeFn: function () {},
+  });
+}
+
+// Test for window.open() with width/height.
+function test_open_with_size() {
+  waitForTabOpen({
+    message: {
+      title: "test_open_with_size",
+      param: "width=400,height=400",
+    },
+    finalizeFn: function () {},
+  });
+}
+
+// Test for window.open() with top/left.
+function test_open_with_pos() {
+  waitForTabOpen({
+    message: {
+      title: "test_open_with_pos",
+      param: "top=200,left=200",
+    },
+    finalizeFn: function () {},
+  });
+}
+
+// Test for window.open() with outerWidth/Height.
+function test_open_with_outerSize() {
+  let [outerWidth, outerHeight] = [window.outerWidth, window.outerHeight];
+  waitForTabOpen({
+    message: {
+      title: "test_open_with_outerSize",
+      param: "outerWidth=200,outerHeight=200",
+    },
+    successFn: function () {
+      is(window.outerWidth, outerWidth, "Don't change window.outerWidth.");
+      is(window.outerHeight, outerHeight, "Don't change window.outerHeight.");
+    },
+    finalizeFn: function () {},
+  });
+}
+
+// Test for window.open() with innerWidth/Height.
+function test_open_with_innerSize() {
+  let [innerWidth, innerHeight] = [window.innerWidth, window.innerHeight];
+  waitForTabOpen({
+    message: {
+      title: "test_open_with_innerSize",
+      param: "innerWidth=200,innerHeight=200",
+    },
+    successFn: function () {
+      is(window.innerWidth, innerWidth, "Don't change window.innerWidth.");
+      is(window.innerHeight, innerHeight, "Don't change window.innerHeight.");
+    },
+    finalizeFn: function () {},
+  });
+}
+
+// Test for window.open() with dialog.
+function test_open_with_dialog() {
+  waitForTabOpen({
+    message: {
+      title: "test_open_with_dialog",
+      param: "dialog=yes",
+    },
+    finalizeFn: function () {},
+  });
+}
+
+// Test for window.open()
+// when "browser.link.open_newwindow" is nsIBrowserDOMWindow.OPEN_NEWWINDOW
+function test_open_when_open_new_window_by_pref() {
+  const PREF_NAME = "browser.link.open_newwindow";
+  Services.prefs.setIntPref(PREF_NAME, Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW);
+  is(Services.prefs.getIntPref(PREF_NAME), Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW,
+     PREF_NAME + " is nsIBrowserDOMWindow.OPEN_NEWWINDOW at this time");
+
+  waitForTabOpen({
+    message: {
+      title: "test_open_when_open_new_window_by_pref",
+      param: "width=400,height=400",
+    },
+    finalizeFn: function () {
+      Services.prefs.clearUserPref(PREF_NAME);
+    },
+  });
+}
+
+// Test for the pref, "browser.link.open_newwindow.disabled_in_fullscreen"
+function test_open_with_pref_to_disable_in_fullscreen() {
+  Services.prefs.setBoolPref(PREF_DISABLE_OPEN_NEW_WINDOW, false);
+
+  waitForWindowOpen({
+    message: {
+      title: "test_open_with_pref_disabled_in_fullscreen",
+      param: "width=400,height=400",
+    },
+    finalizeFn: function () {
+      Services.prefs.setBoolPref(PREF_DISABLE_OPEN_NEW_WINDOW, true);
+    },
+  });
+}
+
+
+// Test for window.open() called from chrome context.
+function test_open_from_chrome() {
+  waitForWindowOpenFromChrome({
+    message: {
+      title: "test_open_from_chrome",
+      param: "",
+    },
+    finalizeFn: function () {},
+    timeout: 10000,
+  });
+}
+
+function waitForTabOpen(aOptions) {
+  let start = Date.now();
+  let timeout = aOptions.timeout || 5000;
+  let message = aOptions.message;
+
+  if (!message.title) {
+    ok(false, "Can't get message.title.");
+    aOptions.finalizeFn();
+    runNextTest();
+    return;
+  }
+
+  info("Running test: " + message.title);
+
+  let onTabOpen = function onTabOpen(aEvent) {
+    gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen, true);
+
+    let tab = aEvent.target;
+    tab.linkedBrowser.addEventListener("load", function onLoad(ev){
+      let browser = ev.currentTarget;
+      browser.removeEventListener("load", onLoad, true, true);
+      clearTimeout(onTimeout);
+
+      is(browser.contentWindow.document.title, message.title,
+         "Opened Tab is expected: " + message.title);
+
+      if (aOptions.successFn) {
+        aOptions.successFn();
+      }
+
+      gBrowser.removeTab(tab);
+      finalize();
+    }, true, true);
+  }
+  gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen, true);
+
+  let finalize = function () {
+    aOptions.finalizeFn();
+    info("Finished: " + message.title);
+    runNextTest();
+  };
+
+  let onTimeout = setTimeout(function(){
+    gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen, true);
+
+    ok(false, "Timeout: '"+message.title + "'.");
+    finalize();
+  }, timeout);
+
+
+  const URI = "data:text/html;charset=utf-8,<!DOCTYPE html><html><head><title>"+
+              message.title +
+              "<%2Ftitle><%2Fhead><body><%2Fbody><%2Fhtml>";
+
+  executeWindowOpenInContent({
+    uri: URI,
+    title: message.title,
+    option: message.param,
+  });
+}
+
+
+function waitForWindowOpen(aOptions) {
+  let start = Date.now();
+  let timeout = aOptions.timeout || 10000;
+  let message = aOptions.message;
+  let url = aOptions.url || getBrowserURL();
+
+  if (!message.title) {
+    ok(false, "Can't get message.title");
+    aOptions.finalizeFn();
+    runNextTest();
+    return;
+  }
+
+  info("Running test: " + message.title);
+
+  let onFinalize = function () {
+    aOptions.finalizeFn();
+
+    info("Finished: " + message.title);
+    runNextTest();
+  };
+
+  let onTimeout = setTimeout(function(){
+    Services.wm.removeListener(listener);
+    ok(false, "Fail: '"+message.title + "'.");
+
+    onFinalize();
+  }, timeout);
+
+  let listener = new WindowListener(message.title, url, {
+    onSuccess: aOptions.successFn,
+    onTimeout: onTimeout,
+    onFinalize: onFinalize,
+  });
+  Services.wm.addListener(listener);
+
+  const URI = aOptions.url || "about:blank";
+
+  executeWindowOpenInContent({
+    uri: URI,
+    title: message.title,
+    option: message.param,
+  });
+}
+
+function executeWindowOpenInContent(aParam) {
+  var testWindow = gBrowser.selectedBrowser.contentWindow;
+  var testElm = testWindow.document.getElementById("test");
+
+  testElm.setAttribute("data-test-param", JSON.stringify(aParam));
+  EventUtils.synthesizeMouseAtCenter(testElm, {}, testWindow);
+}
+
+function waitForWindowOpenFromChrome(aOptions) {
+  let start = Date.now();
+  let timeout = aOptions.timeout || 10000;
+  let message = aOptions.message;
+  let url = aOptions.url || getBrowserURL();
+
+  if (!message.title) {
+    ok(false, "Can't get message.title");
+    aOptions.finalizeFn();
+    runNextTest();
+    return;
+  }
+
+  info("Running test: " + message.title);
+
+  let onFinalize = function () {
+    aOptions.finalizeFn();
+
+    info("Finished: " + message.title);
+    runNextTest();
+  };
+
+  let onTimeout = setTimeout(function(){
+    Services.wm.removeListener(listener);
+    ok(false, "Fail: '"+message.title + "'.");
+
+    testWindow.close();
+    onFinalize();
+  }, timeout);
+
+  let listener = new WindowListener(message.title, url, {
+    onSuccess: aOptions.successFn,
+    onTimeout: onTimeout,
+    onFinalize: onFinalize,
+  });
+  Services.wm.addListener(listener);
+
+
+  const URI = aOptions.url || "about:blank";
+
+  let testWindow = window.open(URI, message.title, message.option);
+}
+
+function WindowListener(aTitle, aUrl, aCallBackObj) {
+  this.test_title = aTitle;
+  this.test_url = aUrl;
+  this.callback_onSuccess = aCallBackObj.onSuccess;
+  this.callBack_onTimeout = aCallBackObj.onTimeout;
+  this.callBack_onFinalize = aCallBackObj.onFinalize;
+}
+WindowListener.prototype = {
+
+  test_title: null,
+  test_url: null,
+  callback_onSuccess: null,
+  callBack_onTimeout: null,
+  callBack_onFinalize: null,
+
+  onOpenWindow: function(aXULWindow) {
+    Services.wm.removeListener(this);
+
+    let domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                    .getInterface(Ci.nsIDOMWindow);
+    domwindow.addEventListener("load", function onLoad(aEvent) {
+      is(domwindow.document.location.href, this.test_url,
+        "Opened Window is expected: "+ this.test_title);
+      if (this.callback_onSuccess) {
+        this.callback_onSuccess();
+      }
+
+      domwindow.removeEventListener("load", onLoad, true);
+      clearTimeout(this.callBack_onTimeout);
+
+      // wait for trasition to fullscreen on OSX Lion later
+      if (isOSX) {
+        setTimeout(function(){
+          domwindow.close();
+          executeSoon(this.callBack_onFinalize);
+        }.bind(this), 3000);
+      }
+      else {
+        domwindow.close();
+        executeSoon(this.callBack_onFinalize);
+      }
+    }.bind(this), true);
+  },
+  onCloseWindow: function(aXULWindow) {},
+  onWindowTitleChange: function(aXULWindow, aNewTitle) {},
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIWindowMediatorListener,
+                                         Ci.nsISupports]),
+};
--- a/browser/base/content/test/browser_popupNotification.js
+++ b/browser/base/content/test/browser_popupNotification.js
@@ -22,26 +22,26 @@ function cleanUp() {
 }
 
 const PREF_SECURITY_DELAY_INITIAL = Services.prefs.getIntPref("security.notification_enable_delay");
 
 var gActiveListeners = {};
 var gActiveObservers = {};
 var gShownState = {};
 
+function goNext() {
+  if (++gTestIndex == tests.length)
+    executeSoon(finish);
+  else
+    executeSoon(runNextTest);
+}
+
 function runNextTest() {
   let nextTest = tests[gTestIndex];
 
-  function goNext() {
-    if (++gTestIndex == tests.length)
-      executeSoon(finish);
-    else
-      executeSoon(runNextTest);
-  }
-
   function addObserver(topic) {
     function observer() {
       Services.obs.removeObserver(observer, "PopupNotifications-" + topic);
       delete gActiveObservers["PopupNotifications-" + topic];
 
       info("[Test #" + gTestIndex + "] observer for " + topic + " called");
       nextTest[topic]();
       goNext();
@@ -49,17 +49,17 @@ function runNextTest() {
     Services.obs.addObserver(observer, "PopupNotifications-" + topic, false);
     gActiveObservers["PopupNotifications-" + topic] = observer;
   }
 
   if (nextTest.backgroundShow) {
     addObserver("backgroundShow");
   } else if (nextTest.updateNotShowing) {
     addObserver("updateNotShowing");
-  } else {
+  } else if (nextTest.onShown) {
     doOnPopupEvent("popupshowing", function () {
       info("[Test #" + gTestIndex + "] popup showing");
     });
     doOnPopupEvent("popupshown", function () {
       gShownState[gTestIndex] = true;
       info("[Test #" + gTestIndex + "] popup shown");
       nextTest.onShown(this);
     });
@@ -719,16 +719,44 @@ var tests = [
       }, 500);
 
     },
     onHidden: function (popup) {
       ok(this.notifyObj.mainActionClicked, "mainAction was clicked after the delay");
       ok(!this.notifyObj.dismissalCallbackTriggered, "dismissal callback was not triggered");
       PopupNotifications.buttonDelay = PREF_SECURITY_DELAY_INITIAL;
     },
+  },
+  { // Test #25 - location change in background tab removes notification
+    run: function () {
+      this.oldSelectedTab = gBrowser.selectedTab;
+      this.newTab = gBrowser.addTab("about:blank");
+      gBrowser.selectedTab = this.newTab;
+
+      loadURI("http://example.com/", function() {
+        gBrowser.selectedTab = this.oldSelectedTab;
+        let browser = gBrowser.getBrowserForTab(this.newTab);
+
+        this.notifyObj = new basicNotification();
+        this.notifyObj.browser = browser;
+        this.notifyObj.options.eventCallback = function (eventName) {
+          if (eventName == "removed") {
+            ok(true, "Notification removed in background tab after reloading");
+            executeSoon(function () {
+              gBrowser.removeTab(this.newTab);
+              goNext();
+            }.bind(this));
+          }
+        }.bind(this);
+        this.notification = showNotification(this.notifyObj);
+        executeSoon(function () {
+          browser.reload();
+        });
+      }.bind(this));
+    }
   }
 ];
 
 function showNotification(notifyObj) {
   return PopupNotifications.show(notifyObj.browser,
                                  notifyObj.id,
                                  notifyObj.message,
                                  notifyObj.anchorID,
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/file_fullscreen-window-open.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Test for window.open() when browser is in fullscreen</title>
+  </head>
+  <body>
+    <script>
+      window.addEventListener("load", function onLoad() {
+        window.removeEventListener("load", onLoad, true);
+
+        document.getElementById("test").addEventListener("click", onClick, true);
+      }, true);
+
+      function onClick(aEvent) {
+        aEvent.preventDefault();
+
+        var dataStr = aEvent.target.getAttribute("data-test-param");
+        var data = JSON.parse(dataStr);
+        window.open(data.uri, data.title, data.option);
+      }
+    </script>
+    <a id="test" href="" data-test-param="">Test</a>
+  </body>
+</html>
--- a/browser/base/content/test/newtab/head.js
+++ b/browser/base/content/test/newtab/head.js
@@ -1,17 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const PREF_NEWTAB_ENABLED = "browser.newtabpage.enabled";
 
 Services.prefs.setBoolPref(PREF_NEWTAB_ENABLED, true);
 
 let tmp = {};
-Cu.import("resource:///modules/NewTabUtils.jsm", tmp);
+Cu.import("resource://gre/modules/NewTabUtils.jsm", tmp);
 Cc["@mozilla.org/moz/jssubscript-loader;1"]
   .getService(Ci.mozIJSSubScriptLoader)
   .loadSubScript("chrome://browser/content/sanitize.js", tmp);
 
 let {NewTabUtils, Sanitizer} = tmp;
 
 let uri = Services.io.newURI("about:newtab", null, null);
 let principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(uri);
--- a/browser/components/Makefile.in
+++ b/browser/components/Makefile.in
@@ -37,17 +37,16 @@ PARALLEL_DIRS = \
   places \
   preferences \
   privatebrowsing \
   search \
   sessionstore \
   shell \
   sidebar \
   tabview \
-  thumbnails \
   migration \
   $(NULL)
 
 ifdef MOZ_SAFE_BROWSING
 PARALLEL_DIRS += safebrowsing
 endif
 
 TEST_DIRS += test
--- a/browser/components/downloads/content/downloads.js
+++ b/browser/components/downloads/content/downloads.js
@@ -116,64 +116,74 @@ const DownloadsPanel = {
    * Starts loading the download data in background, without opening the panel.
    * Use showPanel instead to load the data and open the panel at the same time.
    *
    * @param aCallback
    *        Called when initialization is complete.
    */
   initialize: function DP_initialize(aCallback)
   {
+    DownloadsCommon.log("Attempting to initialize DownloadsPanel for a window.");
     if (this._state != this.kStateUninitialized) {
+      DownloadsCommon.log("DownloadsPanel is already initialized.");
       DownloadsOverlayLoader.ensureOverlayLoaded(this.kDownloadsOverlay,
                                                  aCallback);
       return;
     }
     this._state = this.kStateHidden;
 
     window.addEventListener("unload", this.onWindowUnload, false);
 
     // Ensure that the Download Manager service is running.  This resumes
     // active downloads if required.  If there are downloads to be shown in the
     // panel, starting the service will make us load their data asynchronously.
     Services.downloads;
 
     // Now that data loading has eventually started, load the required XUL
     // elements and initialize our views.
+    DownloadsCommon.log("Ensuring DownloadsPanel overlay loaded.");
     DownloadsOverlayLoader.ensureOverlayLoaded(this.kDownloadsOverlay,
                                                function DP_I_callback() {
       DownloadsViewController.initialize();
+      DownloadsCommon.log("Attaching DownloadsView...");
       DownloadsCommon.getData(window).addView(DownloadsView);
+      DownloadsCommon.log("DownloadsView attached - the panel for this window",
+                          "should now see download items come in.");
       DownloadsPanel._attachEventListeners();
+      DownloadsCommon.log("DownloadsPanel initialized.");
       aCallback();
     });
   },
 
   /**
    * Closes the downloads panel and frees the internal resources related to the
    * downloads.  The downloads panel can be reopened later, even after this
    * function has been called.
    */
   terminate: function DP_terminate()
   {
+    DownloadsCommon.log("Attempting to terminate DownloadsPanel for a window.");
     if (this._state == this.kStateUninitialized) {
+      DownloadsCommon.log("DownloadsPanel was never initialized. Nothing to do.");
       return;
     }
 
     window.removeEventListener("unload", this.onWindowUnload, false);
 
     // Ensure that the panel is closed before shutting down.
     this.hidePanel();
 
     DownloadsViewController.terminate();
     DownloadsCommon.getData(window).removeView(DownloadsView);
     this._unattachEventListeners();
 
     this._state = this.kStateUninitialized;
 
     DownloadsSummary.active = false;
+    DownloadsCommon.log("DownloadsPanel terminated.");
   },
 
   //////////////////////////////////////////////////////////////////////////////
   //// Panel interface
 
   /**
    * Main panel element in the browser window.
    */
@@ -186,48 +196,56 @@ const DownloadsPanel = {
   /**
    * Starts opening the downloads panel interface, anchored to the downloads
    * button of the browser window.  The list of downloads to display is
    * initialized the first time this method is called, and the panel is shown
    * only when data is ready.
    */
   showPanel: function DP_showPanel()
   {
+    DownloadsCommon.log("Opening the downloads panel.");
+
     if (this.isPanelShowing) {
+      DownloadsCommon.log("Panel is already showing - focusing instead.");
       this._focusPanel();
       return;
     }
 
     this.initialize(function DP_SP_callback() {
       // Delay displaying the panel because this function will sometimes be
       // called while another window is closing (like the window for selecting
       // whether to save or open the file), and that would cause the panel to
       // close immediately.
       setTimeout(function () DownloadsPanel._openPopupIfDataReady(), 0);
     }.bind(this));
 
+    DownloadsCommon.log("Waiting for the downloads panel to appear.");
     this._state = this.kStateWaitingData;
   },
 
   /**
    * Hides the downloads panel, if visible, but keeps the internal state so that
    * the panel can be reopened quickly if required.
    */
   hidePanel: function DP_hidePanel()
   {
+    DownloadsCommon.log("Closing the downloads panel.");
+
     if (!this.isPanelShowing) {
+      DownloadsCommon.log("Downloads panel is not showing - nothing to do.");
       return;
     }
 
     this.panel.hidePopup();
 
     // Ensure that we allow the panel to be reopened.  Note that, if the popup
     // was open, then the onPopupHidden event handler has already updated the
     // current state, otherwise we must update the state ourselves.
     this._state = this.kStateHidden;
+    DownloadsCommon.log("Downloads panel is now closed.");
   },
 
   /**
    * Indicates whether the panel is shown or will be shown.
    */
   get isPanelShowing()
   {
     return this._state == this.kStateWaitingData ||
@@ -293,16 +311,17 @@ const DownloadsPanel = {
 
   onPopupShown: function DP_onPopupShown(aEvent)
   {
     // Ignore events raised by nested popups.
     if (aEvent.target != aEvent.currentTarget) {
       return;
     }
 
+    DownloadsCommon.log("Downloads panel has shown.");
     this._state = this.kStateShown;
 
     // Since at most one popup is open at any given time, we can set globally.
     DownloadsCommon.getIndicatorData(window).attentionSuppressed = true;
 
     // Ensure that an item is selected when the panel is focused.
     if (DownloadsView.richListBox.itemCount > 0 &&
         !DownloadsView.richListBox.selectedItem) {
@@ -314,16 +333,18 @@ const DownloadsPanel = {
 
   onPopupHidden: function DP_onPopupHidden(aEvent)
   {
     // Ignore events raised by nested popups.
     if (aEvent.target != aEvent.currentTarget) {
       return;
     }
 
+    DownloadsCommon.log("Downloads panel has hidden.");
+
     // Removes the keyfocus attribute so that we stop handling keyboard
     // navigation.
     this.keyFocusing = false;
 
     // Since at most one popup is open at any given time, we can set globally.
     DownloadsCommon.getIndicatorData(window).attentionSuppressed = false;
 
     // Allow the anchor to be hidden.
@@ -336,16 +357,17 @@ const DownloadsPanel = {
   //////////////////////////////////////////////////////////////////////////////
   //// Related operations
 
   /**
    * Shows or focuses the user interface dedicated to downloads history.
    */
   showDownloadsHistory: function DP_showDownloadsHistory()
   {
+    DownloadsCommon.log("Showing download history.");
     // Hide the panel before showing another window, otherwise focus will return
     // to the browser window when the panel closes automatically.
     this.hidePanel();
 
     BrowserDownloadsUI();
   },
 
   //////////////////////////////////////////////////////////////////////////////
@@ -440,16 +462,18 @@ const DownloadsPanel = {
 #else
                   aEvent.ctrlKey;
 #endif
 
     if (!pasting) {
       return;
     }
 
+    DownloadsCommon.log("Received a paste event.");
+
     let trans = Cc["@mozilla.org/widget/transferable;1"]
                   .createInstance(Ci.nsITransferable);
     trans.init(null);
     let flavors = ["text/x-moz-url", "text/unicode"];
     flavors.forEach(trans.addDataFlavor);
     Services.clipboard.getData(trans, Services.clipboard.kGlobalClipboard);
     // Getting the data or creating the nsIURI might fail
     try {
@@ -459,16 +483,17 @@ const DownloadsPanel = {
                             .QueryInterface(Ci.nsISupportsString)
                             .data
                             .split("\n");
       if (!url) {
         return;
       }
 
       let uri = NetUtil.newURI(url);
+      DownloadsCommon.log("Pasted URL seems valid. Starting download.");
       saveURL(uri.spec, name || uri.spec, null, true, true,
               undefined, document);
     } catch (ex) {}
   },
 
   /**
    * Move focus to the main element in the downloads panel, unless another
    * element in the panel is already focused.
@@ -520,19 +545,23 @@ const DownloadsPanel = {
       // minimized and in that case force the panel to the closed state.
       if (window.windowState == Ci.nsIDOMChromeWindow.STATE_MINIMIZED) {
         DownloadsButton.releaseAnchor();
         this._state = this.kStateHidden;
         return;
       }
 
       if (aAnchor) {
+        DownloadsCommon.log("Opening downloads panel popup.");
         this.panel.openPopup(aAnchor, "bottomcenter topright", 0, 0, false,
                              null);
       } else {
+        DownloadsCommon.error("We can't find the anchor! Failure case - opening",
+                              "downloads panel on TabsToolbar. We should never",
+                              "get here!");
         Components.utils.reportError(
           "Downloads button cannot be found");
       }
     }.bind(this));
   }
 };
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -592,16 +621,17 @@ const DownloadsOverlayLoader = {
       // reapplied, including "iconsize" on the toolbars.  Until bug 640158 is
       // fixed, we must recalculate the correct "iconsize" attributes manually.
       retrieveToolbarIconsizesFromTheme();
 
       this.processPendingRequests();
     }
 
     this._overlayLoading = true;
+    DownloadsCommon.log("Loading overlay ", aOverlay);
     document.loadOverlay(aOverlay, DOL_EOL_loadCallback.bind(this));
   },
 
   /**
    * Re-processes all the currently pending requests, invoking the callbacks
    * and/or loading more overlays as needed.  In most cases, there will be a
    * single request for one overlay, that will be processed immediately.
    */
@@ -658,22 +688,26 @@ const DownloadsView = {
    */
   _viewItems: {},
 
   /**
    * Called when the number of items in the list changes.
    */
   _itemCountChanged: function DV_itemCountChanged()
   {
+    DownloadsCommon.log("The downloads item count has changed - we are tracking",
+                        this._dataItems.length, "downloads in total.");
     let count = this._dataItems.length;
     let hiddenCount = count - this.kItemCountLimit;
 
     if (count > 0) {
+      DownloadsCommon.log("Setting the panel's hasdownloads attribute to true.");
       DownloadsPanel.panel.setAttribute("hasdownloads", "true");
     } else {
+      DownloadsCommon.log("Removing the panel's hasdownloads attribute.");
       DownloadsPanel.panel.removeAttribute("hasdownloads");
     }
 
     // If we've got some hidden downloads, we should activate the
     // DownloadsSummary. The DownloadsSummary will determine whether or not
     // it's appropriate to actually display the summary.
     DownloadsSummary.active = hiddenCount > 0;
   },
@@ -699,24 +733,27 @@ const DownloadsView = {
   //////////////////////////////////////////////////////////////////////////////
   //// Callback functions from DownloadsData
 
   /**
    * Called before multiple downloads are about to be loaded.
    */
   onDataLoadStarting: function DV_onDataLoadStarting()
   {
+    DownloadsCommon.log("onDataLoadStarting called for DownloadsView.");
     this.loading = true;
   },
 
   /**
    * Called after data loading finished.
    */
   onDataLoadCompleted: function DV_onDataLoadCompleted()
   {
+    DownloadsCommon.log("onDataLoadCompleted called for DownloadsView.");
+
     this.loading = false;
 
     // We suppressed item count change notifications during the batch load, at
     // this point we should just call the function once.
     this._itemCountChanged();
 
     // Notify the panel that all the initially available downloads have been
     // loaded.  This ensures that the interface is visible, if still required.
@@ -725,16 +762,19 @@ const DownloadsView = {
 
   /**
    * Called when the downloads database becomes unavailable (for example,
    * entering Private Browsing Mode).  References to existing data should be
    * discarded.
    */
   onDataInvalidated: function DV_onDataInvalidated()
   {
+    DownloadsCommon.log("Downloads data has been invalidated. Cleaning up",
+                        "DownloadsView.");
+
     DownloadsPanel.terminate();
 
     // Clear the list by replacing with a shallow copy.
     let emptyView = this.richListBox.cloneNode(false);
     this.richListBox.parentNode.replaceChild(emptyView, this.richListBox);
     this.richListBox = emptyView;
     this._viewItems = {};
     this._dataItems = [];
@@ -750,16 +790,19 @@ const DownloadsView = {
    *        When true, indicates that this item is the most recent and should be
    *        added in the topmost position.  This happens when a new download is
    *        started.  When false, indicates that the item is the least recent
    *        and should be appended.  The latter generally happens during the
    *        asynchronous data load.
    */
   onDataItemAdded: function DV_onDataItemAdded(aDataItem, aNewest)
   {
+    DownloadsCommon.log("A new download data item was added - aNewest =",
+                        aNewest);
+
     if (aNewest) {
       this._dataItems.unshift(aDataItem);
     } else {
       this._dataItems.push(aDataItem);
     }
 
     let itemsNowOverflow = this._dataItems.length > this.kItemCountLimit;
     if (aNewest || !itemsNowOverflow) {
@@ -785,16 +828,18 @@ const DownloadsView = {
    * Called when a data item is removed.  Ensures that the widget associated
    * with the view item is removed from the user interface.
    *
    * @param aDataItem
    *        DownloadsDataItem object that is being removed.
    */
   onDataItemRemoved: function DV_onDataItemRemoved(aDataItem)
   {
+    DownloadsCommon.log("A download data item was removed.");
+
     let itemIndex = this._dataItems.indexOf(aDataItem);
     this._dataItems.splice(itemIndex, 1);
 
     if (itemIndex < this.kItemCountLimit) {
       // The item to remove is visible in the panel.
       this._removeViewItem(aDataItem);
       if (this._dataItems.length >= this.kItemCountLimit) {
         // Reinsert the next item into the panel.
@@ -832,31 +877,35 @@ const DownloadsView = {
   }),
 
   /**
    * Creates a new view item associated with the specified data item, and adds
    * it to the top or the bottom of the list.
    */
   _addViewItem: function DV_addViewItem(aDataItem, aNewest)
   {
+    DownloadsCommon.log("Adding a new DownloadsViewItem to the downloads list.",
+                        "aNewest =", aNewest);
+
     let element = document.createElement("richlistitem");
     let viewItem = new DownloadsViewItem(aDataItem, element);
     this._viewItems[aDataItem.downloadGuid] = viewItem;
     if (aNewest) {
       this.richListBox.insertBefore(element, this.richListBox.firstChild);
     } else {
       this.richListBox.appendChild(element);
     }
   },
 
   /**
    * Removes the view item associated with the specified data item.
    */
   _removeViewItem: function DV_removeViewItem(aDataItem)
   {
+    DownloadsCommon.log("Removing a DownloadsViewItem from the downloads list.");
     let element = this.getViewItem(aDataItem)._element;
     let previousSelectedIndex = this.richListBox.selectedIndex;
     this.richListBox.removeChild(element);
     this.richListBox.selectedIndex = Math.min(previousSelectedIndex,
                                               this.richListBox.itemCount - 1);
     delete this._viewItems[aDataItem.downloadGuid];
   },
 
--- a/browser/components/downloads/src/DownloadsCommon.jsm
+++ b/browser/components/downloads/src/DownloadsCommon.jsm
@@ -54,16 +54,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
                                   "resource://gre/modules/DownloadUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
                                   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
                                   "resource:///modules/RecentWindow.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
                                   "resource://gre/modules/PlacesUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "DownloadsLogger",
+                                  "resource:///modules/DownloadsLogger.jsm");
 
 const nsIDM = Ci.nsIDownloadManager;
 
 const kDownloadsStringBundleUrl =
   "chrome://browser/locale/downloads/downloads.properties";
 
 const kPrefBdmScanWhenDone =   "browser.download.manager.scanWhenDone";
 const kPrefBdmAlertOnExeOpen = "browser.download.manager.alertOnEXEOpen";
@@ -85,24 +87,61 @@ const kDownloadsStringsRequiringPluralFo
 
 XPCOMUtils.defineLazyGetter(this, "DownloadsLocalFileCtor", function () {
   return Components.Constructor("@mozilla.org/file/local;1",
                                 "nsILocalFile", "initWithPath");
 });
 
 const kPartialDownloadSuffix = ".part";
 
+const kPrefDebug = "browser.download.debug";
+
+let DebugPrefObserver = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
+                                         Ci.nsISupportsWeakReference]),
+  observe: function PDO_observe(aSubject, aTopic, aData) {
+    this.debugEnabled = Services.prefs.getBoolPref(kPrefDebug);
+  }
+}
+
+XPCOMUtils.defineLazyGetter(DebugPrefObserver, "debugEnabled", function () {
+  Services.prefs.addObserver(kPrefDebug, DebugPrefObserver, true);
+  return Services.prefs.getBoolPref(kPrefDebug);
+});
+
+
 ////////////////////////////////////////////////////////////////////////////////
 //// DownloadsCommon
 
 /**
  * This object is exposed directly to the consumers of this JavaScript module,
  * and provides shared methods for all the instances of the user interface.
  */
 this.DownloadsCommon = {
+  log: function DC_log(...aMessageArgs) {
+    delete this.log;
+    this.log = function DC_log(...aMessageArgs) {
+      if (!DebugPrefObserver.debugEnabled) {
+        return;
+      }
+      DownloadsLogger.log.apply(DownloadsLogger, aMessageArgs);
+    }
+    this.log.apply(this, aMessageArgs);
+  },
+
+  error: function DC_error(...aMessageArgs) {
+    delete this.error;
+    this.error = function DC_error(...aMessageArgs) {
+      if (!DebugPrefObserver.debugEnabled) {
+        return;
+      }
+      DownloadsLogger.reportError.apply(DownloadsLogger, aMessageArgs);
+    }
+    this.error.apply(this, aMessageArgs);
+  },
   /**
    * Returns an object whose keys are the string names from the downloads string
    * bundle, and whose values are either the translated strings or functions
    * returning formatted strings.
    */
   get strings()
   {
     let strings = {};
@@ -682,17 +721,18 @@ DownloadsDataCtor.prototype = {
                        : aSource.getResultByName("guid");
     if (downloadGuid in this.dataItems) {
       let existingItem = this.dataItems[downloadGuid];
       if (existingItem || !aMayReuseGUID) {
         // Returns null if the download was removed and we can't reuse the item.
         return existingItem;
       }
     }
-
+    DownloadsCommon.log("Creating a new DownloadsDataItem with downloadGuid =",
+                        downloadGuid);
     let dataItem = new DownloadsDataItem(aSource);
     this.dataItems[downloadGuid] = dataItem;
 
     // Create the view items before returning.
     let addToStartOfList = aSource instanceof Ci.nsIDownload;
     this._views.forEach(
       function (view) view.onDataItemAdded(dataItem, addToStartOfList)
     );
@@ -754,16 +794,17 @@ DownloadsDataCtor.prototype = {
 
     if (this._pendingStatement) {
       // We are already in the process of reloading all downloads.
       return;
     }
 
     if (aActiveOnly) {
       if (this._loadState == this.kLoadNone) {
+        DownloadsCommon.log("Loading only active downloads from the persistence database");
         // Indicate to the views that a batch loading operation is in progress.
         this._views.forEach(
           function (view) view.onDataLoadStarting()
         );
 
         // Reload the list using the Download Manager service.  The list is
         // returned in no particular order.
         let downloads = Services.downloads.activeDownloads;
@@ -772,23 +813,25 @@ DownloadsDataCtor.prototype = {
           this._getOrAddDataItem(download, true);
         }
         this._loadState = this.kLoadActive;
 
         // Indicate to the views that the batch loading operation is complete.
         this._views.forEach(
           function (view) view.onDataLoadCompleted()
         );
+        DownloadsCommon.log("Active downloads done loading.");
       }
     } else {
       if (this._loadState != this.kLoadAll) {
         // Load only the relevant columns from the downloads database.  The
         // columns are read in the _initFromDataRow method of DownloadsDataItem.
         // Order by descending download identifier so that the most recent
         // downloads are notified first to the listening views.
+        DownloadsCommon.log("Loading all downloads from the persistence database.");
         let dbConnection = Services.downloads.DBConnection;
         let statement = dbConnection.createAsyncStatement(
           "SELECT guid, target, name, source, referrer, state, "
         +        "startTime, endTime, currBytes, maxBytes "
         + "FROM moz_downloads "
         + "ORDER BY startTime DESC"
         );
         try {
@@ -829,22 +872,24 @@ DownloadsDataCtor.prototype = {
       // unless we already received a notification providing more reliable
       // information for this download.
       this._getOrAddDataItem(row, false);
     }
   },
 
   handleError: function DD_handleError(aError)
   {
-    Cu.reportError("Database statement execution error (" + aError.result +
-                   "): " + aError.message);
+    DownloadsCommon.error("Database statement execution error (",
+                          aError.result, "): ", aError.message);
   },
 
   handleCompletion: function DD_handleCompletion(aReason)
   {
+    DownloadsCommon.log("Loading all downloads from database completed with reason:",
+                        aReason);
     this._pendingStatement = null;
 
     // To ensure that we don't inadvertently delete more downloads from the
     // database than needed on shutdown, we should update the load state only if
     // the operation completed successfully.
     if (aReason == Ci.mozIStorageStatementCallback.REASON_FINISHED) {
       this._loadState = this.kLoadAll;
     }
@@ -863,31 +908,36 @@ DownloadsDataCtor.prototype = {
   //// nsIObserver
 
   observe: function DD_observe(aSubject, aTopic, aData)
   {
     switch (aTopic) {
       case "download-manager-remove-download-guid":
         // If a single download was removed, remove the corresponding data item.
         if (aSubject) {
-          this._removeDataItem(aSubject.QueryInterface(Ci.nsISupportsCString)
-                                       .data);
+            let downloadGuid = aSubject.QueryInterface(Ci.nsISupportsCString).data;
+            DownloadsCommon.log("A single download with id",
+                                downloadGuid, "was removed.");
+          this._removeDataItem(downloadGuid);
           break;
         }
 
         // Multiple downloads have been removed.  Iterate over known downloads
         // and remove those that don't exist anymore.
+        DownloadsCommon.log("Multiple downloads were removed.");
         for each (let dataItem in this.dataItems) {
           if (dataItem) {
             // Bug 449811 - We have to bind to the dataItem because Javascript
             // doesn't do fresh let-bindings per loop iteration.
             let dataItemBinding = dataItem;
             Services.downloads.getDownloadByGUID(dataItemBinding.downloadGuid,
                                                  function(aStatus, aResult) {
               if (aStatus == Components.results.NS_ERROR_NOT_AVAILABLE) {
+                DownloadsCommon.log("Removing download with id",
+                                    dataItemBinding.downloadGuid);
                 this._removeDataItem(dataItemBinding.downloadGuid);
               }
             }.bind(this));
           }
         }
         break;
     }
   },
@@ -911,16 +961,17 @@ DownloadsDataCtor.prototype = {
 
     let dataItem = this._getOrAddDataItem(aDownload, isNew);
     if (!dataItem) {
       return;
     }
 
     let wasInProgress = dataItem.inProgress;
 
+    DownloadsCommon.log("A download changed its state to:", aDownload.state);
     dataItem.state = aDownload.state;
     dataItem.referrer = aDownload.referrer && aDownload.referrer.spec;
     dataItem.resumable = aDownload.resumable;
     dataItem.startTime = Math.round(aDownload.startTime / 1000);
     dataItem.currBytes = aDownload.amountTransferred;
     dataItem.maxBytes = aDownload.size;
 
     if (wasInProgress && !dataItem.inProgress) {
@@ -1029,30 +1080,33 @@ DownloadsDataCtor.prototype = {
    * Displays a new or finished download notification in the most recent browser
    * window, if one is currently available with the required privacy type.
    *
    * @param aType
    *        Set to "start" for new downloads, "finish" for completed downloads.
    */
   _notifyDownloadEvent: function DD_notifyDownloadEvent(aType)
   {
+    DownloadsCommon.log("Attempting to notify that a new download has started or finished.");
     if (DownloadsCommon.useToolkitUI) {
+      DownloadsCommon.log("Cancelling notification - we're using the toolkit downloads manager.");
       return;
     }
 
     // Show the panel in the most recent browser window, if present.
     let browserWin = RecentWindow.getMostRecentBrowserWindow({ private: this._isPrivate });
     if (!browserWin) {
       return;
     }
 
     if (this.panelHasShownBefore) {
       // For new downloads after the first one, don't show the panel
       // automatically, but provide a visible notification in the topmost
       // browser window, if the status indicator is already visible.
+      DownloadsCommon.log("Showing new download notification.");
       browserWin.DownloadsIndicatorView.showEventNotification(aType);
       return;
     }
     this.panelHasShownBefore = true;
     browserWin.DownloadsPanel.showPanel();
   }
 };
 
new file mode 100644
--- /dev/null
+++ b/browser/components/downloads/src/DownloadsLogger.jsm
@@ -0,0 +1,76 @@
+/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * The contents of this file were copied almost entirely from
+ * toolkit/identity/LogUtils.jsm. Until we've got a more generalized logging
+ * mechanism for toolkit, I think this is going to be how we roll.
+ */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = ["DownloadsLogger"];
+const PREF_DEBUG = "browser.download.debug";
+
+const Cu = Components.utils;
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+const Cr = Components.results;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+this.DownloadsLogger = {
+  _generateLogMessage: function _generateLogMessage(args) {
+    // create a string representation of a list of arbitrary things
+    let strings = [];
+
+    for (let arg of args) {
+      if (typeof arg === 'string') {
+        strings.push(arg);
+      } else if (arg === undefined) {
+        strings.push('undefined');
+      } else if (arg === null) {
+        strings.push('null');
+      } else {
+        try {
+          strings.push(JSON.stringify(arg, null, 2));
+        } catch(err) {
+          strings.push("<<something>>");
+        }
+      }
+    };
+    return 'Downloads: ' + strings.join(' ');
+  },
+
+  /**
+   * log() - utility function to print a list of arbitrary things
+   *
+   * Enable with about:config pref browser.download.debug
+   */
+  log: function DL_log(...args) {
+    let output = this._generateLogMessage(args);
+    dump(output + "\n");
+
+    // Additionally, make the output visible in the Error Console
+    Services.console.logStringMessage(output);
+  },
+
+  /**
+   * reportError() - report an error through component utils as well as
+   * our log function
+   */
+  reportError: function DL_reportError(...aArgs) {
+    // Report the error in the browser
+    let output = this._generateLogMessage(aArgs);
+    Cu.reportError(output);
+    dump("ERROR:" + output + "\n");
+    for (let frame = Components.stack.caller; frame; frame = frame.caller) {
+      dump("\t" + frame + "\n");
+    }
+  }
+
+};
--- a/browser/components/downloads/src/Makefile.in
+++ b/browser/components/downloads/src/Makefile.in
@@ -13,13 +13,14 @@ EXTRA_COMPONENTS = \
   BrowserDownloads.manifest \
   DownloadsUI.js \
   $(NULL)
 
 EXTRA_PP_COMPONENTS = \
   DownloadsStartup.js \
   $(NULL)
 
-EXTRA_PP_JS_MODULES = \
+EXTRA_JS_MODULES = \
   DownloadsCommon.jsm \
+  DownloadsLogger.jsm \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -31,20 +31,20 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 
 XPCOMUtils.defineLazyModuleGetter(this, "BookmarkHTMLUtils",
                                   "resource://gre/modules/BookmarkHTMLUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "webappsUI",
                                   "resource:///modules/webappsUI.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs",
-                                  "resource:///modules/PageThumbs.jsm");
+                                  "resource://gre/modules/PageThumbs.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
-                                  "resource:///modules/NewTabUtils.jsm");
+                                  "resource://gre/modules/NewTabUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "BrowserNewTabPreloader",
                                   "resource:///modules/BrowserNewTabPreloader.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PdfJs",
                                   "resource://pdf.js/PdfJs.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "webrtcUI",
--- a/browser/components/sessionstore/src/SessionStore.jsm
+++ b/browser/components/sessionstore/src/SessionStore.jsm
@@ -287,16 +287,21 @@ let SessionStoreInternal = {
   _restorePinnedTabsOnDemand: null,
 
   // The state from the previous session (after restoring pinned tabs). This
   // state is persisted and passed through to the next session during an app
   // restart to make the third party add-on warning not trash the deferred
   // session
   _lastSessionState: null,
 
+  // When starting Firefox with a single private window, this is the place
+  // where we keep the session we actually wanted to restore in case the user
+  // decides to later open a non-private window as well.
+  _deferredInitialState: null,
+
   // A promise resolved once initialization is complete
   _promiseInitialization: Promise.defer(),
 
   // Whether session has been initialized
   _sessionInitialized: false,
 
   // The original "sessionstore.resume_session_once" preference value before it
   // was modified by saveState.  saveState will set the
@@ -677,58 +682,81 @@ let SessionStoreInternal = {
     aWindow.__SSi = "window" + Date.now();
 
     // and create its data object
     this._windows[aWindow.__SSi] = { tabs: [], selected: 0, _closedTabs: [], busy: false };
 
     // and create its internal data object
     this._internalWindows[aWindow.__SSi] = { hosts: {} }
 
+    let isPrivateWindow = false;
     if (PrivateBrowsingUtils.isWindowPrivate(aWindow))
-      this._windows[aWindow.__SSi].isPrivate = true;
+      this._windows[aWindow.__SSi].isPrivate = isPrivateWindow = true;
     if (!this._isWindowLoaded(aWindow))
       this._windows[aWindow.__SSi]._restoring = true;
     if (!aWindow.toolbar.visible)
       this._windows[aWindow.__SSi].isPopup = true;
 
     // perform additional initialization when the first window is loading
     if (this._loadState == STATE_STOPPED) {
       this._loadState = STATE_RUNNING;
       this._lastSaveTime = Date.now();
 
       // restore a crashed session resp. resume the last session if requested
       if (this._initialState) {
-        TelemetryTimestamps.add("sessionRestoreRestoring");
-        // make sure that the restored tabs are first in the window
-        this._initialState._firstTabs = true;
-        this._restoreCount = this._initialState.windows ? this._initialState.windows.length : 0;
-        this.restoreWindow(aWindow, this._initialState,
-                           this._isCmdLineEmpty(aWindow, this._initialState));
-        delete this._initialState;
-
-        // _loadState changed from "stopped" to "running"
-        // force a save operation so that crashes happening during startup are correctly counted
-        this.saveState(true);
+        if (isPrivateWindow) {
+          // We're starting with a single private window. Save the state we
+          // actually wanted to restore so that we can do it later in case
+          // the user opens another, non-private window.
+          this._deferredInitialState = this._initialState;
+          delete this._initialState;
+
+          // Nothing to restore now, notify observers things are complete.
+          Services.obs.notifyObservers(null, NOTIFY_WINDOWS_RESTORED, "");
+        } else {
+          TelemetryTimestamps.add("sessionRestoreRestoring");
+          // make sure that the restored tabs are first in the window
+          this._initialState._firstTabs = true;
+          this._restoreCount = this._initialState.windows ? this._initialState.windows.length : 0;
+          this.restoreWindow(aWindow, this._initialState,
+                             this._isCmdLineEmpty(aWindow, this._initialState));
+          delete this._initialState;
+
+          // _loadState changed from "stopped" to "running"
+          // force a save operation so that crashes happening during startup are correctly counted
+          this.saveState(true);
+        }
       }
       else {
         // Nothing to restore, notify observers things are complete.
         Services.obs.notifyObservers(null, NOTIFY_WINDOWS_RESTORED, "");
 
         // the next delayed save request should execute immediately
         this._lastSaveTime -= this._interval;
       }
     }
     // this window was opened by _openWindowWithState
     else if (!this._isWindowLoaded(aWindow)) {
       let followUp = this._statesToRestore[aWindow.__SS_restoreID].windows.length == 1;
       this.restoreWindow(aWindow, this._statesToRestore[aWindow.__SS_restoreID], true, followUp);
     }
+    // The user opened another, non-private window after starting up with
+    // a single private one. Let's restore the session we actually wanted to
+    // restore at startup.
+    else if (this._deferredInitialState && !isPrivateWindow &&
+             aWindow.toolbar.visible) {
+
+      this._deferredInitialState._firstTabs = true;
+      this._restoreCount = this._deferredInitialState.windows ?
+        this._deferredInitialState.windows.length : 0;
+      this.restoreWindow(aWindow, this._deferredInitialState, true);
+      this._deferredInitialState = null;
+    }
     else if (this._restoreLastWindow && aWindow.toolbar.visible &&
-             this._closedWindows.length &&
-             !PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
+             this._closedWindows.length && !isPrivateWindow) {
 
       // default to the most-recently closed window
       // don't use popup windows
       let closedWindowState = null;
       let closedWindowIndex;
       for (let i = 0; i < this._closedWindows.length; i++) {
         // Take the first non-popup, point our object at it, and break out.
         if (!this._closedWindows[i].isPopup) {
@@ -3626,16 +3654,25 @@ let SessionStoreInternal = {
     for (let i = oState.windows.length - 1; i >= 0; i--) {
       if (oState.windows[i].isPrivate) {
         oState.windows.splice(i, 1);
         if (oState.selectedWindow >= i) {
           oState.selectedWindow--;
         }
       }
     }
+
+    // Don't save invalid states.
+    // Looks we currently have private windows, only.
+    if (oState.windows.length == 0) {
+      TelemetryStopwatch.cancel("FX_SESSION_RESTORE_COLLECT_DATA_MS");
+      TelemetryStopwatch.cancel("FX_SESSION_RESTORE_COLLECT_DATA_LONGEST_OP_MS");
+      return;
+    }
+
     for (let i = oState._closedWindows.length - 1; i >= 0; i--) {
       if (oState._closedWindows[i].isPrivate) {
         oState._closedWindows.splice(i, 1);
       }
     }
 
 #ifndef XP_MACOSX
     // We want to restore closed windows that are marked with _shouldRestore.
--- a/browser/components/tabview/tabview.js
+++ b/browser/components/tabview/tabview.js
@@ -25,17 +25,17 @@ XPCOMUtils.defineLazyGetter(this, "tabbr
 function tabviewString(name) tabviewBundle.GetStringFromName('tabview.' + name);
 function tabbrowserString(name) tabbrowserBundle.GetStringFromName(name);
 
 XPCOMUtils.defineLazyGetter(this, "gPrefBranch", function() {
   return Services.prefs.getBranch("browser.panorama.");
 });
 
 XPCOMUtils.defineLazyModuleGetter(this, "gPageThumbnails",
-  "resource:///modules/PageThumbs.jsm", "PageThumbs");
+  "resource://gre/modules/PageThumbs.jsm", "PageThumbs");
 
 var gWindow = window.parent;
 var gBrowser = gWindow.gBrowser;
 var gTabView = gWindow.TabView;
 var gTabViewDeck = gWindow.document.getElementById("tab-view-deck");
 var gBrowserPanel = gWindow.document.getElementById("browser-panel");
 var gTabViewFrame = gWindow.document.getElementById("tab-view");
 
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-11.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-11.js
@@ -182,17 +182,17 @@ function testFrameParameters()
             "Should have the right property name for 'type' in buttonProtoNode.");
           is(buttonProtoNode.get("type").target.querySelector(".value")
              .getAttribute("value"), '"submit"',
             "'type' in buttonProtoNode should have the right value.");
           is(buttonProtoNode.get("formMethod").target.querySelector(".name")
              .getAttribute("value"), "formMethod",
             "Should have the right property name for 'formMethod' in buttonProtoNode.");
           is(buttonProtoNode.get("formMethod").target.querySelector(".value")
-             .getAttribute("value"), '"get"',
+             .getAttribute("value"), '""',
             "'formMethod' in buttonProtoNode should have the right value.");
 
           is(documentProtoNode.get("baseURI").target.querySelector(".name")
              .getAttribute("value"), "baseURI",
             "Should have the right property name for 'baseURI' in documentProtoNode.");
           is(documentProtoNode.get("baseURI").target.querySelector(".value")
              .getAttribute("value"), '"' + TAB_URL + '"',
             "'baseURI' in documentProtoNode should have the right value.");
@@ -238,17 +238,17 @@ function testFrameParameters()
               "Should have the right property name for 'type' in buttonAsProtoProtoProtoNode.");
             is(buttonAsProtoProtoProtoNode.get("type").target.querySelector(".value")
                .getAttribute("value"), '"submit"',
               "'type' in buttonAsProtoProtoProtoNode should have the right value.");
             is(buttonAsProtoProtoProtoNode.get("formMethod").target.querySelector(".name")
                .getAttribute("value"), "formMethod",
               "Should have the right property name for 'formMethod' in buttonAsProtoProtoProtoNode.");
             is(buttonAsProtoProtoProtoNode.get("formMethod").target.querySelector(".value")
-               .getAttribute("value"), '"get"',
+               .getAttribute("value"), '""',
               "'formMethod' in buttonAsProtoProtoProtoNode should have the right value.");
 
             resumeAndFinish();
           }, 100);
         }, 100);
       }, 100);
     }}, 0);
   }, false);
--- a/browser/devtools/profiler/ProfilerPanel.jsm
+++ b/browser/devtools/profiler/ProfilerPanel.jsm
@@ -465,18 +465,20 @@ ProfilerPanel.prototype = {
         viewSource(data.uri, null, this.document, data.line);
     }
 
     gDevTools.showToolbox(this.target, "jsdebugger").then(function (toolbox) {
       let dbg = toolbox.getCurrentPanel();
       panelWin = dbg.panelWin;
 
       let view = dbg.panelWin.DebuggerView;
-      if (view.Source && view.Sources.selectedValue === data.uri) {
-        return void view.editor.setCaretPosition(data.line - 1);
+      if (view.Sources.selectedValue === data.uri) {
+        view.editor.setCaretPosition(data.line - 1);
+        onOpen();
+        return;
       }
 
       panelWin.addEventListener("Debugger:SourceShown", onSourceShown, false);
       panelWin.DebuggerView.Sources.preferredSource = data.uri;
     }.bind(this));
   },
 
   /**
--- a/browser/devtools/profiler/test/browser_profiler_bug_834878_source_buttons.js
+++ b/browser/devtools/profiler/test/browser_profiler_bug_834878_source_buttons.js
@@ -13,17 +13,26 @@ function test() {
       let data = { uri: SCRIPT, line: 5, isChrome: false };
 
       panel.displaySource(data, function onOpen() {
         let target = TargetFactory.forTab(tab);
         let dbg = gDevTools.getToolbox(target).getPanel("jsdebugger");
         let view = dbg.panelWin.DebuggerView;
 
         is(view.Sources.selectedValue, data.uri, "URI is different");
-        is(view.editor.getCaretPosition().line, data.line - 1, "Line is different");
+        is(view.editor.getCaretPosition().line, data.line - 1,
+          "Line is different");
 
-        tearDown(tab);
+        // Test the case where script is already loaded.
+        view.editor.setCaretPosition(1);
+        gDevTools.showToolbox(target, "jsprofiler").then(function () {
+          panel.displaySource(data, function onOpenAgain() {
+            is(view.editor.getCaretPosition().line, data.line - 1,
+              "Line is different");
+            tearDown(tab);
+          });
+        });
       });
     });
 
     panel.createProfile();
   });
 }
--- a/browser/devtools/shared/DeveloperToolbar.jsm
+++ b/browser/devtools/shared/DeveloperToolbar.jsm
@@ -621,27 +621,26 @@ function DT__updateErrorsCount(aChangedT
     return;
   }
 
   let errors = this._errorsCount[tabId];
   let warnings = this._warningsCount[tabId];
   let btn = this._errorCounterButton;
   if (errors) {
     let errorsText = toolboxStrings
-                     .GetStringFromName("toolboxToggleButton.errorsCount");
-    errorsText = PluralForm.get(errors, errorsText);
+                     .GetStringFromName("toolboxToggleButton.errors");
+    errorsText = PluralForm.get(errors, errorsText).replace("#1", errors);
 
     let warningsText = toolboxStrings
-                       .GetStringFromName("toolboxToggleButton.warningsCount");
-    warningsText = PluralForm.get(warnings, warningsText);
+                       .GetStringFromName("toolboxToggleButton.warnings");
+    warningsText = PluralForm.get(warnings, warningsText).replace("#1", warnings);
 
     let tooltiptext = toolboxStrings
-                      .formatStringFromName("toolboxToggleButton.tooltiptext",
-                                            [errors, errorsText, warnings,
-                                             warningsText], 4);
+                      .formatStringFromName("toolboxToggleButton.tooltip",
+                                            [errorsText, warningsText], 2);
 
     btn.setAttribute("error-count", errors);
     btn.setAttribute("tooltiptext", tooltiptext);
   } else {
     btn.removeAttribute("error-count");
     btn.setAttribute("tooltiptext", btn._defaultTooltipText);
   }
 };
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,4 +1,4 @@
 This is the pdf.js project output, https://github.com/mozilla/pdf.js
 
-Current extension version is: 0.7.210
+Current extension version is: 0.7.236
 
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -11,18 +11,18 @@
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 var PDFJS = {};
-PDFJS.version = '0.7.210';
-PDFJS.build = '7f6456d';
+PDFJS.version = '0.7.236';
+PDFJS.build = 'f8e70dc';
 
 (function pdfjsWrapper() {
   // Use strict in our context only - users might not want it
   'use strict';
 
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 /* Copyright 2012 Mozilla Foundation
@@ -1542,16 +1542,18 @@ var PDFPageProxy = (function PDFPageProx
     },
     /**
      * Begins the process of rendering a page to the desired context.
      * @param {object} params A parameter object that supports:
      * {
      *   canvasContext(required): A 2D context of a DOM Canvas object.,
      *   textLayer(optional): An object that has beginLayout, endLayout, and
      *                        appendText functions.,
+     *   imageLayer(optional): An object that has beginLayout, endLayout and
+     *                         appendImage functions.,
      *   continueCallback(optional): A function that will be called each time
      *                               the rendering is paused.  To continue
      *                               rendering call the function that is the
      *                               first argument to the callback.
      * }.
      * @return {Promise} A promise that is resolved when the page finishes
      * rendering.
      */
@@ -1593,17 +1595,17 @@ var PDFPageProxy = (function PDFPageProx
       this.displayReadyPromise.then(
         function pageDisplayReadyPromise() {
           if (self.destroyed) {
             complete();
             return;
           }
 
           var gfx = new CanvasGraphics(params.canvasContext, this.commonObjs,
-            this.objs, params.textLayer);
+            this.objs, params.textLayer, params.imageLayer);
           try {
             this.display(gfx, params.viewport, complete, continueCallback);
           } catch (e) {
             complete(e);
           }
         }.bind(this),
         function pageDisplayReadPromiseError(reason) {
           complete(reason);
@@ -2208,26 +2210,27 @@ var CanvasExtraState = (function CanvasE
   return CanvasExtraState;
 })();
 
 var CanvasGraphics = (function CanvasGraphicsClosure() {
   // Defines the time the executeOperatorList is going to be executing
   // before it stops and shedules a continue of execution.
   var EXECUTION_TIME = 15;
 
-  function CanvasGraphics(canvasCtx, commonObjs, objs, textLayer) {
+  function CanvasGraphics(canvasCtx, commonObjs, objs, textLayer, imageLayer) {
     this.ctx = canvasCtx;
     this.current = new CanvasExtraState();
     this.stateStack = [];
     this.pendingClip = null;
     this.res = null;
     this.xobjs = null;
     this.commonObjs = commonObjs;
     this.objs = objs;
     this.textLayer = textLayer;
+    this.imageLayer = imageLayer;
     if (canvasCtx) {
       addContextCurrentTransform(canvasCtx);
     }
   }
 
   function applyStencilMask(imgArray, width, height, inverseDecode, buffer) {
     var imgArrayPos = 0;
     var i, j, mask, buf;
@@ -2393,18 +2396,22 @@ var CanvasGraphics = (function CanvasGra
       'shadingFill': true
     },
 
     beginDrawing: function CanvasGraphics_beginDrawing(viewport) {
       var transform = viewport.transform;
       this.ctx.save();
       this.ctx.transform.apply(this.ctx, transform);
 
-      if (this.textLayer)
+      if (this.textLayer) {
         this.textLayer.beginLayout();
+      }
+      if (this.imageLayer) {
+        this.imageLayer.beginLayout();
+      }
     },
 
     executeOperatorList: function CanvasGraphics_executeOperatorList(
                                     operatorList,
                                     executionStartIdx, continueCallback,
                                     stepper) {
       var argsArray = operatorList.argsArray;
       var fnArray = operatorList.fnArray;
@@ -2471,18 +2478,22 @@ var CanvasGraphics = (function CanvasGra
         // If the operatorList isn't executed completely yet OR the execution
         // time was short enough, do another execution round.
       }
     },
 
     endDrawing: function CanvasGraphics_endDrawing() {
       this.ctx.restore();
 
-      if (this.textLayer)
+      if (this.textLayer) {
         this.textLayer.endLayout();
+      }
+      if (this.imageLayer) {
+        this.imageLayer.endLayout();
+      }
     },
 
     // Graphics state
     setLineWidth: function CanvasGraphics_setLineWidth(width) {
       this.current.lineWidth = width;
       this.ctx.lineWidth = width;
     },
     setLineCap: function CanvasGraphics_setLineCap(style) {
@@ -3269,17 +3280,27 @@ var CanvasGraphics = (function CanvasGra
       this.save();
 
       var ctx = this.ctx;
       // scale the image to the unit square
       ctx.scale(1 / w, -1 / h);
 
       ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
                     0, -h, w, h);
-
+      if (this.imageLayer) {
+        var currentTransform = ctx.mozCurrentTransformInverse;
+        var position = this.getCanvasPosition(0, 0);
+        this.imageLayer.appendImage({
+          objId: objId,
+          left: position[0],
+          top: position[1],
+          width: w / currentTransform[0],
+          height: h / currentTransform[3]
+        });
+      }
       this.restore();
     },
 
     paintImageMaskXObject: function CanvasGraphics_paintImageMaskXObject(
                              imgArray, inverseDecode, width, height) {
       var ctx = this.ctx;
       var tmpCanvas = createScratchCanvas(width, height);
       var tmpCtx = tmpCanvas.getContext('2d');
@@ -3368,16 +3389,27 @@ var CanvasGraphics = (function CanvasGra
       } else {
         if (typeof ImageData !== 'undefined' && imgData instanceof ImageData) {
           tmpCtx.putImageData(imgData, 0, 0);
         } else {
           putBinaryImageData(tmpCtx, imgData.data, width, height);
         }
         ctx.drawImage(tmpCanvas, 0, -height);
       }
+
+      if (this.imageLayer) {
+        var position = this.getCanvasPosition(0, -height);
+        this.imageLayer.appendImage({
+          imgData: imgData,
+          left: position[0],
+          top: position[1],
+          width: width / currentTransform[0],
+          height: height / currentTransform[3]
+        });
+      }
       this.restore();
     },
 
     paintInlineImageXObjectGroup:
       function CanvasGraphics_paintInlineImageXObjectGroup(imgData, map) {
       var ctx = this.ctx;
       var w = imgData.width;
       var h = imgData.height;
@@ -3388,16 +3420,26 @@ var CanvasGraphics = (function CanvasGra
 
       for (var i = 0, ii = map.length; i < ii; i++) {
         var entry = map[i];
         ctx.save();
         ctx.transform.apply(ctx, entry.transform);
         ctx.scale(1, -1);
         ctx.drawImage(tmpCanvas, entry.x, entry.y, entry.w, entry.h,
                       0, -1, 1, 1);
+        if (this.imageLayer) {
+          var position = this.getCanvasPosition(entry.x, entry.y);
+          this.imageLayer.appendImage({
+            imgData: imgData,
+            left: position[0],
+            top: position[1],
+            width: w,
+            height: h
+          });
+        }
         ctx.restore();
       }
     },
 
     // Marked content
 
     markPoint: function CanvasGraphics_markPoint(tag) {
       // TODO Marked content.
@@ -3453,16 +3495,23 @@ var CanvasGraphics = (function CanvasGra
       this.ctx.mozFillRule = rule;
     },
     getSinglePixelWidth: function CanvasGraphics_getSinglePixelWidth(scale) {
       var inverse = this.ctx.mozCurrentTransformInverse;
       // max of the current horizontal and vertical scale
       return Math.sqrt(Math.max(
         (inverse[0] * inverse[0] + inverse[1] * inverse[1]),
         (inverse[2] * inverse[2] + inverse[3] * inverse[3])));
+    },
+    getCanvasPosition: function CanvasGraphics_getCanvasPosition(x, y) {
+        var transform = this.ctx.mozCurrentTransform;
+        return [
+          transform[0] * x + transform[2] * y + transform[4],
+          transform[1] * x + transform[3] * y + transform[5]
+        ];
     }
   };
 
   return CanvasGraphics;
 })();
 
 
 
--- a/browser/extensions/pdfjs/content/web/viewer.css
+++ b/browser/extensions/pdfjs/content/web/viewer.css
@@ -1160,16 +1160,17 @@ canvas {
 .textLayer {
   position: absolute;
   left: 0;
   top: 0;
   right: 0;
   bottom: 0;
   color: #000;
   font-family: sans-serif;
+  overflow: hidden;
 }
 
 .textLayer > div {
   color: transparent;
   position: absolute;
   line-height:1.3;
   white-space:pre;
 }
--- a/browser/extensions/pdfjs/content/web/viewer.html
+++ b/browser/extensions/pdfjs/content/web/viewer.html
@@ -122,21 +122,21 @@ limitations under the License.
                   <span data-l10n-id="download_label">Download</span>
                 </button>
                 <!-- <div class="toolbarButtonSpacer"></div> -->
                 <a href="#" id="viewBookmark" class="toolbarButton bookmark" title="Current view (copy or open in new window)" tabindex="15" data-l10n-id="bookmark"><span data-l10n-id="bookmark_label">Current View</span></a>
               </div>
               <div class="outerCenter">
                 <div class="innerCenter" id="toolbarViewerMiddle">
                   <div class="splitToolbarButton">
-                    <button class="toolbarButton zoomOut" title="Zoom Out" tabindex="8" data-l10n-id="zoom_out">
+                    <button class="toolbarButton zoomOut" id="zoom_out" title="Zoom Out" tabindex="8" data-l10n-id="zoom_out">
                       <span data-l10n-id="zoom_out_label">Zoom Out</span>
                     </button>
                     <div class="splitToolbarButtonSeparator"></div>
-                    <button class="toolbarButton zoomIn" title="Zoom In" tabindex="9" data-l10n-id="zoom_in">
+                    <button class="toolbarButton zoomIn" id="zoom_in" title="Zoom In" tabindex="9" data-l10n-id="zoom_in">
                       <span data-l10n-id="zoom_in_label">Zoom In</span>
                      </button>
                   </div>
                   <span id="scaleSelectContainer" class="dropdownToolbarButton">
                      <select id="scaleSelect" title="Zoom" oncontextmenu="return false;" tabindex="10" data-l10n-id="zoom">
                       <option id="pageAutoOption" value="auto" selected="selected" data-l10n-id="page_scale_auto">Automatic Zoom</option>
                       <option id="pageActualOption" value="page-actual" data-l10n-id="page_scale_actual">Actual Size</option>
                       <option id="pageFitOption" value="page-fit" data-l10n-id="page_scale_fit">Fit Page</option>
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -215,27 +215,16 @@ var FirefoxCom = (function FirefoxComClo
 })();
 
 
 // Settings Manager - This is a utility for saving settings
 // First we see if localStorage is available
 // If not, we use FUEL in FF
 // Use asyncStorage for B2G
 var Settings = (function SettingsClosure() {
-  var isLocalStorageEnabled = (function localStorageEnabledTest() {
-    // Feature test as per http://diveintohtml5.info/storage.html
-    // The additional localStorage call is to get around a FF quirk, see
-    // bug #495747 in bugzilla
-    try {
-      return 'localStorage' in window && window['localStorage'] !== null &&
-          localStorage;
-    } catch (e) {
-      return false;
-    }
-  })();
 
   function Settings(fingerprint) {
     this.fingerprint = fingerprint;
     this.initializedPromise = new PDFJS.Promise();
 
     var resolvePromise = (function settingsResolvePromise(db) {
       this.initialize(db || '{}');
       this.initializedPromise.resolve();
@@ -269,17 +258,20 @@ var Settings = (function SettingsClosure
 
     set: function settingsSet(name, val) {
       if (!this.initializedPromise.isResolved)
         return;
 
       var file = this.file;
       file[name] = val;
       var database = JSON.stringify(this.database);
+
+
       FirefoxCom.requestSync('setDatabase', database);
+
     },
 
     get: function settingsGet(name, defaultValue) {
       if (!this.initializedPromise.isResolved)
         return defaultValue;
 
       return this.file[name] || defaultValue;
     }
@@ -3102,16 +3094,19 @@ window.addEventListener('scalechange', f
       return;
   }
 
   var predefinedValueFound = selectScaleOption('' + evt.scale);
   if (!predefinedValueFound) {
     customScaleOption.textContent = Math.round(evt.scale * 10000) / 100 + '%';
     customScaleOption.selected = true;
   }
+  
+  document.getElementById('zoom_out').disabled = (evt.scale === MIN_SCALE);
+  document.getElementById('zoom_in').disabled = (evt.scale === MAX_SCALE);
 
   updateViewarea();
 }, true);
 
 window.addEventListener('pagechange', function pagechange(evt) {
   var page = evt.pageNumber;
   if (PDFView.previousPageNumber !== page) {
     document.getElementById('pageNumber').value = page;
@@ -3252,16 +3247,22 @@ window.addEventListener('keydown', funct
           break;
         }
         /* falls through */
       case 75: // 'k'
       case 80: // 'p'
         PDFView.page--;
         handled = true;
         break;
+      case 27: // esc key
+        if (!PDFView.supportsIntegratedFind && PDFFindBar.opened) {
+          PDFFindBar.close();
+          handled = true;
+        }
+        break;
       case 40: // down arrow
       case 34: // pg down
       case 32: // spacebar
         if (!PDFView.isFullscreen && PDFView.currentScaleValue !== 'page-fit') {
           break;
         }
         /* falls through */
       case 39: // right arrow
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -280,16 +280,19 @@
 #ifdef MOZ_ENABLE_PROFILER_SPS
 @BINPATH@/components/profiler.xpt
 #endif
 @BINPATH@/components/rdf.xpt
 @BINPATH@/components/satchel.xpt
 @BINPATH@/components/saxparser.xpt
 @BINPATH@/browser/components/sessionstore.xpt
 @BINPATH@/components/services-crypto-component.xpt
+#ifdef MOZ_CAPTIVEDETECT
+@BINPATH@/components/captivedetect.xpt
+#endif
 @BINPATH@/browser/components/shellservice.xpt
 @BINPATH@/components/shistory.xpt
 @BINPATH@/components/spellchecker.xpt
 @BINPATH@/components/storage.xpt
 @BINPATH@/components/toolkitprofile.xpt
 #ifdef MOZ_ENABLE_XREMOTE
 @BINPATH@/components/toolkitremote.xpt
 #endif
@@ -340,17 +343,17 @@
 @BINPATH@/browser/components/nsBrowserContentHandler.js
 @BINPATH@/browser/components/nsBrowserGlue.js
 @BINPATH@/browser/components/nsSetDefaultBrowser.manifest
 @BINPATH@/browser/components/nsSetDefaultBrowser.js
 @BINPATH@/browser/components/BrowserDownloads.manifest
 @BINPATH@/browser/components/DownloadsStartup.js
 @BINPATH@/browser/components/DownloadsUI.js
 @BINPATH@/browser/components/BrowserPlaces.manifest
-@BINPATH@/browser/components/BrowserPageThumbs.manifest
+@BINPATH@/components/BrowserPageThumbs.manifest
 @BINPATH@/browser/components/nsPrivateBrowsingServiceObsolete.manifest
 @BINPATH@/browser/components/nsPrivateBrowsingServiceObsolete.js
 @BINPATH@/components/SiteSpecificUserAgent.js
 @BINPATH@/components/SiteSpecificUserAgent.manifest
 @BINPATH@/components/toolkitsearch.manifest
 @BINPATH@/components/nsSearchService.js
 @BINPATH@/components/nsSearchSuggestions.js
 @BINPATH@/components/passwordmgr.manifest
@@ -405,17 +408,17 @@
 @BINPATH@/components/nsLivemarkService.js
 @BINPATH@/components/nsTaggingService.js
 @BINPATH@/components/nsPlacesAutoComplete.manifest
 @BINPATH@/components/nsPlacesAutoComplete.js
 @BINPATH@/components/nsPlacesExpiration.js
 @BINPATH@/browser/components/PlacesProtocolHandler.js
 @BINPATH@/components/PlacesCategoriesStarter.js
 @BINPATH@/components/ColorAnalyzer.js
-@BINPATH@/browser/components/PageThumbsProtocol.js
+@BINPATH@/components/PageThumbsProtocol.js
 @BINPATH@/components/nsDefaultCLH.manifest
 @BINPATH@/components/nsDefaultCLH.js
 @BINPATH@/components/nsContentPrefService.manifest
 @BINPATH@/components/nsContentPrefService.js
 @BINPATH@/components/nsContentDispatchChooser.manifest
 @BINPATH@/components/nsContentDispatchChooser.js
 @BINPATH@/components/nsHandlerService.manifest
 @BINPATH@/components/nsHandlerService.js
@@ -478,16 +481,20 @@
 #endif
 #ifdef MOZ_SERVICES_HEALTHREPORT
 @BINPATH@/components/HealthReportComponents.manifest
 #endif
 #ifdef MOZ_SERVICES_SYNC
 @BINPATH@/components/SyncComponents.manifest
 @BINPATH@/components/Weave.js
 #endif
+#ifdef MOZ_CAPTIVEDETECT
+@BINPATH@/components/CaptivePortalDetectComponents.manifest
+@BINPATH@/components/captivedetect.js
+#endif
 @BINPATH@/components/servicesComponents.manifest
 @BINPATH@/components/cryptoComponents.manifest
 @BINPATH@/components/TelemetryPing.js
 @BINPATH@/components/TelemetryPing.manifest
 @BINPATH@/components/messageWakeupService.js
 @BINPATH@/components/messageWakeupService.manifest
 @BINPATH@/components/SettingsManager.js
 @BINPATH@/components/SettingsManager.manifest
--- a/browser/locales/en-US/chrome/browser/devtools/toolbox.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/toolbox.properties
@@ -1,10 +1,22 @@
 toolboxDockButtons.bottom.tooltip=Dock to bottom of browser window
 toolboxDockButtons.side.tooltip=Dock to side of browser window
 toolboxDockButtons.window.tooltip=Show in separate window
 
-# LOCALIZATION NOTE (toolboxToggleButton): These strings are used for the button
-# that allows users to open/close the developer tools. You can find this button
-# on the developer toolbar.
-toolboxToggleButton.errorsCount=error;errors
-toolboxToggleButton.warningsCount=warning;warnings
-toolboxToggleButton.tooltiptext=%S %S, %S %S.\nClick to toggle the developer tools.
+# LOCALIZATION NOTE (toolboxToggleButton.errors): Semi-colon list of plural
+# forms.
+# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
+# #1 number of errors in the current web page
+toolboxToggleButton.errors=#1 error;#1 errors
+
+# LOCALIZATION NOTE (toolboxToggleButton.warnings): Semi-colon list of plural
+# forms.
+# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
+# #1 number of warnings in the current web page
+toolboxToggleButton.warnings=#1 warning;#1 warnings
+
+# LOCALIZATION NOTE (toolboxToggleButton.tooltip): This string is shown
+# as tooltip in the developer toolbar to open/close the developer tools.
+# It's using toolboxToggleButton.errors as first and
+# toolboxToggleButton.warnings as second argument to show the number of errors
+# and warnings.
+toolboxToggleButton.tooltip=%1$S, %2$S\nClick to toggle the developer tools.
--- a/browser/makefiles.sh
+++ b/browser/makefiles.sh
@@ -31,17 +31,16 @@ browser/components/privatebrowsing/src/M
 browser/components/search/Makefile
 browser/components/sessionstore/Makefile
 browser/components/sessionstore/src/Makefile
 browser/components/sidebar/Makefile
 browser/components/shell/Makefile
 browser/components/shell/public/Makefile
 browser/components/shell/src/Makefile
 browser/components/tabview/Makefile
-browser/components/thumbnails/Makefile
 browser/devtools/Makefile
 browser/devtools/debugger/Makefile
 browser/devtools/inspector/Makefile
 browser/devtools/scratchpad/Makefile
 browser/devtools/shared/Makefile
 browser/devtools/sourceeditor/Makefile
 browser/devtools/styleeditor/Makefile
 browser/devtools/styleinspector/Makefile
@@ -113,17 +112,16 @@ if [ "$ENABLE_TESTS" ]; then
     browser/components/migration/tests/Makefile
     browser/components/places/tests/Makefile
     browser/components/places/tests/chrome/Makefile
     browser/components/places/tests/browser/Makefile
     browser/components/privatebrowsing/test/Makefile
     browser/components/privatebrowsing/test/browser/Makefile
     browser/components/tabview/test/Makefile
     browser/components/test/Makefile
-    browser/components/thumbnails/test/Makefile
     browser/devtools/debugger/test/Makefile
     browser/devtools/inspector/test/Makefile
     browser/devtools/scratchpad/test/Makefile
     browser/devtools/shared/test/Makefile
     browser/devtools/sourceeditor/test/Makefile
     browser/devtools/styleeditor/test/Makefile
     browser/devtools/styleinspector/test/Makefile
     browser/devtools/tilt/test/Makefile
--- a/browser/metro/base/content/TopSites.js
+++ b/browser/metro/base/content/TopSites.js
@@ -33,16 +33,20 @@ let TopSites = {
 
 function TopSitesView(aGrid, maxSites) {
   this._set = aGrid;
   this._set.controller = this;
   this._topSitesMax = maxSites;
 
   // handle selectionchange DOM events from the grid/tile group
   this._set.addEventListener("context-action", this, false);
+
+  let history = Cc["@mozilla.org/browser/nav-history-service;1"].
+                getService(Ci.nsINavHistoryService);
+  history.addObserver(this, false);
 }
 
 TopSitesView.prototype = {
   _set:null,
   _topSitesMax: null,
 
   handleItemClick: function tabview_handleItemClick(aItem) {
     let url = aItem.getAttribute("value");
@@ -148,16 +152,52 @@ TopSitesView.prototype = {
   },
 
   isFirstRun: function isFirstRun() {
     return prefs.getBoolPref("browser.firstrun.show.localepicker");
   },
 
   destruct: function destruct() {
     // remove the observers here
+  },
+
+  // nsINavHistoryObserver
+
+  onBeginUpdateBatch: function() {
+  },
+
+  onEndUpdateBatch: function() {
+  },
+
+  onVisit: function(aURI, aVisitID, aTime, aSessionID,
+                    aReferringID, aTransitionType) {
+  },
+
+  onTitleChanged: function(aURI, aPageTitle) {
+  },
+
+  onDeleteURI: function(aURI) {
+  },
+
+  onClearHistory: function() {
+    this._set.clearAll();
+  },
+
+  onPageChanged: function(aURI, aWhat, aValue) {
+  },
+
+  onPageExpired: function(aURI, aVisitTime, aWholeEntry) {
+  },
+
+  QueryInterface: function(iid) {
+    if (iid.equals(Components.interfaces.nsINavHistoryObserver) ||
+        iid.equals(Components.interfaces.nsISupports)) {
+      return this;
+    }
+    throw Cr.NS_ERROR_NO_INTERFACE;
   }
 
 };
 
 let TopSitesStartView = {
   _view: null,
   get _grid() { return document.getElementById("start-topsites-grid"); },
 
--- a/browser/metro/base/content/bindings/grid.xml
+++ b/browser/metro/base/content/bindings/grid.xml
@@ -183,16 +183,28 @@
             let addition = this._createItemElement(aLabel, aValue);
             this.appendChild(addition);
             this.arrangeItems();
             return addition;
           ]]>
         </body>
       </method>
 
+      <method name="clearAll">
+        <body>
+          <![CDATA[
+            while (this.firstChild) {
+              this.removeChild(this.firstChild);
+            }
+            this._grid.style.width = "0px";
+            this._contextActions = null;
+          ]]>
+        </body>
+      </method>
+
       <method name="insertItemAt">
         <parameter name="anIndex"/>
         <parameter name="aLabel"/>
         <parameter name="aValue"/>
         <body>
           <![CDATA[
             let existing = this.getItemAtIndex(anIndex);
             let addition = this._createItemElement(aLabel, aValue);
--- a/browser/metro/base/content/bindings/toggleswitch.xml
+++ b/browser/metro/base/content/bindings/toggleswitch.xml
@@ -12,18 +12,18 @@
 <bindings
     xmlns="http://www.mozilla.org/xbl"
     xmlns:xbl="http://www.mozilla.org/xbl"
     xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <binding id="checkbox-toggleswitch" display="xul:box" extends="chrome://global/content/bindings/checkbox.xml#checkbox-baseline">
     <content>
       <xul:hbox>
-        <xul:description anonid="onlabel" class="onlabel" value="&checkbox.yes.label;" xbl:inherits="value=onlabel"/>
-        <xul:description anonid="offlabel" class="offlabel" value="&checkbox.no.label;" xbl:inherits="value=offlabel"/>
+        <xul:description anonid="onlabel" class="onlabel" value="&checkbox.on.label;" xbl:inherits="value=onlabel"/>
+        <xul:description anonid="offlabel" class="offlabel" value="&checkbox.off.label;" xbl:inherits="value=offlabel"/>
         <xul:radiogroup anonid="group" xbl:inherits="disabled">
           <xul:radio anonid="on" class="checkbox-radio-on"/>
           <xul:radio anonid="off" class="checkbox-radio-off"/>
         </xul:radiogroup>
       </xul:hbox>
     </content>
     <implementation>
       <constructor><![CDATA[
--- a/browser/metro/base/content/contenthandlers/Content.js
+++ b/browser/metro/base/content/contenthandlers/Content.js
@@ -432,31 +432,26 @@ let Content = {
 
     this.formAssistant.focusSync = true;
 
     // The form manager handles focus related changes on form elements.
     // If it returns false, it didn't find anything to act on. If the
     // target element doesn't match the current focus element, clear
     // focus. This allows users to remove focus from form elements by
     // taping on white space content.
-    if (!this.formAssistant.open(element, aEvent.clientX, aEvent.clientY)) {
+    if (!this.formAssistant.open(element, aEvent)) {
       if (gFocusManager.focusedElement &&
           gFocusManager.focusedElement != element) {
         gFocusManager.focusedElement.blur();
       }
       // This may not have any effect if element is unfocusable.
       gFocusManager.setFocus(element, Ci.nsIFocusManager.FLAG_NOSCROLL);
       sendAsyncMessage("FindAssist:Hide", { });
     }
 
-    // Fire mouse events on everything but selects, see bug 685197
-    if (element instanceof HTMLSelectElement) {
-      aEvent.preventDefault()
-      aEvent.stopPropagation()
-    }
     this._cancelTapHighlight();
     this.formAssistant.focusSync = false;
   },
 
   /******************************************************
    * Event handlers
    */
 
--- a/browser/metro/base/content/contenthandlers/FormHelper.js
+++ b/browser/metro/base/content/contenthandlers/FormHelper.js
@@ -99,56 +99,67 @@ FormAssistant.prototype = {
         this.currentIndex = currentIndex + 1;
       else if (this._currentIndex != currentIndex)
         this.currentIndex = currentIndex;
     }
     return element;
   },
 
   _open: false,
-  open: function formHelperOpen(aElement, aX, aY) {
+  open: function formHelperOpen(aElement, aEvent) {
     // If the click is on an option element we want to check if the parent
     // is a valid target.
     if (aElement instanceof HTMLOptionElement &&
         aElement.parentNode instanceof HTMLSelectElement &&
         !aElement.disabled) {
       aElement = aElement.parentNode;
     }
 
+    if (aElement instanceof HTMLSelectElement && aEvent) {
+      // Don't show the formhelper popup for multi-select boxes, except for touch.
+      if ((aElement.multiple || aElement.size > 1) &&
+          aEvent.mozInputSource != Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH) {
+        return false;
+      }
+      // Don't fire mouse events on selects; see bug 685197.
+      aEvent.preventDefault()
+      aEvent.stopPropagation()
+    }
+
     // The form assistant will close if a click happen:
     // * outside of the scope of the form helper
     // * hover a button of type=[image|submit]
     // * hover a disabled element
     if (!this._isValidElement(aElement)) {
       let passiveButtons = { button: true, checkbox: true, file: true, radio: true, reset: true };
       if ((aElement instanceof HTMLInputElement || aElement instanceof HTMLButtonElement) &&
           passiveButtons[aElement.type] && !aElement.disabled)
         return false;
 
       // Check for plugins element
       if (aElement instanceof Ci.nsIDOMHTMLEmbedElement) {
-        aX = aX || 0;
-        aY = aY || 0;
+        let x = (aEvent && aEvent.clientX) || 0;
+        let y = (aEvent && aEvent.clientY) || 0;
         this._executeDelayed(function(self) {
           let utils = Util.getWindowUtils(aElement.ownerDocument.defaultView);
           if (utils.IMEStatus == utils.IME_STATUS_PLUGIN) {
             let jsvar = {
               current: {
                 id: aElement.id,
                 name: aElement.name,
                 title: "plugin",
                 value: null,
                 maxLength: 0,
                 type: (aElement.getAttribute("type") || "").toLowerCase(),
                 choices: null,
                 isAutocomplete: false,
                 validationMessage: null,
                 list: null,
                 rect: getBoundingContentRect(aElement),
-                caretRect: new Rect(aX, aY, 1, 10),
+                caretRect: new Rect(x, y, 1, 10),
                 editable: true
               },
               hasPrevious: false,
               hasNext: false
             };
             sendAsyncMessage("FormAssist:Show", jsvar);
           }
         });
--- a/browser/metro/base/content/cursor.css
+++ b/browser/metro/base/content/cursor.css
@@ -7,8 +7,13 @@
 
 xul|*:-moz-system-metric(touch-enabled) {
   cursor: none !important;
 }
 
 html|*:-moz-system-metric(touch-enabled) {
   cursor: none !important;
 }
+
+/* For touch input, *all* select boxes use the SelectHelper popup. */
+select option, select optgroup {
+  pointer-events: none;
+}
--- a/browser/metro/base/content/history.js
+++ b/browser/metro/base/content/history.js
@@ -5,17 +5,19 @@
 'use strict';
 
 
 // TODO <jwilde>: Observe changes in history with nsINavHistoryObserver
 function HistoryView(aSet) {
   this._set = aSet;
   this._set.controller = this;
 
-  //add observers here
+  let history = Cc["@mozilla.org/browser/nav-history-service;1"].
+                getService(Ci.nsINavHistoryService);
+  history.addObserver(this, false);
 }
 
 HistoryView.prototype = {
   _set:null,
 
   handleItemClick: function tabview_handleItemClick(aItem) {
     let url = aItem.getAttribute("value");
     BrowserUI.goToURI(url);
@@ -44,16 +46,52 @@ HistoryView.prototype = {
       item.setAttribute("iconURI", node.icon);
     }
 
     rootNode.containerOpen = false;
   },
 
   destruct: function destruct() {
   },
+
+  // nsINavHistoryObserver
+
+  onBeginUpdateBatch: function() {
+  },
+
+  onEndUpdateBatch: function() {
+  },
+
+  onVisit: function(aURI, aVisitID, aTime, aSessionID,
+                    aReferringID, aTransitionType) {
+  },
+
+  onTitleChanged: function(aURI, aPageTitle) {
+  },
+
+  onDeleteURI: function(aURI) {
+  },
+
+  onClearHistory: function() {
+    this._set.clearAll();
+  },
+
+  onPageChanged: function(aURI, aWhat, aValue) {
+  },
+
+  onPageExpired: function(aURI, aVisitTime, aWholeEntry) {
+  },
+
+  QueryInterface: function(iid) {
+    if (iid.equals(Components.interfaces.nsINavHistoryObserver) ||
+        iid.equals(Components.interfaces.nsISupports)) {
+      return this;
+    }
+    throw Cr.NS_ERROR_NO_INTERFACE;
+  }
 };
 
 let HistoryStartView = {
   _view: null,
   get _grid() { return document.getElementById("start-history-grid"); },
 
   show: function show() {
     this._grid.arrangeItems();
--- a/browser/metro/components/ContentPermissionPrompt.js
+++ b/browser/metro/components/ContentPermissionPrompt.js
@@ -55,17 +55,17 @@ ContentPermissionPrompt.prototype = {
      return chromeWin;
   },
 
   getNotificationBoxForRequest: function getNotificationBoxForRequest(request) {
     let notificationBox = null;
     if (request.window) {
       let requestingWindow = request.window.top;
       let chromeWin = this.getChromeWindow(requestingWindow).wrappedJSObject;
-      let windowID = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
+      let windowID = request.window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
       let browser = chromeWin.Browser.getBrowserForWindowId(windowID);
       return chromeWin.getNotificationBox(browser);
     }
 
     let chromeWin = request.element.ownerDocument.defaultView;
     return chromeWin.Browser.getNotificationBox(request.element);
   },
 
--- a/browser/metro/locales/en-US/chrome/checkbox.dtd
+++ b/browser/metro/locales/en-US/chrome/checkbox.dtd
@@ -1,6 +1,6 @@
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
-<!ENTITY checkbox.yes.label    "Yes">
-<!ENTITY checkbox.no.label     "No">
+<!ENTITY checkbox.on.label    "On">
+<!ENTITY checkbox.off.label     "Off">
--- a/browser/metro/theme/content.css
+++ b/browser/metro/theme/content.css
@@ -118,18 +118,20 @@ select[size][multiple],
 * > input:not([type="image"]) {
 
   border-style: solid;
   border-color: #7d7d7d;
   color: #414141;
   /*background: white -moz-linear-gradient(top, rgba(115,115,115,0.5) 0, rgba(215,215,215,0.5) 3px, rgba(255,255,255,0.2) 16px);*/
 }
 
-/* Selects are handled by the form helper, see bug 685197 */
-select option, select optgroup {
+/* For both mouse and touch, single-selects are handled by the SelectHelper popup.
+ * Suppress mouse events on the popup itself. See also ../base/content/cursor.css */
+select[size=1] :-moz-any(option, optgroup),
+select:not([size]):not([multiple]) :-moz-any(option, optgroup) {
   pointer-events: none;
 }
 
 input:-moz-placeholder {
   color: GrayText;
 }
 
 select:not([size]):not([multiple]),
--- a/browser/modules/Makefile.in
+++ b/browser/modules/Makefile.in
@@ -13,17 +13,16 @@ include $(topsrcdir)/config/config.mk
 
 TEST_DIRS += test
 
 EXTRA_JS_MODULES = \
 	AboutHomeUtils.jsm \
 	BrowserNewTabPreloader.jsm \
 	openLocationLastURL.jsm \
 	NetworkPrioritizer.jsm \
-	NewTabUtils.jsm \
 	offlineAppCache.jsm \
 	SignInToWebsite.jsm \
 	webappsUI.jsm \
 	webrtcUI.jsm \
 	KeywordURLResetPrompter.jsm \
 	Social.jsm \
 	SharedFrame.jsm \
 	$(NULL)
--- a/browser/modules/test/Makefile.in
+++ b/browser/modules/test/Makefile.in
@@ -9,18 +9,16 @@ VPATH		= @srcdir@
 relativesrcdir  = @relativesrcdir@
 
 DIRS = \
 	chrome \
 	$(NULL)
 
 include $(DEPTH)/config/autoconf.mk
 
-XPCSHELL_TESTS = unit
-
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_FILES = \
                  browser_NetworkPrioritizer.js \
                  # bug 793906 - temporarily disabling desktop UI while working on b2g
                  # browser_SignInToWebsite.js \
                  $(NULL)
 
deleted file mode 100644
--- a/browser/modules/test/unit/xpcshell.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-[DEFAULT]
-head =
-tail =
-firefox-appdir = browser
-
-[test_newtab-migrate-v1.js]
--- a/browser/modules/webrtcUI.jsm
+++ b/browser/modules/webrtcUI.jsm
@@ -17,21 +17,23 @@ Cu.import("resource://gre/modules/XPCOMU
 XPCOMUtils.defineLazyServiceGetter(this, "MediaManagerService",
                                    "@mozilla.org/mediaManagerService;1",
                                    "nsIMediaManagerService");
 
 this.webrtcUI = {
   init: function () {
     Services.obs.addObserver(handleRequest, "getUserMedia:request", false);
     Services.obs.addObserver(updateGlobalIndicator, "recording-device-events", false);
+    Services.obs.addObserver(removeBrowserSpecificIndicator, "recording-window-ended", false);
   },
 
   uninit: function () {
     Services.obs.removeObserver(handleRequest, "getUserMedia:request");
     Services.obs.removeObserver(updateGlobalIndicator, "recording-device-events");
+    Services.obs.removeObserver(removeBrowserSpecificIndicator, "recording-window-ended");
   },
 
   showGlobalIndicator: false,
 
   get activeStreams() {
     let contentWindowSupportsArray = MediaManagerService.activeMediaCaptureWindows;
     let count = contentWindowSupportsArray.Count();
     let activeStreams = [];
@@ -49,35 +51,44 @@ this.webrtcUI = {
           tab: tab
         });
       }
     }
     return activeStreams;
   }
 }
 
-function handleRequest(aSubject, aTopic, aData) {
-  let {windowID: windowID, callID: callID} = JSON.parse(aData);
-
+function getBrowserForWindowId(aWindowID) {
   let someWindow = Services.wm.getMostRecentWindow(null);
   let contentWindow = someWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                                 .getInterface(Ci.nsIDOMWindowUtils)
-                                .getOuterWindowWithId(windowID);
-  let browser = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                             .getInterface(Ci.nsIWebNavigation)
-                             .QueryInterface(Ci.nsIDocShell)
-                             .chromeEventHandler;
+                                .getOuterWindowWithId(aWindowID);
+  return contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                      .getInterface(Ci.nsIWebNavigation)
+                      .QueryInterface(Ci.nsIDocShell)
+                      .chromeEventHandler;
+}
 
+function handleRequest(aSubject, aTopic, aData) {
+  let {windowID: windowID, callID: callID} = JSON.parse(aData);
+
+  let browser = getBrowserForWindowId(windowID);
   let params = aSubject.QueryInterface(Ci.nsIMediaStreamOptions);
 
   browser.ownerDocument.defaultView.navigator.mozGetUserMediaDevices(
     function (devices) {
       prompt(browser, callID, params.audio, params.video, devices);
     },
     function (error) {
+      // bug 827146 -- In the future, the UI should catch NO_DEVICES_FOUND
+      // and allow the user to plug in a device, instead of immediately failing.
+      let msg = Cc["@mozilla.org/supports-string;1"].
+                createInstance(Ci.nsISupportsString);
+      msg.data = error;
+      Services.obs.notifyObservers(msg, "getUserMedia:response:deny", callID);
       Cu.reportError(error);
     }
   );
 }
 
 function prompt(aBrowser, aCallID, aAudioRequested, aVideoRequested, aDevices) {
   let audioDevices = [];
   let videoDevices = [];
@@ -200,8 +211,18 @@ function prompt(aBrowser, aCallID, aAudi
 function updateGlobalIndicator() {
   webrtcUI.showGlobalIndicator =
     MediaManagerService.activeMediaCaptureWindows.Count() > 0;
 
   let e = Services.wm.getEnumerator("navigator:browser");
   while (e.hasMoreElements())
     e.getNext().WebrtcIndicator.updateButton();
 }
+
+function removeBrowserSpecificIndicator(aSubject, aTopic, aData) {
+  let browser = getBrowserForWindowId(aData);
+  let PopupNotifications = browser.ownerDocument.defaultView.PopupNotifications;
+  let notification = PopupNotifications &&
+                     PopupNotifications.getNotification("webRTC-sharingDevices",
+                                                        browser);
+  if (notification)
+    PopupNotifications.remove(notification);
+}
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -1208,16 +1208,20 @@ toolbar[iconsize="small"] #webrtc-status
 .popup-notification-icon[popupid="password-change"] {
   list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
 }
 
 .popup-notification-icon[popupid="webapps-install"] {
   list-style-image: url(chrome://browser/skin/webapps-64.png);
 }
 
+.popup-notification-icon[popupid="mixed-content-blocked"] {
+  list-style-image: url(chrome://browser/skin/mixed-content-blocked-64.png);
+}
+
 .popup-notification-icon[popupid="webRTC-sharingDevices"],
 .popup-notification-icon[popupid="webRTC-shareDevices"] {
   list-style-image: url(chrome://browser/skin/webRTC-shareDevice-64.png);
 }
 
 /* Notification icon box */
 #notification-popup-box {
   position: relative;
--- a/browser/themes/gnomestripe/jar.mn
+++ b/browser/themes/gnomestripe/jar.mn
@@ -26,16 +26,17 @@ browser.jar:
   skin/classic/browser/Go-arrow.png
   skin/classic/browser/identity.png
   skin/classic/browser/identity-icons-generic.png
   skin/classic/browser/identity-icons-https.png
   skin/classic/browser/identity-icons-https-ev.png
   skin/classic/browser/identity-icons-https-mixed-active.png
   skin/classic/browser/Info.png
   skin/classic/browser/mixed-content-blocked-16.png
+  skin/classic/browser/mixed-content-blocked-64.png
   skin/classic/browser/monitor.png
   skin/classic/browser/monitor_16-10.png
 * skin/classic/browser/pageInfo.css
   skin/classic/browser/pageInfo.png
   skin/classic/browser/page-livemarks.png
   skin/classic/browser/Privacy-16.png
   skin/classic/browser/Privacy-48.png
   skin/classic/browser/privatebrowsing-mask.png
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..cac4415140767c17f9132e79e68805a959f14591
GIT binary patch
literal 2063
zc$@(b2=MobP)<h;3K|Lk000e1NJLTq002M$002M;1ONa40ARUQ000NpNkl<ZcwX(9
zdr(x@9ml`-y-yx02uLu?LvaMu2tgEu#P~?s`bg6@Mw=$piM1_JG?{7DwSY-&r=3K!
zP3<Fnm>4smlQJe^)d>@PtV(Rv6cB+31E_$}gvY|(-FxrpKfCwNF39d)aPmj{`)ltX
z_ny!FobS2k%x@`zueNCXuLH2SN0lN-@hG6a&MyP&IjL0PBwX;TpXmk&UL2M(Pa9Tn
z5iDp>kW-`|c%0$~(qSBf2VvGdLs)_l%Z81{?+OVV7*NoPK!ykIo}stN0W_=kk2Ao0
zcAIe}&#?Cljsgj8W$38%8a^IxfPAjRxL8o%JD>twxG{9vT~bm#UH}iWubEZ{4jvrB
zStV^QY0(FurPzq=mX{0$c7(wR6c7LuXiy_U47r`JlUGUy^aDI$IAD5!8#d<(WOxA4
z+$r<}qScuIBa7kLAn;(YYv@O%@9P1Gr1x5%6Tkq&(vH5#^_g`uTj@^p1F(?9#s@EF
zbZ3xAZdgiWh!}WR{&DG@umE-~Gyd6>zy&Nd32s<gvM$WKME?i%xVg(qUq&GgGfC!!
zIiKeCrSTLy?7qRC!Hs2=Ap-0Ys6Ey#2Fm~4C5VWs&p(}h78lU6iy#-@;Pc!`NCQ-i
zWIWuIe<uHKra-ACR1f_Jl;Sd1Pyl<HaM(PT_Y<kW4X(5BSmsHbws&C?HW{DiZ7di#
z;S9*%?pWkEEUkXroy3Fo^WcWFPW<-ntD^$g6NJVHD;qG2E+yrol@&~t{RXBn+l=dY
zlP{P9=+^)=h<N4k55IYBiNLV|7W;=>Gk3R+0#G^iTAL+c{^Z`p@6G-z&e<cWSIsX7
ztapaJ00R^-0s@7cYip~X!6g42IbqBAR{bd3@v7UD?5~Zx{=Hw%F0(uAOAHOsKQyyk
zNS`A+LGAQczyAwklL+D$$hlpk?}md+pAt=ZhZhljd0n~i-cAu^)*S|#0pM?pfZ(3h
z6ZxABUGKcu{jdSPC(_R3FM}LNm@gGIxv>|YFB9I{Npl}Y*-bQquuEhQKU*^8oTTEi
zeUL{t0QQc@MtdW}IOxh9G5k?WHmALNC<e4raEw_f=ds=k<}MHnpxf=sCqCzQ5YBGO
z<}sG)VKo}QCnx}SLsqGj1cC%}pBf__1^_6DK6?t-n?VnyLOW3nkjVgdi(qV}#L+4)
z-x<^Z->QIk0X%U8hIV<32IP3!Ye0sfEvSL07DY86#{ibk#%e&0)eM+hf*Qza`a~v-
zSDp#hw5y+DEC@ek%~67yf%Jx;2BLepUd=&NYI-;A91DOUiKf-BKz~~BRRF@>mM2hN
z0Aa>YF2&qc%(U(dSkql<0@yo{f*Jt0Tbco+0_<%C`iq&SC4lP&f*SzWp{)bSM!?>5
zJw$XHkW-*0fV%;NV8GC-8NgJ)&^{IeijDI9f}u4e1CjL|ssXo+z|^EbzX8ccs|GAr
zLjp+t_Z3yF98WOeO7mC%rU+^XW3GfW1zGJ}zs~>>Fy)~-$k16YN63+s7nKqV8$&Vx
zH`gOu885=bSuy_<Zp(4>Jq(Oq5t&4dApbcALNWjd9omLOWxuQ#+w{he&!g1{3O7S;
zP#By03K=h-GKav_*f)>Sl>sH2(l(-&kb6YYmlRcyoB>2$)Efelp&5v}60!lCL)(Bn
z4-z5oqdG}psjv-fW30&r)j)zHWCL@X_+H}604wAswpew2jQCkFs^{UsMWGwOkfB42
z^rb*pvGvp}M_V!-wgF*<b`&w*L|@1T0CS^n))|nMz|uFF9#7ck0%{ebCcu0xtTx>w
zN7qxtOGr}5!g$A~U;bs&Kq?O^WCO)H5m~-9AYnpnSe?@B6GZmO<zRWgc=p6Mwv<gh
z<szZ3hvF>r5sp$fB9eYQybcNXs|Hspqjfo4&JC|0M&bFj$5)eRt#L63CxwyfN%KL$
ztliIaZl8|9Fbu#Gdsb2}7#IxJx3~SFxOQIIOFw_$tV@<g%Y%`6!}527Iy@j_axDhK
zY}Mu;Y+fVtK0XRO==H9`Ezj*OUw^sfYe$yfP3ORjlz|-KZ^jucC>2qGN6tAIcDFpm
zG5e?pMN2d|m{KgKw*Gd@zfyN^Em{31bF(Y3H5@_hH=j4p(547bAY$gptm?44WSdbw
z_sEXg6+A-+HmdFn?!q6-C!^p}LG}Fh4AtcerZRpa8_?Vl$(*B4?SVrF08l>bd{NcY
zw3!Kbs0ZS8@fEyP9*YH=D*!N9BkUBW2X+)C$U{pi7VXDH9eu(V0Ra1wIyM|yH(>KV
z+8?4-+=GK4SR-r~rUed8;D)Jv%^};H_zchu0PM5MPrkdh;ZcrZfMF0)4-_^o5D$>y
zR;JfH^A1;mUO+E^4}n77<#ivd661#tL;z4DH0`;bCn~cK;S3Z&CqR+k)&6+*s*08M
zkFY!gDoCGPlG1CwQz`rdH^%W#tD;-{@7I=Y+#6LVj&eekAtIu2{k~^Qgx_hykKKUg
zArg;$vi$h+!9)(su)#er-g@-Jf@3&Q^aZdV;|ricBw|_hBaQ;67eX66uja9jspCa$
z0C0Z*G>9}Tswq6Z$eF|fkYKtozh-d_YS2_ffcp!eL8PGI+`==tGPB_P!ZWBTYJyt#
t8$g4Yid-<bP;?ytbOU^~_5VMw{|kFWBP&}xIg<bY002ovPDHLkV1ngIxkdm0
--- a/browser/themes/winstripe/jar.mn
+++ b/browser/themes/winstripe/jar.mn
@@ -34,16 +34,17 @@ browser.jar:
         skin/classic/browser/identity-icons-https-ev.png
         skin/classic/browser/identity-icons-https-mixed-active.png
         skin/classic/browser/keyhole-forward-mask.svg
         skin/classic/browser/KUI-background.png
         skin/classic/browser/livemark-folder.png
         skin/classic/browser/menu-back.png
         skin/classic/browser/menu-forward.png
         skin/classic/browser/mixed-content-blocked-16.png
+        skin/classic/browser/mixed-content-blocked-64.png
         skin/classic/browser/monitor.png
         skin/classic/browser/monitor_16-10.png
         skin/classic/browser/pageInfo.css
         skin/classic/browser/pageInfo.png
         skin/classic/browser/page-livemarks.png                      (feeds/feedIcon16.png)
         skin/classic/browser/Privacy-16.png
         skin/classic/browser/Privacy-48.png
         skin/classic/browser/privatebrowsing-light.png
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..cac4415140767c17f9132e79e68805a959f14591
GIT binary patch
literal 2063
zc$@(b2=MobP)<h;3K|Lk000e1NJLTq002M$002M;1ONa40ARUQ000NpNkl<ZcwX(9
zdr(x@9ml`-y-yx02uLu?LvaMu2tgEu#P~?s`bg6@Mw=$piM1_JG?{7DwSY-&r=3K!
zP3<Fnm>4smlQJe^)d>@PtV(Rv6cB+31E_$}gvY|(-FxrpKfCwNF39d)aPmj{`)ltX
z_ny!FobS2k%x@`zueNCXuLH2SN0lN-@hG6a&MyP&IjL0PBwX;TpXmk&UL2M(Pa9Tn
z5iDp>kW-`|c%0$~(qSBf2VvGdLs)_l%Z81{?+OVV7*NoPK!ykIo}stN0W_=kk2Ao0
zcAIe}&#?Cljsgj8W$38%8a^IxfPAjRxL8o%JD>twxG{9vT~bm#UH}iWubEZ{4jvrB
zStV^QY0(FurPzq=mX{0$c7(wR6c7LuXiy_U47r`JlUGUy^aDI$IAD5!8#d<(WOxA4
z+$r<}qScuIBa7kLAn;(YYv@O%@9P1Gr1x5%6Tkq&(vH5#^_g`uTj@^p1F(?9#s@EF
zbZ3xAZdgiWh!}WR{&DG@umE-~Gyd6>zy&Nd32s<gvM$WKME?i%xVg(qUq&GgGfC!!
zIiKeCrSTLy?7qRC!Hs2=Ap-0Ys6Ey#2Fm~4C5VWs&p(}h78lU6iy#-@;Pc!`NCQ-i
zWIWuIe<uHKra-ACR1f_Jl;Sd1Pyl<HaM(PT_Y<kW4X(5BSmsHbws&C?HW{DiZ7di#
z;S9*%?pWkEEUkXroy3Fo^WcWFPW<-ntD^$g6NJVHD;qG2E+yrol@&~t{RXBn+l=dY
zlP{P9=+^)=h<N4k55IYBiNLV|7W;=>Gk3R+0#G^iTAL+c{^Z`p@6G-z&e<cWSIsX7
ztapaJ00R^-0s@7cYip~X!6g42IbqBAR{bd3@v7UD?5~Zx{=Hw%F0(uAOAHOsKQyyk
zNS`A+LGAQczyAwklL+D$$hlpk?}md+pAt=ZhZhljd0n~i-cAu^)*S|#0pM?pfZ(3h
z6ZxABUGKcu{jdSPC(_R3FM}LNm@gGIxv>|YFB9I{Npl}Y*-bQquuEhQKU*^8oTTEi
zeUL{t0QQc@MtdW}IOxh9G5k?WHmALNC<e4raEw_f=ds=k<}MHnpxf=sCqCzQ5YBGO
z<}sG)VKo}QCnx}SLsqGj1cC%}pBf__1^_6DK6?t-n?VnyLOW3nkjVgdi(qV}#L+4)
z-x<^Z->QIk0X%U8hIV<32IP3!Ye0sfEvSL07DY86#{ibk#%e&0)eM+hf*Qza`a~v-
zSDp#hw5y+DEC@ek%~67yf%Jx;2BLepUd=&NYI-;A91DOUiKf-BKz~~BRRF@>mM2hN
z0Aa>YF2&qc%(U(dSkql<0@yo{f*Jt0Tbco+0_<%C`iq&SC4lP&f*SzWp{)bSM!?>5
zJw$XHkW-*0fV%;NV8GC-8NgJ)&^{IeijDI9f}u4e1CjL|ssXo+z|^EbzX8ccs|GAr
zLjp+t_Z3yF98WOeO7mC%rU+^XW3GfW1zGJ}zs~>>Fy)~-$k16YN63+s7nKqV8$&Vx
zH`gOu885=bSuy_<Zp(4>Jq(Oq5t&4dApbcALNWjd9omLOWxuQ#+w{he&!g1{3O7S;
zP#By03K=h-GKav_*f)>Sl>sH2(l(-&kb6YYmlRcyoB>2$)Efelp&5v}60!lCL)(Bn
z4-z5oqdG}psjv-fW30&r)j)zHWCL@X_+H}604wAswpew2jQCkFs^{UsMWGwOkfB42
z^rb*pvGvp}M_V!-wgF*<b`&w*L|@1T0CS^n))|nMz|uFF9#7ck0%{ebCcu0xtTx>w
zN7qxtOGr}5!g$A~U;bs&Kq?O^WCO)H5m~-9AYnpnSe?@B6GZmO<zRWgc=p6Mwv<gh
z<szZ3hvF>r5sp$fB9eYQybcNXs|Hspqjfo4&JC|0M&bFj$5)eRt#L63CxwyfN%KL$
ztliIaZl8|9Fbu#Gdsb2}7#IxJx3~SFxOQIIOFw_$tV@<g%Y%`6!}527Iy@j_axDhK
zY}Mu;Y+fVtK0XRO==H9`Ezj*OUw^sfYe$yfP3ORjlz|-KZ^jucC>2qGN6tAIcDFpm
zG5e?pMN2d|m{KgKw*Gd@zfyN^Em{31bF(Y3H5@_hH=j4p(547bAY$gptm?44WSdbw
z_sEXg6+A-+HmdFn?!q6-C!^p}LG}Fh4AtcerZRpa8_?Vl$(*B4?SVrF08l>bd{NcY
zw3!Kbs0ZS8@fEyP9*YH=D*!N9BkUBW2X+)C$U{pi7VXDH9eu(V0Ra1wIyM|yH(>KV
z+8?4-+=GK4SR-r~rUed8;D)Jv%^};H_zchu0PM5MPrkdh;ZcrZfMF0)4-_^o5D$>y
zR;JfH^A1;mUO+E^4}n77<#ivd661#tL;z4DH0`;bCn~cK;S3Z&CqR+k)&6+*s*08M
zkFY!gDoCGPlG1CwQz`rdH^%W#tD;-{@7I=Y+#6LVj&eekAtIu2{k~^Qgx_hykKKUg
zArg;$vi$h+!9)(su)#er-g@-Jf@3&Q^aZdV;|ricBw|_hBaQ;67eX66uja9jspCa$
z0C0Z*G>9}Tswq6Z$eF|fkYKtozh-d_YS2_ffcp!eL8PGI+`==tGPB_P!ZWBTYJyt#
t8$g4Yid-<bP;?ytbOU^~_5VMw{|kFWBP&}xIg<bY002ovPDHLkV1ngIxkdm0
--- a/build/Makefile.in
+++ b/build/Makefile.in
@@ -4,16 +4,18 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
+USE_RCS_MK := 1
+include $(topsrcdir)/config/makefiles/makeutils.mk
 
 MODULE = build
 
 ifeq (,$(filter WINNT OS2,$(OS_ARCH)))
 DIRS		= unix
 endif
 
 ifeq (WINNT,$(OS_ARCH))
@@ -58,20 +60,19 @@ DEFINES += -DGRE_MILESTONE=$(GRE_MILESTO
 DEFINES += -DMOZ_APP_VERSION="$(MOZ_APP_VERSION)"
 APP_INI_DEPS += $(DEPTH)/config/autoconf.mk
 
 MOZ_SOURCE_STAMP := $(firstword $(shell cd $(topsrcdir)/$(MOZ_BUILD_APP)/.. && hg parent --template="{node|short}\n" 2>/dev/null))
 ifdef MOZ_SOURCE_STAMP
 DEFINES += -DMOZ_SOURCE_STAMP="$(MOZ_SOURCE_STAMP)"
 endif
 
-_dollar=$$
-SOURCE_REPO := $(shell cd $(topsrcdir)/$(MOZ_BUILD_APP)/.. && hg showconfig paths.default 2>/dev/null | head -n1 | sed -e "s/^ssh:/http:/" -e "s/\/$(_dollar)//" )
-ifdef SOURCE_REPO
-DEFINES += -DMOZ_SOURCE_REPO="$(SOURCE_REPO)"
+source_repo ?= $(call getSourceRepo,$(topsrcdir)/$(MOZ_BUILD_APP)/..)
+ifneq (,$(source_repo))
+  DEFINES += -DMOZ_SOURCE_REPO="$(source_repo)"
 endif
 
 DEFINES += \
   -DMOZ_APP_BASENAME="$(MOZ_APP_BASENAME)" \
   -DMOZ_APP_VENDOR="$(MOZ_APP_VENDOR)" \
   -DMOZ_APP_ID="$(MOZ_APP_ID)" \
   -DMAR_CHANNEL_ID="$(MAR_CHANNEL_ID)" \
   -DACCEPTED_MAR_CHANNEL_IDS="$(ACCEPTED_MAR_CHANNEL_IDS)" \
--- a/build/autoconf/toolchain.m4
+++ b/build/autoconf/toolchain.m4
@@ -51,20 +51,20 @@ if test "$GXX" = yes; then
    if test "`$CXX -help 2>&1 | grep -c 'Intel(R) C++ Compiler'`" != "0"; then
      INTEL_CXX=1
    fi
 fi
 
 CLANG_CC=
 CLANG_CXX=
 if test "$GCC" = yes; then
-   if test "`$CC -v 2>&1 | grep -c 'clang version\|Apple.*clang'`" != "0"; then
+   if test "`$CC -v 2>&1 | egrep -c '(clang version|Apple.*clang)'`" != "0"; then
      CLANG_CC=1
    fi
 fi
 
 if test "$GXX" = yes; then
-   if test "`$CXX -v 2>&1 | grep -c 'clang version\|Apple.*clang'`" != "0"; then
+   if test "`$CXX -v 2>&1 | egrep -c '(clang version|Apple.*clang)'`" != "0"; then
      CLANG_CXX=1
    fi
 fi
 AC_SUBST(CLANG_CXX)
 ])
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -438,16 +438,17 @@ user_pref("browser.console.showInPanel",
 user_pref("browser.dom.window.dump.enabled", true);
 user_pref("browser.firstrun.show.localepicker", false);
 user_pref("browser.firstrun.show.uidiscovery", false);
 user_pref("browser.startup.page", 0); // use about:blank, not browser.startup.homepage
 user_pref("browser.ui.layout.tablet", 0); // force tablet UI off
 user_pref("dom.allow_scripts_to_close_windows", true);
 user_pref("dom.disable_open_during_load", false);
 user_pref("dom.experimental_forms", true); // on for testing
+user_pref("dom.experimental_forms_range", true); // on for testing
 user_pref("dom.max_script_run_time", 0); // no slow script dialogs
 user_pref("hangmonitor.timeout", 0); // no hang monitor
 user_pref("dom.max_chrome_script_run_time", 0);
 user_pref("dom.popup_maximum", -1);
 user_pref("dom.send_after_paint_to_content", true);
 user_pref("dom.successive_dialog_time_limit", 0);
 user_pref("signed.applets.codebase_principal_support", true);
 user_pref("browser.shell.checkDefaultBrowser", false);
--- a/build/pgo/profileserver.py
+++ b/build/pgo/profileserver.py
@@ -15,17 +15,17 @@ from datetime import datetime
 
 SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
 sys.path.insert(0, SCRIPT_DIR)
 from automation import Automation
 from automationutils import getDebuggerInfo, addCommonOptions
 
 PORT = 8888
 PROFILE_DIRECTORY = os.path.abspath(os.path.join(SCRIPT_DIR, "./pgoprofile"))
-MOZ_JAR_LOG_DIR = os.path.abspath(os.getenv("JARLOG_DIR"))
+MOZ_JAR_LOG_FILE = os.path.abspath(os.getenv("JARLOG_FILE"))
 os.chdir(SCRIPT_DIR)
 
 class EasyServer(SocketServer.TCPServer):
   allow_reuse_address = True
 
 if __name__ == '__main__':
   from optparse import OptionParser
   automation = Automation()
@@ -42,17 +42,17 @@ if __name__ == '__main__':
   t = threading.Thread(target=httpd.serve_forever)
   t.setDaemon(True) # don't hang on exit
   t.start()
   
   automation.setServerInfo("localhost", PORT)
   automation.initializeProfile(PROFILE_DIRECTORY)
   browserEnv = automation.environment()
   browserEnv["XPCOM_DEBUG_BREAK"] = "warn"
-  browserEnv["MOZ_JAR_LOG_DIR"] = MOZ_JAR_LOG_DIR
+  browserEnv["MOZ_JAR_LOG_FILE"] = MOZ_JAR_LOG_FILE
 
   url = "http://localhost:%d/index.html" % PORT
   appPath = os.path.join(SCRIPT_DIR, automation.DEFAULT_APP)
   status = automation.runApp(url, browserEnv, appPath, PROFILE_DIRECTORY, {},
                              debuggerInfo=debuggerInfo,
                              # the profiling HTML doesn't output anything,
                              # so let's just run this without a timeout
                              timeout = None)
--- a/client.mk
+++ b/client.mk
@@ -198,17 +198,18 @@ ifdef MOZ_OBJDIR
   PGO_OBJDIR = $(MOZ_OBJDIR)
 else
   PGO_OBJDIR := $(TOPSRCDIR)
 endif
 
 profiledbuild::
 	$(MAKE) -f $(TOPSRCDIR)/client.mk realbuild MOZ_PROFILE_GENERATE=1 MOZ_PGO_INSTRUMENTED=1
 	$(MAKE) -C $(PGO_OBJDIR) package MOZ_PGO_INSTRUMENTED=1 MOZ_INTERNAL_SIGNING_FORMAT= MOZ_EXTERNAL_SIGNING_FORMAT=
-	MOZ_PGO_INSTRUMENTED=1 OBJDIR=${PGO_OBJDIR} JARLOG_DIR=${PGO_OBJDIR}/jarlog/en-US $(PROFILE_GEN_SCRIPT)
+	rm -f ${PGO_OBJDIR}/jarlog/en-US.log
+	MOZ_PGO_INSTRUMENTED=1 OBJDIR=${PGO_OBJDIR} JARLOG_FILE=${PGO_OBJDIR}/jarlog/en-US.log $(PROFILE_GEN_SCRIPT)
 	$(MAKE) -f $(TOPSRCDIR)/client.mk maybe_clobber_profiledbuild
 	$(MAKE) -f $(TOPSRCDIR)/client.mk realbuild MOZ_PROFILE_USE=1
 
 #####################################################
 # Build date unification
 
 ifdef MOZ_UNIFY_BDATE
 ifndef MOZ_BUILD_DATE
--- a/config/makefiles/makeutils.mk
+++ b/config/makefiles/makeutils.mk
@@ -108,10 +108,14 @@ endif #}
 ## Common makefile library loader
 ###########################################################################
 topORerr =$(if $(topsrcdir),$(topsrcdir),$(error topsrcdir is not defined))
 
 ifdef USE_AUTOTARGETS_MK # mkdir_deps
   include $(topORerr)/config/makefiles/autotargets.mk
 endif
 
+ifdef USE_RCS_MK
+  include $(topORerr)/config/makefiles/rcs.mk
+endif
+
 ## copy(src, dst): recursive copy
 copy_dir = (cd $(1)/. && $(TAR) $(TAR_CREATE_FLAGS_QUIET) - .) | (cd $(2)/. && tar -xf -)
new file mode 100644
--- /dev/null
+++ b/config/makefiles/rcs.mk
@@ -0,0 +1,42 @@
+# -*- makefile -*-
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+ifdef USE_RCS_MK #{
+
+ifndef INCLUDED_RCS_MK #{
+
+MOZ_RCS_TYPE ?= $(notdir $(wildcard $(topsrcdir)/.hg))
+
+
+###########################################################################
+# HAVE_MERCURIAL_RCS
+###########################################################################
+ifeq (.hg,$(MOZ_RCS_TYPE)) #{
+
+# Intent: Retrieve the http:// repository path for a directory.
+# Usage: $(call getSourceRepo[,repo_dir|args])
+# Args:
+#   path (optional): repository to query.  Defaults to $(topsrcdir)
+getSourceRepo = \
+  $(call FUNC_getSourceRepo,$(if $(1),cd $(1) && hg,hg --repository $(topsrcdir)))
+
+# return: http://hg.mozilla.org/mozilla-central
+FUNC_getSourceRepo = \
+  $(strip \
+    $(patsubst %/,%,\
+    $(patsubst ssh://%,http://%,\
+    $(firstword $(shell $(getargv) showconfig paths.default))\
+    )))
+
+endif #} HAVE_MERCURIAL_RCS
+
+
+INCLUDED_RCS_MK := 1
+endif #}
+
+endif #}
--- a/configure.in
+++ b/configure.in
@@ -4236,17 +4236,17 @@ MOZ_ONLY_TOUCH_EVENTS=
 MOZ_TOOLKIT_SEARCH=1
 MOZ_UI_LOCALE=en-US
 MOZ_UNIVERSALCHARDET=1
 MOZ_URL_CLASSIFIER=
 MOZ_XUL=1
 MOZ_ZIPWRITER=1
 NS_PRINTING=1
 MOZ_PDF_PRINTING=
-MOZ_DISABLE_DOMCRYPTO=
+MOZ_DISABLE_CRYPTOLEGACY=
 NSS_DISABLE_DBM=
 NECKO_WIFI=1
 NECKO_COOKIES=1
 NECKO_PROTOCOLS_DEFAULT="about data file ftp http res viewsource websocket wyciwyg device"
 USE_ARM_KUSER=
 BUILD_CTYPES=1
 MOZ_USE_NATIVE_POPUP_WINDOWS=
 MOZ_ANDROID_HISTORY=
@@ -6335,19 +6335,20 @@ if test -n "$MOZ_DISABLE_PARENTAL_CONTRO
     AC_DEFINE(MOZ_DISABLE_PARENTAL_CONTROLS)
 fi
 
 AC_SUBST(MOZ_DISABLE_PARENTAL_CONTROLS)
 
 dnl ========================================================
 dnl = Disable DOMCrypto
 dnl ========================================================
-if test -n "$MOZ_DISABLE_DOMCRYPTO"; then
-    AC_DEFINE(MOZ_DISABLE_DOMCRYPTO)
-fi
+if test -n "$MOZ_DISABLE_CRYPTOLEGACY"; then
+    AC_DEFINE(MOZ_DISABLE_CRYPTOLEGACY)
+fi
+AC_SUBST(MOZ_DISABLE_CRYPTOLEGACY)
 
 dnl ========================================================
 dnl =
 dnl = Module specific options
 dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(Individual module options)
 
@@ -8373,16 +8374,22 @@ if test -n "$MOZ_SERVICES_NOTIFICATIONS"
 fi
 
 dnl Build Sync Services if required
 AC_SUBST(MOZ_SERVICES_SYNC)
 if test -n "$MOZ_SERVICES_SYNC"; then
   AC_DEFINE(MOZ_SERVICES_SYNC)
 fi
 
+dnl Build Captive Portal Detector if required
+AC_SUBST(MOZ_CAPTIVEDETECT)
+if test -n "$MOZ_CAPTIVEDETECT"; then
+  AC_DEFINE(MOZ_CAPTIVEDETECT)
+fi
+
 dnl ========================================================
 if test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC" -o "$MOZ_DMD"; then
     MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS=
 fi
 
 if test "$MOZ_APP_COMPONENT_INCLUDE"; then
   AC_DEFINE_UNQUOTED(MOZ_APP_COMPONENT_INCLUDE, "$MOZ_APP_COMPONENT_INCLUDE")
 fi
--- a/content/base/public/nsISelectionPrivate.idl
+++ b/content/base/public/nsISelectionPrivate.idl
@@ -1,16 +1,15 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 #include "nsISelectionListener.idl"
-#include "nsIEnumerator.idl"
 #include "nsISelection.idl"
 
 interface nsRange;
 interface nsIDOMNode;
 interface nsISelectionListener;
 interface nsIContent;
 interface nsINode;
 
@@ -26,17 +25,17 @@ struct ScrollAxis;
 [ptr] native nsFrameSelection(nsFrameSelection);
 [ptr] native nsIFrame(nsIFrame);
 [ptr] native RangeArray(nsTArray<nsRange*>);
 [ref] native constTextRangeStyleRef(const nsTextRangeStyle);
 [ref] native nsPointRef(nsPoint);
 native nsDirection(nsDirection);
 native ScrollAxis(nsIPresShell::ScrollAxis);
 
-[scriptable, builtinclass, uuid(2e44b10f-7d6d-4bf4-92e2-f9551d22f422)]
+[scriptable, builtinclass, uuid(a6d2cedd-afbc-4d25-bffb-e725b9881e30)]
 interface nsISelectionPrivate : nsISelection
  {
     const short ENDOFPRECEDINGLINE=0;
     const short STARTOFNEXTLINE=1;
     
     attribute boolean interlinePosition;
 
     /* startBatchChanges
@@ -44,17 +43,16 @@ interface nsISelectionPrivate : nsISelec
     */
     void  startBatchChanges();
     
     /* endBatchChanges
        match this up with startBatchChanges
     */
     void  endBatchChanges();
 		
-    nsIEnumerator  getEnumerator();
     DOMString  toStringWithFormat(in string formatType, in unsigned long flags, in int32_t wrapColumn);
     void  addSelectionListener(in nsISelectionListener newListener);
     void  removeSelectionListener(in nsISelectionListener listenerToRemove);
 
     /* Table selection stuff
        We should probably move this and table-related 
        items in nsFrameSelection  to a
        new nsITableSelection interface
--- a/content/base/src/Element.cpp
+++ b/content/base/src/Element.cpp
@@ -328,17 +328,17 @@ Element::GetBindingURL(nsIDocument *aDoc
   // Get the computed -moz-binding directly from the style context
   nsPresContext *pctx = shell->GetPresContext();
   NS_ENSURE_TRUE(pctx, false);
 
   nsRefPtr<nsStyleContext> sc = pctx->StyleSet()->ResolveStyleFor(this,
                                                                   nullptr);
   NS_ENSURE_TRUE(sc, false);
 
-  *aResult = sc->GetStyleDisplay()->mBinding;
+  *aResult = sc->StyleDisplay()->mBinding;
 
   return true;
 }
 
 JSObject*
 Element::WrapObject(JSContext *aCx, JSObject *aScope,
                     bool *aTriedToWrap)
 {
@@ -588,17 +588,17 @@ static nsSize GetScrollRectSizeForOverfl
     return nsSize(0,0);
   }
 
   nsRect paddingRect = aFrame->GetPaddingRectRelativeToSelf();
   nsOverflowAreas overflowAreas(paddingRect, paddingRect);
   nsLayoutUtils::UnionChildOverflow(aFrame, overflowAreas);
   return nsLayoutUtils::GetScrolledRect(aFrame,
       overflowAreas.ScrollableOverflow(), paddingRect.Size(),
-      aFrame->GetStyleVisibility()->mDirection).Size();
+      aFrame->StyleVisibility()->mDirection).Size();
 }
 
 int32_t
 Element::ScrollHeight()
 {
   if (IsSVG())
     return 0;
 
@@ -636,17 +636,17 @@ Element::GetClientAreaRect()
   nsIFrame* styledFrame;
   nsIScrollableFrame* sf = GetScrollFrame(&styledFrame);
 
   if (sf) {
     return sf->GetScrollPortRect();
   }
 
   if (styledFrame &&
-      (styledFrame->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_INLINE ||
+      (styledFrame->StyleDisplay()->mDisplay != NS_STYLE_DISPLAY_INLINE ||
        styledFrame->IsFrameOfType(nsIFrame::eReplaced))) {
     // Special case code to make client area work even when there isn't
     // a scroll view, see bug 180552, bug 227567.
     return styledFrame->GetPaddingRect() - styledFrame->GetPositionIgnoringScrolling();
   }
 
   // SVG nodes reach here and just return 0
   return nsRect(0, 0, 0, 0);
--- a/content/base/src/nsDOMDataChannel.cpp
+++ b/content/base/src/nsDOMDataChannel.cpp
@@ -17,16 +17,17 @@ extern PRLogModuleInfo* GetDataChannelLo
 #undef LOG
 #define LOG(args) PR_LOG(GetDataChannelLog(), PR_LOG_DEBUG, args)
 
 
 #include "nsDOMDataChannel.h"
 #include "nsIDOMFile.h"
 #include "nsIJSNativeInitializer.h"
 #include "nsIDOMDataChannel.h"
+#include "nsIDOMRTCPeerConnection.h"
 #include "nsIDOMMessageEvent.h"
 #include "nsDOMClassInfo.h"
 #include "nsDOMEventTargetHelper.h"
 
 #include "js/Value.h"
 
 #include "nsError.h"
 #include "nsAutoPtr.h"
@@ -104,16 +105,21 @@ private:
   enum
   {
     DC_BINARY_TYPE_ARRAYBUFFER,
     DC_BINARY_TYPE_BLOB,
   } mBinaryType;
 };
 
 DOMCI_DATA(DataChannel, nsDOMDataChannel)
+// A bit of a hack for RTCPeerConnection, since it doesn't have a .cpp file of
+// its own.  Note that it's not castable to anything in particular other than
+// nsIDOMRTCPeerConnection, so we can just use nsIDOMRTCPeerConnection as the
+// "class".
+DOMCI_DATA(RTCPeerConnection, nsIDOMRTCPeerConnection)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMDataChannel,
                                                   nsDOMEventTargetHelper)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMDataChannel,
                                                 nsDOMEventTargetHelper)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -448,17 +448,20 @@ NS_INTERFACE_MAP_END
 
 // Threadsafe when GetMutable() == false
 NS_IMPL_THREADSAFE_ADDREF(nsDOMFile)
 NS_IMPL_THREADSAFE_RELEASE(nsDOMFile)
 
 ////////////////////////////////////////////////////////////////////////////
 // nsDOMFileCC implementation
 
-NS_IMPL_CYCLE_COLLECTION_0(nsDOMFileCC)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsDOMFileCC)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMFileCC)
+  // We don't have anything to traverse, but some of our subclasses do.
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMFileCC)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFile)
   NS_INTERFACE_MAP_ENTRY(nsIDOMBlob)
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMFile, mIsFile)
   NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
   NS_INTERFACE_MAP_ENTRY(nsIMutable)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(File, mIsFile)
--- a/content/base/src/nsDocumentEncoder.cpp
+++ b/content/base/src/nsDocumentEncoder.cpp
@@ -112,17 +112,17 @@ protected:
         nsIFrame* frame = content->GetPrimaryFrame();
         if (!frame) {
           if (aNode->IsNodeOfType(nsINode::eTEXT)) {
             // We have already checked that our parent is visible.
             return true;
           }
           return false;
         }
-        bool isVisible = frame->GetStyleVisibility()->IsVisible();
+        bool isVisible = frame->StyleVisibility()->IsVisible();
         if (!isVisible && aNode->IsNodeOfType(nsINode::eTEXT))
           return false;
       }
     }
     return true;
   }
 
   static bool IsTag(nsIContent* aContent, nsIAtom* aAtom);
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1793,16 +1793,17 @@ GK_ATOM(menuFrame,"MenuFrame")
 GK_ATOM(menuPopupFrame,"MenuPopupFrame")
 GK_ATOM(objectFrame, "ObjectFrame")
 GK_ATOM(pageFrame, "PageFrame")
 GK_ATOM(pageBreakFrame, "PageBreakFrame")
 GK_ATOM(pageContentFrame, "PageContentFrame")
 GK_ATOM(placeholderFrame, "PlaceholderFrame")
 GK_ATOM(popupSetFrame, "PopupSetFrame")
 GK_ATOM(canvasFrame, "CanvasFrame")
+GK_ATOM(rangeFrame, "RangeFrame")
 GK_ATOM(rootFrame, "RootFrame")
 GK_ATOM(scrollFrame, "ScrollFrame")
 GK_ATOM(scrollbarFrame, "ScrollbarFrame")
 GK_ATOM(sequenceFrame, "SequenceFrame")
 GK_ATOM(sliderFrame, "sliderFrame")
 GK_ATOM(tableCaptionFrame, "TableCaptionFrame")
 GK_ATOM(tableCellFrame, "TableCellFrame")
 GK_ATOM(tableColFrame, "TableColFrame")
--- a/content/base/src/nsINode.cpp
+++ b/content/base/src/nsINode.cpp
@@ -94,17 +94,17 @@
 #include "nsUnicharUtils.h"
 #include "nsXBLBinding.h"
 #include "nsXBLInsertionPoint.h"
 #include "nsXBLPrototypeBinding.h"
 #include "prprf.h"
 #include "xpcpublic.h"
 #include "nsCSSRuleProcessor.h"
 #include "nsCSSParser.h"
-#include "nsHTMLLegendElement.h"
+#include "HTMLLegendElement.h"
 #include "nsWrapperCacheInlines.h"
 #include "WrapperFactory.h"
 #include "DocumentType.h"
 #include <algorithm>
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -2054,21 +2054,21 @@ CanvasRenderingContext2D::SetFont(const 
 
   nsRefPtr<nsStyleContext> sc =
       styleSet->ResolveStyleForRules(parentContext, rules);
   if (!sc) {
     error.Throw(NS_ERROR_FAILURE);
     return;
   }
 
-  const nsStyleFont* fontStyle = sc->GetStyleFont();
+  const nsStyleFont* fontStyle = sc->StyleFont();
 
   NS_ASSERTION(fontStyle, "Could not obtain font style");
 
-  nsIAtom* language = sc->GetStyleFont()->mLanguage;
+  nsIAtom* language = sc->StyleFont()->mLanguage;
   if (!language) {
     language = presShell->GetPresContext()->GetLanguageFromCharset();
   }
 
   // use CSS pixels instead of dev pixels to avoid being affected by page zoom
   const uint32_t aupcp = nsPresContext::AppUnitsPerCSSPixel();
   // un-zoom the font size to avoid being affected by text-only zoom
   //
@@ -2479,17 +2479,17 @@ CanvasRenderingContext2D::DrawOrMeasureT
     nsRefPtr<nsStyleContext> canvasStyle =
       nsComputedDOMStyle::GetStyleContextForElement(mCanvasElement,
                                                     nullptr,
                                                     presShell);
     if (!canvasStyle) {
       return NS_ERROR_FAILURE;
     }
 
-    isRTL = canvasStyle->GetStyleVisibility()->mDirection ==
+    isRTL = canvasStyle->StyleVisibility()->mDirection ==
       NS_STYLE_DIRECTION_RTL;
   } else {
     isRTL = GET_BIDI_OPTION_DIRECTION(document->GetBidiOptions()) == IBMBIDI_TEXTDIRECTION_RTL;
   }
 
   gfxFontGroup* currentFontStyle = GetCurrentFontStyle();
   NS_ASSERTION(currentFontStyle, "font group is null");
 
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -2479,17 +2479,17 @@ nsEventStateManager::DoScrollZoom(nsIFra
 }
 
 static nsIFrame*
 GetParentFrameToScroll(nsIFrame* aFrame)
 {
   if (!aFrame)
     return nullptr;
 
-  if (aFrame->GetStyleDisplay()->mPosition == NS_STYLE_POSITION_FIXED &&
+  if (aFrame->StyleDisplay()->mPosition == NS_STYLE_POSITION_FIXED &&
       nsLayoutUtils::IsReallyFixedPos(aFrame))
     return aFrame->PresContext()->GetPresShell()->GetRootScrollFrame();
 
   return aFrame->GetParent();
 }
 
 void
 nsEventStateManager::DispatchLegacyMouseScrollEvents(nsIFrame* aTargetFrame,
@@ -3125,17 +3125,17 @@ nsEventStateManager::PostHandleEvent(nsP
       }
 
       nsCOMPtr<nsIContent> activeContent;
       if (nsEventStatus_eConsumeNoDefault != *aStatus) {
         nsCOMPtr<nsIContent> newFocus;      
         bool suppressBlur = false;
         if (mCurrentTarget) {
           mCurrentTarget->GetContentForEvent(aEvent, getter_AddRefs(newFocus));
-          const nsStyleUserInterface* ui = mCurrentTarget->GetStyleUserInterface();
+          const nsStyleUserInterface* ui = mCurrentTarget->StyleUserInterface();
           suppressBlur = (ui->mUserFocus == NS_STYLE_USER_FOCUS_IGNORE);
           activeContent = mCurrentTarget->GetContent();
         }
 
         nsIFrame* currFrame = mCurrentTarget;
 
         // When a root content which isn't editable but has an editable HTML
         // <body> element is clicked, we should redirect the focus to the
@@ -3160,17 +3160,17 @@ nsEventStateManager::PostHandleEvent(nsP
           }
         }
 
         // When the mouse is pressed, the default action is to focus the
         // target. Look for the nearest enclosing focusable frame.
         while (currFrame) {
           // If the mousedown happened inside a popup, don't
           // try to set focus on one of its containing elements
-          const nsStyleDisplay* display = currFrame->GetStyleDisplay();
+          const nsStyleDisplay* display = currFrame->StyleDisplay();
           if (display->mDisplay == NS_STYLE_DISPLAY_POPUP) {
             newFocus = nullptr;
             break;
           }
 
           int32_t tabIndexUnused;
           if (currFrame->IsFocusable(&tabIndexUnused, true)) {
             newFocus = currFrame->GetContent();
@@ -4785,17 +4785,17 @@ nsEventStateManager::SetContentState(nsI
   if (aState == NS_EVENT_STATE_HOVER || aState == NS_EVENT_STATE_ACTIVE) {
     // Hover and active are hierarchical
     updateAncestors = true;
 
     // check to see that this state is allowed by style. Check dragover too?
     // XXX Is this even what we want?
     if (mCurrentTarget)
     {
-      const nsStyleUserInterface* ui = mCurrentTarget->GetStyleUserInterface();
+      const nsStyleUserInterface* ui = mCurrentTarget->StyleUserInterface();
       if (ui->mUserInput == NS_STYLE_USER_INPUT_NONE)
         return false;
     }
 
     if (aState == NS_EVENT_STATE_ACTIVE) {
       if (aContent != mActiveContent) {
         notifyContent1 = aContent;
         notifyContent2 = mActiveContent;
--- a/content/events/test/test_eventctors.html
+++ b/content/events/test/test_eventctors.html
@@ -157,16 +157,57 @@ var dict = { get detail() { throw "foo";
 try {
   e = new CustomEvent("hello", dict);
 } catch (exp) {
   ex = true;
 }
 ok(ex, "Should have thrown an exception!");
 ex = false;
 
+// BlobEvent
+
+try {
+  e = new BlobEvent();
+} catch(exp) {
+  ex = true;
+}
+ok(ex, "First parameter is required!");
+ex = false;
+
+e = new BlobEvent("hello");
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event shouldn't be trusted!");
+ok(!e.bubbles, "Event shouldn't bubble!");
+ok(!e.cancelable, "Event shouldn't be cancelable!");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+var blob = Blob();
+e = new BlobEvent("hello", { bubbles: true, cancelable: true, data: blob });
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event shouldn't be trusted!");
+ok(e.bubbles, "Event should bubble!");
+ok(e.cancelable, "Event should be cancelable!");
+is(e.data, blob , "Wrong event.data!");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+
+e = new BlobEvent("hello", {data: blob});
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event shouldn't be trusted!");
+ok(!e.bubbles, "Event shouldn't bubble!");
+ok(!e.cancelable, "Event should be cancelable1!");
+is(e.data, blob , "Wrong event.data!");
+
+e = new BlobEvent("hello", { data: null });
+is(e.data, null, "Wrong event.data!");
+ok(!e.bubbles, "Event shouldn't bubble!");
+ok(!e.cancelable, "Event shouldn't be cancelable!");
+blob = null;
 // CloseEvent
 
 try {
   e = new CloseEvent();
 } catch(exp) {
   ex = true;
 }
 ok(ex, "First parameter is required!");
new file mode 100644
--- /dev/null
+++ b/content/html/content/crashtests/838256-1.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<style>
+
+::-moz-range-track {
+  display: none ! important;
+}
+
+::-moz-range-thumb {
+  display: none ! important;
+}
+
+</style>
+</head>
+<body>
+<input type="range">
+</body>
+</html>
--- a/content/html/content/crashtests/crashtests.list
+++ b/content/html/content/crashtests/crashtests.list
@@ -44,8 +44,10 @@ load 795221-4.html
 load 795221-5.xml
 load 798802-1.html
 load 811226.html
 load 819745.html
 pref(dom.experimental_forms,true) load 828472.html
 load 828180.html
 load 832011.html
 load 837033.html
+pref(dom.experimental_forms_range,true) load 838256-1.html
+
--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -253,21 +253,16 @@ public:
   // main thread when/if the size changes.
   void UpdateMediaSize(nsIntSize size);
 
   // Returns the CanPlayStatus indicating if we can handle the
   // full MIME type including the optional codecs parameter.
   static mozilla::CanPlayStatus GetCanPlay(const nsAString& aType);
 
   /**
-   * Get the mime type for this element.
-   */
-  void GetMimeType(nsCString& aMimeType);
-
-  /**
    * Called when a child source element is added to this media element. This
    * may queue a task to run the select resource algorithm if appropriate.
    */
   void NotifyAddedSource();
 
   /**
    * Called when there's been an error fetching the resource. This decides
    * whether it's appropriate to fire an error event.
@@ -894,23 +889,16 @@ protected:
   mozilla::CORSMode mCORSMode;
 
   // True if the media has an audio track
   bool mHasAudio;
 
   // True if the media's channel's download has been suspended.
   bool mDownloadSuspendedByCache;
 
-  // The Content-Type for this media. When we are sniffing for the Content-Type,
-  // and we are recreating a channel after the initial load, we need that
-  // information to give it as a hint to the channel for it to bypass the
-  // sniffing phase, that would fail because sniffing only works when applied to
-  // the first bytes of the stream.
-  nsCString mMimeType;
-
   // Audio Channel Type.
   mozilla::dom::AudioChannelType mAudioChannelType;
 
   // The audiochannel has been suspended.
   bool mChannelSuspended;
 
   // Is this media element playing?
   bool mPlayingThroughTheAudioChannel;
--- a/content/html/content/public/nsIFormControl.h
+++ b/content/html/content/public/nsIFormControl.h
@@ -58,16 +58,17 @@ enum InputElementTypes {
   NS_FORM_INPUT_PASSWORD,
   NS_FORM_INPUT_RADIO,
   NS_FORM_INPUT_SEARCH,
   NS_FORM_INPUT_SUBMIT,
   NS_FORM_INPUT_TEL,
   NS_FORM_INPUT_TEXT,
   NS_FORM_INPUT_TIME,
   NS_FORM_INPUT_URL,
+  NS_FORM_INPUT_RANGE,
   eInputElementTypesMax
 };
 
 PR_STATIC_ASSERT((uint32_t)eFormControlsWithoutSubTypesMax < (uint32_t)NS_FORM_BUTTON_ELEMENT);
 PR_STATIC_ASSERT((uint32_t)eButtonElementTypesMax < (uint32_t)NS_FORM_INPUT_ELEMENT);
 PR_STATIC_ASSERT((uint32_t)eInputElementTypesMax  < 1<<8);
 
 #define NS_IFORMCONTROL_IID   \
--- a/content/html/content/src/HTMLButtonElement.cpp
+++ b/content/html/content/src/HTMLButtonElement.cpp
@@ -114,20 +114,20 @@ NS_IMETHODIMP
 HTMLButtonElement::GetForm(nsIDOMHTMLFormElement** aForm)
 {
   return nsGenericHTMLFormElement::GetForm(aForm);
 }
 
 NS_IMPL_BOOL_ATTR(HTMLButtonElement, Autofocus, autofocus)
 NS_IMPL_BOOL_ATTR(HTMLButtonElement, Disabled, disabled)
 NS_IMPL_ACTION_ATTR(HTMLButtonElement, FormAction, formaction)
-NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLButtonElement, FormEnctype, formenctype,
-                                kFormDefaultEnctype->tag)
-NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLButtonElement, FormMethod, formmethod,
-                                kFormDefaultMethod->tag)
+NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALID_VALUES(HTMLButtonElement, FormEnctype, formenctype,
+                                                 "", kFormDefaultEnctype->tag)
+NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALID_VALUES(HTMLButtonElement, FormMethod, formmethod,
+                                                 "", kFormDefaultMethod->tag)
 NS_IMPL_BOOL_ATTR(HTMLButtonElement, FormNoValidate, formnovalidate)
 NS_IMPL_STRING_ATTR(HTMLButtonElement, FormTarget, formtarget)
 NS_IMPL_STRING_ATTR(HTMLButtonElement, Name, name)
 NS_IMPL_STRING_ATTR(HTMLButtonElement, Value, value)
 NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLButtonElement, Type, type,
                                 kButtonDefaultType->tag)
 
 int32_t
rename from content/html/content/src/nsHTMLFrameElement.cpp
rename to content/html/content/src/HTMLFrameElement.cpp
--- a/content/html/content/src/nsHTMLFrameElement.cpp
+++ b/content/html/content/src/HTMLFrameElement.cpp
@@ -1,119 +1,78 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/Util.h"
-
-#include "nsIDOMHTMLFrameElement.h"
-#include "nsGenericHTMLFrameElement.h"
-#include "nsGkAtoms.h"
-#include "nsError.h"
+#include "HTMLFrameElement.h"
+#include "mozilla/dom/HTMLFrameElementBinding.h"
 
 class nsIDOMDocument;
 
-using namespace mozilla;
-using namespace mozilla::dom;
-
-class nsHTMLFrameElement : public nsGenericHTMLFrameElement,
-                           public nsIDOMHTMLFrameElement
-{
-public:
-  nsHTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
-                     mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER);
-  virtual ~nsHTMLFrameElement();
-
-  // nsISupports
-  NS_DECL_ISUPPORTS_INHERITED
-
-  // nsIDOMNode
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
-
-  // nsIDOMElement
-  NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
+NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Frame)
+DOMCI_NODE_DATA(HTMLFrameElement, mozilla::dom::HTMLFrameElement)
 
-  // nsIDOMHTMLElement
-  NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
-
-  // nsIDOMHTMLFrameElement
-  NS_DECL_NSIDOMHTMLFRAMEELEMENT
+namespace mozilla {
+namespace dom {
 
-  // nsIContent
-  virtual bool ParseAttribute(int32_t aNamespaceID,
-                                nsIAtom* aAttribute,
-                                const nsAString& aValue,
-                                nsAttrValue& aResult);
-  NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
-  nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
-  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
-  virtual nsXPCClassInfo* GetClassInfo();
-  virtual nsIDOMNode* AsDOMNode() { return this; }
-};
-
-
-NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Frame)
-
-
-nsHTMLFrameElement::nsHTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
-                                       FromParser aFromParser)
+HTMLFrameElement::HTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+                                   FromParser aFromParser)
   : nsGenericHTMLFrameElement(aNodeInfo, aFromParser)
 {
+  SetIsDOMBinding();
 }
 
-nsHTMLFrameElement::~nsHTMLFrameElement()
+HTMLFrameElement::~HTMLFrameElement()
 {
 }
 
 
-NS_IMPL_ADDREF_INHERITED(nsHTMLFrameElement, Element)
-NS_IMPL_RELEASE_INHERITED(nsHTMLFrameElement, Element)
+NS_IMPL_ADDREF_INHERITED(HTMLFrameElement, Element)
+NS_IMPL_RELEASE_INHERITED(HTMLFrameElement, Element)
 
 
-DOMCI_NODE_DATA(HTMLFrameElement, nsHTMLFrameElement)
-
-// QueryInterface implementation for nsHTMLFrameElement
-NS_INTERFACE_TABLE_HEAD(nsHTMLFrameElement)
-  NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLFrameElement, nsIDOMHTMLFrameElement)
-  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLFrameElement,
+// QueryInterface implementation for HTMLFrameElement
+NS_INTERFACE_TABLE_HEAD(HTMLFrameElement)
+  NS_HTML_CONTENT_INTERFACE_TABLE1(HTMLFrameElement, nsIDOMHTMLFrameElement)
+  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLFrameElement,
                                                nsGenericHTMLFrameElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLFrameElement)
 
 
-NS_IMPL_ELEMENT_CLONE(nsHTMLFrameElement)
+NS_IMPL_ELEMENT_CLONE(HTMLFrameElement)
 
 
-NS_IMPL_STRING_ATTR(nsHTMLFrameElement, FrameBorder, frameborder)
-NS_IMPL_URI_ATTR(nsHTMLFrameElement, LongDesc, longdesc)
-NS_IMPL_STRING_ATTR(nsHTMLFrameElement, MarginHeight, marginheight)
-NS_IMPL_STRING_ATTR(nsHTMLFrameElement, MarginWidth, marginwidth)
-NS_IMPL_STRING_ATTR(nsHTMLFrameElement, Name, name)
-NS_IMPL_BOOL_ATTR(nsHTMLFrameElement, NoResize, noresize)
-NS_IMPL_STRING_ATTR(nsHTMLFrameElement, Scrolling, scrolling)
-NS_IMPL_URI_ATTR(nsHTMLFrameElement, Src, src)
+NS_IMPL_STRING_ATTR(HTMLFrameElement, FrameBorder, frameborder)
+NS_IMPL_URI_ATTR(HTMLFrameElement, LongDesc, longdesc)
+NS_IMPL_STRING_ATTR(HTMLFrameElement, MarginHeight, marginheight)
+NS_IMPL_STRING_ATTR(HTMLFrameElement, MarginWidth, marginwidth)
+NS_IMPL_STRING_ATTR(HTMLFrameElement, Name, name)
+NS_IMPL_BOOL_ATTR(HTMLFrameElement, NoResize, noresize)
+NS_IMPL_STRING_ATTR(HTMLFrameElement, Scrolling, scrolling)
+NS_IMPL_URI_ATTR(HTMLFrameElement, Src, src)
 
 
 NS_IMETHODIMP
-nsHTMLFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument)
+HTMLFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument)
 {
   return nsGenericHTMLFrameElement::GetContentDocument(aContentDocument);
 }
 
 NS_IMETHODIMP
-nsHTMLFrameElement::GetContentWindow(nsIDOMWindow** aContentWindow)
+HTMLFrameElement::GetContentWindow(nsIDOMWindow** aContentWindow)
 {
   return nsGenericHTMLFrameElement::GetContentWindow(aContentWindow);
 }
 
 bool
-nsHTMLFrameElement::ParseAttribute(int32_t aNamespaceID,
-                                   nsIAtom* aAttribute,
-                                   const nsAString& aValue,
-                                   nsAttrValue& aResult)
+HTMLFrameElement::ParseAttribute(int32_t aNamespaceID,
+                                 nsIAtom* aAttribute,
+                                 const nsAString& aValue,
+                                 nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::bordercolor) {
       return aResult.ParseColor(aValue);
     }
     if (aAttribute == nsGkAtoms::frameborder) {
       return ParseFrameborderValue(aValue, aResult);
     }
@@ -136,23 +95,60 @@ static void
 MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                       nsRuleData* aData)
 {
   nsGenericHTMLElement::MapScrollingAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(bool)
-nsHTMLFrameElement::IsAttributeMapped(const nsIAtom* aAttribute) const
+HTMLFrameElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry* const map[] = {
     sScrollingAttributeMap,
     sCommonAttributeMap,
   };
   
   return FindAttributeDependence(aAttribute, map);
 }
 
 nsMapRuleToAttributesFunc
-nsHTMLFrameElement::GetAttributeMappingFunction() const
+HTMLFrameElement::GetAttributeMappingFunction() const
 {
   return &MapAttributesIntoRule;
 }
+
+already_AddRefed<nsIDocument>
+HTMLFrameElement::GetContentDocument(ErrorResult& aRv)
+{
+  nsCOMPtr<nsIDOMDocument> doc;
+  nsresult rv = nsGenericHTMLFrameElement::GetContentDocument(getter_AddRefs(doc));
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIDocument> ret = do_QueryInterface(doc);
+  return ret.forget();
+}
+
+already_AddRefed<nsIDOMWindow>
+HTMLFrameElement::GetContentWindow(ErrorResult& aRv)
+{
+  nsCOMPtr<nsIDOMWindow> win;
+  nsresult rv = nsGenericHTMLFrameElement::GetContentWindow(getter_AddRefs(win));
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return nullptr;
+  }
+
+  return win.forget();
+}
+
+JSObject*
+HTMLFrameElement::WrapNode(JSContext* aCx, JSObject* aScope,
+                           bool* aTriedToWrap)
+{
+  return HTMLFrameElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+}
+
+} // namespace mozilla
+} // namespace dom
copy from content/html/content/src/nsHTMLFrameElement.cpp
copy to content/html/content/src/HTMLFrameElement.h
--- a/content/html/content/src/nsHTMLFrameElement.cpp
+++ b/content/html/content/src/HTMLFrameElement.h
@@ -1,32 +1,33 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#ifndef mozilla_dom_HTMLFrameElement_h
+#define mozilla_dom_HTMLFrameElement_h
+
 #include "mozilla/Util.h"
-
 #include "nsIDOMHTMLFrameElement.h"
 #include "nsGenericHTMLFrameElement.h"
 #include "nsGkAtoms.h"
-#include "nsError.h"
 
 class nsIDOMDocument;
 
-using namespace mozilla;
-using namespace mozilla::dom;
+namespace mozilla {
+namespace dom {
 
-class nsHTMLFrameElement : public nsGenericHTMLFrameElement,
-                           public nsIDOMHTMLFrameElement
+class HTMLFrameElement : public nsGenericHTMLFrameElement,
+                         public nsIDOMHTMLFrameElement
 {
 public:
-  nsHTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
-                     mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER);
-  virtual ~nsHTMLFrameElement();
+  HTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+                   FromParser aFromParser = NOT_FROM_PARSER);
+  virtual ~HTMLFrameElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
@@ -35,124 +36,82 @@ public:
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
   // nsIDOMHTMLFrameElement
   NS_DECL_NSIDOMHTMLFRAMEELEMENT
 
   // nsIContent
   virtual bool ParseAttribute(int32_t aNamespaceID,
-                                nsIAtom* aAttribute,
-                                const nsAString& aValue,
-                                nsAttrValue& aResult);
+                              nsIAtom* aAttribute,
+                              const nsAString& aValue,
+                              nsAttrValue& aResult);
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
   virtual nsXPCClassInfo* GetClassInfo();
   virtual nsIDOMNode* AsDOMNode() { return this; }
+
+  // WebIDL API
+  // The XPCOM GetFrameBorder is OK for us
+  void SetFrameBorder(const nsAString& aFrameBorder, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::frameborder, aFrameBorder, aError);
+  }
+
+  // The XPCOM GetLongDesc is OK for us
+  void SetLongDesc(const nsAString& aLongDesc, ErrorResult& aError)
+  {
+    SetAttrHelper(nsGkAtoms::longdesc, aLongDesc);
+  }
+
+  // The XPCOM GetMarginHeight is OK for us
+  void SetMarginHeight(const nsAString& aMarginHeight, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::marginheight, aMarginHeight, aError);
+  }
+
+  // The XPCOM GetMarginWidth is OK for us
+  void SetMarginWidth(const nsAString& aMarginWidth, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::marginwidth, aMarginWidth, aError);
+  }
+
+  // The XPCOM GetName is OK for us
+  void SetName(const nsAString& aName, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::name, aName, aError);
+  }
+
+  bool NoResize() const
+  {
+   return GetBoolAttr(nsGkAtoms::noresize);
+  }
+  void SetNoResize(bool& aNoResize, ErrorResult& aError)
+  {
+    SetHTMLBoolAttr(nsGkAtoms::noresize, aNoResize, aError);
+  }
+
+  // The XPCOM GetScrolling is OK for us
+  void SetScrolling(const nsAString& aScrolling, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::scrolling, aScrolling, aError);
+  }
+
+  // The XPCOM GetSrc is OK for us
+  void SetSrc(const nsAString& aSrc, ErrorResult& aError)
+  {
+    SetAttrHelper(nsGkAtoms::src, aSrc);
+  }
+
+  already_AddRefed<nsIDocument> GetContentDocument(ErrorResult& aRv);
+
+  already_AddRefed<nsIDOMWindow> GetContentWindow(ErrorResult& aRv);
+
+protected:
+  virtual JSObject* WrapNode(JSContext* aCx, JSObject* aScope,
+                             bool* aTriedToWrap) MOZ_OVERRIDE;
 };
 
-
-NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Frame)
-
-
-nsHTMLFrameElement::nsHTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
-                                       FromParser aFromParser)
-  : nsGenericHTMLFrameElement(aNodeInfo, aFromParser)
-{
-}
-
-nsHTMLFrameElement::~nsHTMLFrameElement()
-{
-}
-
-
-NS_IMPL_ADDREF_INHERITED(nsHTMLFrameElement, Element)
-NS_IMPL_RELEASE_INHERITED(nsHTMLFrameElement, Element)
-
-
-DOMCI_NODE_DATA(HTMLFrameElement, nsHTMLFrameElement)
-
-// QueryInterface implementation for nsHTMLFrameElement
-NS_INTERFACE_TABLE_HEAD(nsHTMLFrameElement)
-  NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLFrameElement, nsIDOMHTMLFrameElement)
-  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLFrameElement,
-                                               nsGenericHTMLFrameElement)
-NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLFrameElement)
-
-
-NS_IMPL_ELEMENT_CLONE(nsHTMLFrameElement)
-
-
-NS_IMPL_STRING_ATTR(nsHTMLFrameElement, FrameBorder, frameborder)
-NS_IMPL_URI_ATTR(nsHTMLFrameElement, LongDesc, longdesc)
-NS_IMPL_STRING_ATTR(nsHTMLFrameElement, MarginHeight, marginheight)
-NS_IMPL_STRING_ATTR(nsHTMLFrameElement, MarginWidth, marginwidth)
-NS_IMPL_STRING_ATTR(nsHTMLFrameElement, Name, name)
-NS_IMPL_BOOL_ATTR(nsHTMLFrameElement, NoResize, noresize)
-NS_IMPL_STRING_ATTR(nsHTMLFrameElement, Scrolling, scrolling)
-NS_IMPL_URI_ATTR(nsHTMLFrameElement, Src, src)
-
-
-NS_IMETHODIMP
-nsHTMLFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument)
-{
-  return nsGenericHTMLFrameElement::GetContentDocument(aContentDocument);
-}
+} // namespace dom
+} // namespace mozilla
 
-NS_IMETHODIMP
-nsHTMLFrameElement::GetContentWindow(nsIDOMWindow** aContentWindow)
-{
-  return nsGenericHTMLFrameElement::GetContentWindow(aContentWindow);
-}
-
-bool
-nsHTMLFrameElement::ParseAttribute(int32_t aNamespaceID,
-                                   nsIAtom* aAttribute,
-                                   const nsAString& aValue,
-                                   nsAttrValue& aResult)
-{
-  if (aNamespaceID == kNameSpaceID_None) {
-    if (aAttribute == nsGkAtoms::bordercolor) {
-      return aResult.ParseColor(aValue);
-    }
-    if (aAttribute == nsGkAtoms::frameborder) {
-      return ParseFrameborderValue(aValue, aResult);
-    }
-    if (aAttribute == nsGkAtoms::marginwidth) {
-      return aResult.ParseSpecialIntValue(aValue);
-    }
-    if (aAttribute == nsGkAtoms::marginheight) {
-      return aResult.ParseSpecialIntValue(aValue);
-    }
-    if (aAttribute == nsGkAtoms::scrolling) {
-      return ParseScrollingValue(aValue, aResult);
-    }
-  }
-
-  return nsGenericHTMLFrameElement::ParseAttribute(aNamespaceID, aAttribute,
-                                                   aValue, aResult);
-}
-
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                      nsRuleData* aData)
-{
-  nsGenericHTMLElement::MapScrollingAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
-}
-
-NS_IMETHODIMP_(bool)
-nsHTMLFrameElement::IsAttributeMapped(const nsIAtom* aAttribute) const
-{
-  static const MappedAttributeEntry* const map[] = {
-    sScrollingAttributeMap,
-    sCommonAttributeMap,
-  };
-  
-  return FindAttributeDependence(aAttribute, map);
-}
-
-nsMapRuleToAttributesFunc
-nsHTMLFrameElement::GetAttributeMappingFunction() const
-{
-  return &MapAttributesIntoRule;
-}
+#endif // mozilla_dom_HTMLFrameElement_h
rename from content/html/content/src/nsHTMLLegendElement.cpp
rename to content/html/content/src/HTMLLegendElement.cpp
--- a/content/html/content/src/nsHTMLLegendElement.cpp
+++ b/content/html/content/src/HTMLLegendElement.cpp
@@ -1,152 +1,147 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "nsHTMLLegendElement.h"
+
+#include "mozilla/dom/HTMLLegendElement.h"
+#include "mozilla/dom/HTMLLegendElementBinding.h"
 #include "nsIDOMHTMLFormElement.h"
-#include "nsIDOMEventTarget.h"
-#include "nsGkAtoms.h"
-#include "nsStyleConsts.h"
-#include "nsIForm.h"
-#include "nsIFormControl.h"
-#include "nsIDocument.h"
-#include "nsPIDOMWindow.h"
 #include "nsFocusManager.h"
 #include "nsIFrame.h"
 
-using namespace mozilla;
-using namespace mozilla::dom;
-
 NS_IMPL_NS_NEW_HTML_ELEMENT(Legend)
+DOMCI_NODE_DATA(HTMLLegendElement, mozilla::dom::HTMLLegendElement)
 
 
-nsHTMLLegendElement::nsHTMLLegendElement(already_AddRefed<nsINodeInfo> aNodeInfo)
+namespace mozilla {
+namespace dom {
+
+
+HTMLLegendElement::HTMLLegendElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
 }
 
-nsHTMLLegendElement::~nsHTMLLegendElement()
+HTMLLegendElement::~HTMLLegendElement()
 {
 }
 
 
-NS_IMPL_ADDREF_INHERITED(nsHTMLLegendElement, Element)
-NS_IMPL_RELEASE_INHERITED(nsHTMLLegendElement, Element)
+NS_IMPL_ADDREF_INHERITED(HTMLLegendElement, Element)
+NS_IMPL_RELEASE_INHERITED(HTMLLegendElement, Element)
 
 
-DOMCI_NODE_DATA(HTMLLegendElement, nsHTMLLegendElement)
-
-// QueryInterface implementation for nsHTMLLegendElement
-NS_INTERFACE_TABLE_HEAD(nsHTMLLegendElement)
-  NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLLegendElement, nsIDOMHTMLLegendElement)
-  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLLegendElement,
+// QueryInterface implementation for HTMLLegendElement
+NS_INTERFACE_TABLE_HEAD(HTMLLegendElement)
+  NS_HTML_CONTENT_INTERFACE_TABLE1(HTMLLegendElement, nsIDOMHTMLLegendElement)
+  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLLegendElement,
                                                nsGenericHTMLElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLLegendElement)
 
 
 // nsIDOMHTMLLegendElement
 
 
-NS_IMPL_ELEMENT_CLONE(nsHTMLLegendElement)
+NS_IMPL_ELEMENT_CLONE(HTMLLegendElement)
 
 
 NS_IMETHODIMP
-nsHTMLLegendElement::GetForm(nsIDOMHTMLFormElement** aForm)
+HTMLLegendElement::GetForm(nsIDOMHTMLFormElement** aForm)
 {
   Element* form = GetFormElement();
 
   return form ? CallQueryInterface(form, aForm) : NS_OK;
 }
 
 
-NS_IMPL_STRING_ATTR(nsHTMLLegendElement, Align, align)
+NS_IMPL_STRING_ATTR(HTMLLegendElement, Align, align)
 
 // this contains center, because IE4 does
 static const nsAttrValue::EnumTable kAlignTable[] = {
   { "left", NS_STYLE_TEXT_ALIGN_LEFT },
   { "right", NS_STYLE_TEXT_ALIGN_RIGHT },
   { "center", NS_STYLE_TEXT_ALIGN_CENTER },
   { "bottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM },
   { "top", NS_STYLE_VERTICAL_ALIGN_TOP },
   { 0 }
 };
 
 nsIContent*
-nsHTMLLegendElement::GetFieldSet()
+HTMLLegendElement::GetFieldSet()
 {
   nsIContent* parent = GetParent();
 
   if (parent && parent->IsHTML(nsGkAtoms::fieldset)) {
     return parent;
   }
 
   return nullptr;
 }
 
 bool
-nsHTMLLegendElement::ParseAttribute(int32_t aNamespaceID,
-                                    nsIAtom* aAttribute,
-                                    const nsAString& aValue,
-                                    nsAttrValue& aResult)
+HTMLLegendElement::ParseAttribute(int32_t aNamespaceID,
+                                  nsIAtom* aAttribute,
+                                  const nsAString& aValue,
+                                  nsAttrValue& aResult)
 {
   if (aAttribute == nsGkAtoms::align && aNamespaceID == kNameSpaceID_None) {
     return aResult.ParseEnumValue(aValue, kAlignTable, false);
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 nsChangeHint
-nsHTMLLegendElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
-                                            int32_t aModType) const
+HTMLLegendElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
+                                          int32_t aModType) const
 {
   nsChangeHint retval =
       nsGenericHTMLElement::GetAttributeChangeHint(aAttribute, aModType);
   if (aAttribute == nsGkAtoms::align) {
     NS_UpdateHint(retval, NS_STYLE_HINT_REFLOW);
   }
   return retval;
 }
 
 nsresult
-nsHTMLLegendElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
-                             nsIAtom* aPrefix, const nsAString& aValue,
-                             bool aNotify)
+HTMLLegendElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
+                           nsIAtom* aPrefix, const nsAString& aValue,
+                           bool aNotify)
 {
   return nsGenericHTMLElement::SetAttr(aNameSpaceID, aAttribute,
                                        aPrefix, aValue, aNotify);
 }
 nsresult
-nsHTMLLegendElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
-                               bool aNotify)
+HTMLLegendElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
+                             bool aNotify)
 {
   return nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify);
 }
 
 nsresult
-nsHTMLLegendElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                                nsIContent* aBindingParent,
-                                bool aCompileEventHandlers)
+HTMLLegendElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                              nsIContent* aBindingParent,
+                              bool aCompileEventHandlers)
 {
   return nsGenericHTMLElement::BindToTree(aDocument, aParent,
                                           aBindingParent,
                                           aCompileEventHandlers);
 }
 
 void
-nsHTMLLegendElement::UnbindFromTree(bool aDeep, bool aNullParent)
+HTMLLegendElement::UnbindFromTree(bool aDeep, bool aNullParent)
 {
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
 }
 
 void
-nsHTMLLegendElement::Focus(ErrorResult& aError)
+HTMLLegendElement::Focus(ErrorResult& aError)
 {
   nsIFrame* frame = GetPrimaryFrame();
   if (!frame) {
     return;
   }
 
   int32_t tabIndex;
   if (frame->IsFocusable(&tabIndex, false)) {
@@ -163,16 +158,34 @@ nsHTMLLegendElement::Focus(ErrorResult& 
 
   nsCOMPtr<nsIDOMElement> result;
   aError = fm->MoveFocus(nullptr, this, nsIFocusManager::MOVEFOCUS_FORWARD,
                          nsIFocusManager::FLAG_NOPARENTFRAME,
                          getter_AddRefs(result));
 }
 
 void
-nsHTMLLegendElement::PerformAccesskey(bool aKeyCausesActivation,
-                                      bool aIsTrustedEvent)
+HTMLLegendElement::PerformAccesskey(bool aKeyCausesActivation,
+                                    bool aIsTrustedEvent)
 {
   // just use the same behaviour as the focus method
-  mozilla::ErrorResult rv;
+  ErrorResult rv;
   Focus(rv);
 }
 
+already_AddRefed<nsHTMLFormElement>
+HTMLLegendElement::GetForm()
+{
+  Element* form = GetFormElement();
+  MOZ_ASSERT_IF(form, form->IsHTML(nsGkAtoms::form));
+  nsRefPtr<nsHTMLFormElement> ret = static_cast<nsHTMLFormElement*>(form);
+  return ret.forget();
+}
+
+JSObject*
+HTMLLegendElement::WrapNode(JSContext* aCx, JSObject* aScope,
+                            bool* aTriedToWrap)
+{
+  return HTMLLegendElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+}
+
+} // namespace dom
+} // namespace mozilla
rename from content/html/content/src/nsHTMLLegendElement.h
rename to content/html/content/src/HTMLLegendElement.h
--- a/content/html/content/src/nsHTMLLegendElement.h
+++ b/content/html/content/src/HTMLLegendElement.h
@@ -1,43 +1,48 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#ifndef nsHTMLLegendElement_h___
-#define nsHTMLLegendElement_h___
+
+#ifndef mozilla_dom_HTMLLegendElement_h
+#define mozilla_dom_HTMLLegendElement_h
 
 #include "nsIDOMHTMLLegendElement.h"
 #include "nsGenericHTMLElement.h"
+#include "nsHTMLFormElement.h"
 
-class nsHTMLLegendElement : public nsGenericHTMLElement,
-                            public nsIDOMHTMLLegendElement
+namespace mozilla {
+namespace dom {
+
+class HTMLLegendElement : public nsGenericHTMLElement,
+                          public nsIDOMHTMLLegendElement
 {
 public:
-  nsHTMLLegendElement(already_AddRefed<nsINodeInfo> aNodeInfo);
-  virtual ~nsHTMLLegendElement();
+  HTMLLegendElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+  virtual ~HTMLLegendElement();
 
-  NS_IMPL_FROMCONTENT_HTML_WITH_TAG(nsHTMLLegendElement, legend)
+  NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLLegendElement, legend)
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLLegendElement
   NS_DECL_NSIDOMHTMLLEGENDELEMENT
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
-  virtual void Focus(mozilla::ErrorResult& aError) MOZ_OVERRIDE;
+  virtual void Focus(ErrorResult& aError) MOZ_OVERRIDE;
 
   virtual void PerformAccesskey(bool aKeyCausesActivation,
                                 bool aIsTrustedEvent);
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers);
@@ -55,29 +60,54 @@ public:
     return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
   }
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
                            bool aNotify);
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify);
 
-  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+  virtual nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const;
 
-  mozilla::dom::Element *GetFormElement()
+  Element* GetFormElement()
   {
     nsCOMPtr<nsIFormControl> fieldsetControl = do_QueryInterface(GetFieldSet());
 
     return fieldsetControl ? fieldsetControl->GetFormElement() : nullptr;
   }
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual nsIDOMNode* AsDOMNode() { return this; }
+
+  /**
+   * WebIDL Interface
+   */
+
+  already_AddRefed<nsHTMLFormElement> GetForm();
+
+  // The XPCOM GetAlign is OK for us
+  void SetAlign(const nsAString& aAlign, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
+  }
+
+  nsINode* GetParentObject() {
+    Element* form = GetFormElement();
+    return form ? static_cast<nsINode*>(form)
+                : nsGenericHTMLElement::GetParentObject();
+  }
+
 protected:
+  virtual JSObject* WrapNode(JSContext* aCx, JSObject* aScope,
+                             bool* aTriedToWrap) MOZ_OVERRIDE;
+
   /**
    * Get the fieldset content element that contains this legend.
    * Returns null if there is no fieldset containing this legend.
    */
   nsIContent* GetFieldSet();
 };
 
-#endif /* nsHTMLLegendElement_h___ */
+} // namespace dom
+} // namespace mozilla
+
+#endif /* mozilla_dom_HTMLLegendElement_h */
rename from content/html/content/src/nsHTMLMenuElement.cpp
rename to content/html/content/src/HTMLMenuElement.cpp
--- a/content/html/content/src/nsHTMLMenuElement.cpp
+++ b/content/html/content/src/HTMLMenuElement.cpp
@@ -1,24 +1,25 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsHTMLMenuElement.h"
-#include "nsAttrValueInlines.h"
-#include "nsIDOMHTMLMenuItemElement.h"
+#include "HTMLMenuElement.h"
+#include "mozilla/dom/HTMLMenuElementBinding.h"
 #include "nsXULContextMenuBuilder.h"
-#include "nsGUIEvent.h"
 #include "nsEventDispatcher.h"
-#include "nsHTMLMenuItemElement.h"
-#include "nsContentUtils.h"
-#include "nsError.h"
+#include "HTMLMenuItemElement.h"
+#include "nsAttrValueInlines.h"
 
-using namespace mozilla::dom;
+NS_IMPL_NS_NEW_HTML_ELEMENT(Menu)
+DOMCI_NODE_DATA(HTMLMenuElement, mozilla::dom::HTMLMenuElement)
+
+namespace mozilla {
+namespace dom {
 
 enum MenuType
 {
   MENU_TYPE_CONTEXT = 1,
   MENU_TYPE_TOOLBAR,
   MENU_TYPE_LIST
 };
 
@@ -34,54 +35,52 @@ static const nsAttrValue::EnumTable* kMe
 
 enum SeparatorType
 {
   ST_TRUE_INIT = -1,
   ST_FALSE = 0,
   ST_TRUE = 1
 };
 
-NS_IMPL_NS_NEW_HTML_ELEMENT(Menu)
 
 
-nsHTMLMenuElement::nsHTMLMenuElement(already_AddRefed<nsINodeInfo> aNodeInfo)
+HTMLMenuElement::HTMLMenuElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo), mType(MENU_TYPE_LIST)
 {
+  SetIsDOMBinding();
 }
 
-nsHTMLMenuElement::~nsHTMLMenuElement()
+HTMLMenuElement::~HTMLMenuElement()
 {
 }
 
 
-NS_IMPL_ADDREF_INHERITED(nsHTMLMenuElement, Element)
-NS_IMPL_RELEASE_INHERITED(nsHTMLMenuElement, Element)
+NS_IMPL_ADDREF_INHERITED(HTMLMenuElement, Element)
+NS_IMPL_RELEASE_INHERITED(HTMLMenuElement, Element)
 
 
-DOMCI_NODE_DATA(HTMLMenuElement, nsHTMLMenuElement)
-
-// QueryInterface implementation for nsHTMLMenuElement
-NS_INTERFACE_TABLE_HEAD(nsHTMLMenuElement)
-  NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLMenuElement,
+// QueryInterface implementation for HTMLMenuElement
+NS_INTERFACE_TABLE_HEAD(HTMLMenuElement)
+  NS_HTML_CONTENT_INTERFACE_TABLE2(HTMLMenuElement,
                                    nsIDOMHTMLMenuElement,
                                    nsIHTMLMenu)
-  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLMenuElement,
+  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLMenuElement,
                                                nsGenericHTMLElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLMenuElement)
 
-NS_IMPL_ELEMENT_CLONE(nsHTMLMenuElement)
+NS_IMPL_ELEMENT_CLONE(HTMLMenuElement)
 
-NS_IMPL_BOOL_ATTR(nsHTMLMenuElement, Compact, compact)
-NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLMenuElement, Type, type,
+NS_IMPL_BOOL_ATTR(HTMLMenuElement, Compact, compact)
+NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLMenuElement, Type, type,
                                 kMenuDefaultType->tag)
-NS_IMPL_STRING_ATTR(nsHTMLMenuElement, Label, label)
+NS_IMPL_STRING_ATTR(HTMLMenuElement, Label, label)
 
 
 NS_IMETHODIMP
-nsHTMLMenuElement::SendShowEvent()
+HTMLMenuElement::SendShowEvent()
 {
   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR);
 
   nsCOMPtr<nsIDocument> document = GetCurrentDoc();
   if (!document) {
     return NS_ERROR_FAILURE;
   }
 
@@ -98,50 +97,60 @@ nsHTMLMenuElement::SendShowEvent()
   nsEventStatus status = nsEventStatus_eIgnore;
   nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this), presContext,
                               &event, nullptr, &status);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLMenuElement::CreateBuilder(nsIMenuBuilder** _retval)
+HTMLMenuElement::CreateBuilder(nsIMenuBuilder** _retval)
 {
   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR);
 
   *_retval = nullptr;
 
   if (mType == MENU_TYPE_CONTEXT) {
     NS_ADDREF(*_retval = new nsXULContextMenuBuilder());
   }
 
   return NS_OK;
 }
 
+already_AddRefed<nsIMenuBuilder>
+HTMLMenuElement::CreateBuilder()
+{
+  if (mType != MENU_TYPE_CONTEXT) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIMenuBuilder> ret = new nsXULContextMenuBuilder();
+  return ret.forget();
+}
 
 NS_IMETHODIMP
-nsHTMLMenuElement::Build(nsIMenuBuilder* aBuilder)
+HTMLMenuElement::Build(nsIMenuBuilder* aBuilder)
 {
   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR);
 
   if (!aBuilder) {
     return NS_OK;
   }
 
   BuildSubmenu(EmptyString(), this, aBuilder);
 
   return NS_OK;
 }
 
 
 bool
-nsHTMLMenuElement::ParseAttribute(int32_t aNamespaceID,
-                                  nsIAtom* aAttribute,
-                                  const nsAString& aValue,
-                                  nsAttrValue& aResult)
+HTMLMenuElement::ParseAttribute(int32_t aNamespaceID,
+                                nsIAtom* aAttribute,
+                                const nsAString& aValue,
+                                nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::type) {
     bool success = aResult.ParseEnumValue(aValue, kMenuTypeTable,
                                             false);
     if (success) {
       mType = aResult.GetEnumValue();
     } else {
       mType = kMenuDefaultType->value;
@@ -150,35 +159,35 @@ nsHTMLMenuElement::ParseAttribute(int32_
     return success;
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
-nsHTMLMenuElement::BuildSubmenu(const nsAString& aLabel,
-                                nsIContent* aContent,
-                                nsIMenuBuilder* aBuilder)
+HTMLMenuElement::BuildSubmenu(const nsAString& aLabel,
+                              nsIContent* aContent,
+                              nsIMenuBuilder* aBuilder)
 {
   aBuilder->OpenContainer(aLabel);
 
   int8_t separator = ST_TRUE_INIT;
   TraverseContent(aContent, aBuilder, separator);
 
   if (separator == ST_TRUE) {
     aBuilder->UndoAddSeparator();
   }
 
   aBuilder->CloseContainer();
 }
 
 // static
 bool
-nsHTMLMenuElement::CanLoadIcon(nsIContent* aContent, const nsAString& aIcon)
+HTMLMenuElement::CanLoadIcon(nsIContent* aContent, const nsAString& aIcon)
 {
   if (aIcon.IsEmpty()) {
     return false;
   }
 
   nsIDocument* doc = aContent->OwnerDoc();
 
   nsCOMPtr<nsIURI> baseURI = aContent->GetBaseURI();
@@ -190,33 +199,32 @@ nsHTMLMenuElement::CanLoadIcon(nsIConten
     return false;
   }
 
   return nsContentUtils::CanLoadImage(uri, aContent, doc,
                                       aContent->NodePrincipal());
 }
 
 void
-nsHTMLMenuElement::TraverseContent(nsIContent* aContent,
-                                   nsIMenuBuilder* aBuilder,
-                                   int8_t& aSeparator)
+HTMLMenuElement::TraverseContent(nsIContent* aContent,
+                                 nsIMenuBuilder* aBuilder,
+                                 int8_t& aSeparator)
 {
   nsCOMPtr<nsIContent> child;
   for (child = aContent->GetFirstChild(); child;
        child = child->GetNextSibling()) {
     nsGenericHTMLElement* element = nsGenericHTMLElement::FromContent(child);
     if (!element) {
       continue;
     }
 
     nsIAtom* tag = child->Tag();
 
     if (tag == nsGkAtoms::menuitem) {
-      nsHTMLMenuItemElement* menuitem =
-        nsHTMLMenuItemElement::FromContent(child);
+      HTMLMenuItemElement* menuitem = HTMLMenuItemElement::FromContent(child);
 
       if (menuitem->IsHidden()) {
         continue;
       }
 
       nsAutoString label;
       menuitem->GetLabel(label);
       if (label.IsEmpty()) {
@@ -244,17 +252,27 @@ nsHTMLMenuElement::TraverseContent(nsICo
 
         AddSeparator(aBuilder, aSeparator);
       }
     }
   }
 }
 
 inline void
-nsHTMLMenuElement::AddSeparator(nsIMenuBuilder* aBuilder, int8_t& aSeparator)
+HTMLMenuElement::AddSeparator(nsIMenuBuilder* aBuilder, int8_t& aSeparator)
 {
   if (aSeparator) {
     return;
   }
  
   aBuilder->AddSeparator();
   aSeparator = ST_TRUE;
 }
+
+JSObject*
+HTMLMenuElement::WrapNode(JSContext* aCx, JSObject* aScope,
+                          bool* aTriedToWrap)
+{
+  return HTMLMenuElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+}
+
+} // namespace dom
+} // namespace mozilla
rename from content/html/content/src/nsHTMLMenuElement.h
rename to content/html/content/src/HTMLMenuElement.h
--- a/content/html/content/src/nsHTMLMenuElement.h
+++ b/content/html/content/src/HTMLMenuElement.h
@@ -1,26 +1,32 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#ifndef mozilla_dom_HTMLMenuElement_h
+#define mozilla_dom_HTMLMenuElement_h
+
 #include "nsIDOMHTMLMenuElement.h"
 #include "nsIHTMLMenu.h"
 #include "nsGenericHTMLElement.h"
 
-class nsHTMLMenuElement : public nsGenericHTMLElement,
-                          public nsIDOMHTMLMenuElement,
-                          public nsIHTMLMenu
+namespace mozilla {
+namespace dom {
+
+class HTMLMenuElement : public nsGenericHTMLElement,
+                        public nsIDOMHTMLMenuElement,
+                        public nsIHTMLMenu
 {
 public:
-  nsHTMLMenuElement(already_AddRefed<nsINodeInfo> aNodeInfo);
-  virtual ~nsHTMLMenuElement();
+  HTMLMenuElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+  virtual ~HTMLMenuElement();
 
-  NS_IMPL_FROMCONTENT_HTML_WITH_TAG(nsHTMLMenuElement, menu)
+  NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLMenuElement, menu)
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
@@ -43,23 +49,62 @@ public:
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual nsIDOMNode* AsDOMNode() { return this; }
 
   uint8_t GetType() const { return mType; }
 
+  // WebIDL
+
+  // The XPCOM GetType is OK for us
+  void SetType(const nsAString& aType, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::type, aType, aError);
+  }
+
+  // The XPCOM GetLabel is OK for us
+  void SetLabel(const nsAString& aLabel, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::label, aLabel, aError);
+  }
+
+  bool Compact() const
+  {
+    return GetBoolAttr(nsGkAtoms::compact);
+  }
+  void SetCompact(bool aCompact, ErrorResult& aError)
+  {
+    SetHTMLBoolAttr(nsGkAtoms::compact, aCompact, aError);
+  }
+
+  // The XPCOM SendShowEvent is OK for us
+
+  already_AddRefed<nsIMenuBuilder> CreateBuilder();
+
+  // The XPCOM Build is OK for us
+
+protected:
+  virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope,
+                             bool *aTriedToWrap) MOZ_OVERRIDE;
+
+
 protected:
   static bool CanLoadIcon(nsIContent* aContent, const nsAString& aIcon);
 
   void BuildSubmenu(const nsAString& aLabel,
                     nsIContent* aContent,
                     nsIMenuBuilder* aBuilder);
 
   void TraverseContent(nsIContent* aContent,
                        nsIMenuBuilder* aBuilder,
                        int8_t& aSeparator);
 
   void AddSeparator(nsIMenuBuilder* aBuilder, int8_t& aSeparator);
 
   uint8_t mType;
 };
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_HTMLMenuElement_h
rename from content/html/content/src/nsHTMLMenuItemElement.cpp
rename to content/html/content/src/HTMLMenuItemElement.cpp
--- a/content/html/content/src/nsHTMLMenuItemElement.cpp
+++ b/content/html/content/src/HTMLMenuItemElement.cpp
@@ -1,20 +1,24 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsGUIEvent.h"
+#include "HTMLMenuItemElement.h"
+#include "mozilla/dom/HTMLMenuItemElementBinding.h"
 #include "nsEventDispatcher.h"
-#include "nsHTMLMenuItemElement.h"
 #include "nsAttrValueInlines.h"
-#include "nsContentUtils.h"
+
 
-using namespace mozilla::dom;
+NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(MenuItem)
+DOMCI_NODE_DATA(HTMLMenuItemElement, mozilla::dom::HTMLMenuItemElement)
+
+namespace mozilla {
+namespace dom {
 
 // First bits are needed for the menuitem type.
 #define NS_CHECKED_IS_TOGGLED (1 << 2)
 #define NS_ORIGINAL_CHECKED_VALUE (1 << 3)
 #define NS_MENUITEM_TYPE(bits) ((bits) & ~( \
   NS_CHECKED_IS_TOGGLED | NS_ORIGINAL_CHECKED_VALUE))
 
 enum CmdType                                                                 
@@ -41,102 +45,102 @@ public:
   Visitor() { }
   virtual ~Visitor() { }
 
   /**
    * Visit a node in the tree. This is meant to be called on all radios in a
    * group, sequentially. If the method returns false then the iteration is
    * stopped.
    */
-  virtual bool Visit(nsHTMLMenuItemElement* aMenuItem) = 0;
+  virtual bool Visit(HTMLMenuItemElement* aMenuItem) = 0;
 };
 
 // Find the selected radio, see GetSelectedRadio().
 class GetCheckedVisitor : public Visitor
 {
 public:
-  GetCheckedVisitor(nsHTMLMenuItemElement** aResult)
+  GetCheckedVisitor(HTMLMenuItemElement** aResult)
     : mResult(aResult)
     { }
-  virtual bool Visit(nsHTMLMenuItemElement* aMenuItem)
+  virtual bool Visit(HTMLMenuItemElement* aMenuItem)
   {
     if (aMenuItem->IsChecked()) {
       *mResult = aMenuItem;
       return false;
     }
     return true;
   }
 protected:
-  nsHTMLMenuItemElement** mResult;
+  HTMLMenuItemElement** mResult;
 };
 
 // Deselect all radios except the one passed to the constructor.
 class ClearCheckedVisitor : public Visitor
 {
 public:
-  ClearCheckedVisitor(nsHTMLMenuItemElement* aExcludeMenuItem)
+  ClearCheckedVisitor(HTMLMenuItemElement* aExcludeMenuItem)
     : mExcludeMenuItem(aExcludeMenuItem)
     { }
-  virtual bool Visit(nsHTMLMenuItemElement* aMenuItem)
+  virtual bool Visit(HTMLMenuItemElement* aMenuItem)
   {
     if (aMenuItem != mExcludeMenuItem && aMenuItem->IsChecked()) {
       aMenuItem->ClearChecked();
     }
     return true;
   }
 protected:
-  nsHTMLMenuItemElement* mExcludeMenuItem;
+  HTMLMenuItemElement* mExcludeMenuItem;
 };
 
 // Get current value of the checked dirty flag. The same value is stored on all
 // radios in the group, so we need to check only the first one.
 class GetCheckedDirtyVisitor : public Visitor
 {
 public:
   GetCheckedDirtyVisitor(bool* aCheckedDirty,
-                         nsHTMLMenuItemElement* aExcludeMenuItem)
+                         HTMLMenuItemElement* aExcludeMenuItem)
     : mCheckedDirty(aCheckedDirty),
       mExcludeMenuItem(aExcludeMenuItem)
     { }
-  virtual bool Visit(nsHTMLMenuItemElement* aMenuItem)
+  virtual bool Visit(HTMLMenuItemElement* aMenuItem)
   {
     if (aMenuItem == mExcludeMenuItem) {
       return true;
     }
     *mCheckedDirty = aMenuItem->IsCheckedDirty();
     return false;
   }
 protected:
   bool* mCheckedDirty;
-  nsHTMLMenuItemElement* mExcludeMenuItem;
+  HTMLMenuItemElement* mExcludeMenuItem;
 };
 
 // Set checked dirty to true on all radios in the group.
 class SetCheckedDirtyVisitor : public Visitor
 {
 public:
   SetCheckedDirtyVisitor()
     { }
-  virtual bool Visit(nsHTMLMenuItemElement* aMenuItem)
+  virtual bool Visit(HTMLMenuItemElement* aMenuItem)
   {
     aMenuItem->SetCheckedDirty();
     return true;
   }
 };
 
 // A helper visitor that is used to combine two operations (visitors) to avoid
 // iterating over radios twice.
 class CombinedVisitor : public Visitor
 {
 public:
   CombinedVisitor(Visitor* aVisitor1, Visitor* aVisitor2)
     : mVisitor1(aVisitor1), mVisitor2(aVisitor2),
       mContinue1(true), mContinue2(true)
     { }
-  virtual bool Visit(nsHTMLMenuItemElement* aMenuItem)
+  virtual bool Visit(HTMLMenuItemElement* aMenuItem)
   {
     if (mContinue1) {
       mContinue1 = mVisitor1->Visit(aMenuItem);
     }
     if (mContinue2) {
       mContinue2 = mVisitor2->Visit(aMenuItem);
     }
     return mContinue1 || mContinue2;
@@ -144,59 +148,56 @@ public:
 protected:
   Visitor* mVisitor1;
   Visitor* mVisitor2;
   bool mContinue1;
   bool mContinue2;
 };
 
 
-NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(MenuItem)
-
-nsHTMLMenuItemElement::nsHTMLMenuItemElement(
+HTMLMenuItemElement::HTMLMenuItemElement(
   already_AddRefed<nsINodeInfo> aNodeInfo, FromParser aFromParser)
   : nsGenericHTMLElement(aNodeInfo),
     mType(kMenuItemDefaultType->value),
     mParserCreating(false),
     mShouldInitChecked(false),
     mCheckedDirty(false),
     mChecked(false)
 {
+  SetIsDOMBinding();
   mParserCreating = aFromParser;
 }
 
-nsHTMLMenuItemElement::~nsHTMLMenuItemElement()
+HTMLMenuItemElement::~HTMLMenuItemElement()
 {
 }
 
 
-NS_IMPL_ADDREF_INHERITED(nsHTMLMenuItemElement, Element)
-NS_IMPL_RELEASE_INHERITED(nsHTMLMenuItemElement, Element)
+NS_IMPL_ADDREF_INHERITED(HTMLMenuItemElement, Element)
+NS_IMPL_RELEASE_INHERITED(HTMLMenuItemElement, Element)
 
 
-DOMCI_NODE_DATA(HTMLMenuItemElement, nsHTMLMenuItemElement)
-
-// QueryInterface implementation for nsHTMLMenuItemElement
-NS_INTERFACE_TABLE_HEAD(nsHTMLMenuItemElement)
-  NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLMenuItemElement,
+// QueryInterface implementation for HTMLMenuItemElement
+NS_INTERFACE_TABLE_HEAD(HTMLMenuItemElement)
+  NS_HTML_CONTENT_INTERFACE_TABLE2(HTMLMenuItemElement,
                                    nsIDOMHTMLCommandElement,
                                    nsIDOMHTMLMenuItemElement)
-  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLMenuItemElement,
+  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLMenuItemElement,
                                                nsGenericHTMLElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLMenuItemElement)
 
-//NS_IMPL_ELEMENT_CLONE(nsHTMLMenuItemElement)
+//NS_IMPL_ELEMENT_CLONE(HTMLMenuItemElement)
 nsresult
-nsHTMLMenuItemElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
+HTMLMenuItemElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
 {
   *aResult = nullptr;
   nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
-  nsRefPtr<nsHTMLMenuItemElement> it =
-    new nsHTMLMenuItemElement(ni.forget(), NOT_FROM_PARSER);
-  nsresult rv = const_cast<nsHTMLMenuItemElement*>(this)->CopyInnerTo(it);
+  nsRefPtr<HTMLMenuItemElement> it =
+    new HTMLMenuItemElement(ni.forget(), NOT_FROM_PARSER);
+  nsresult rv = const_cast<HTMLMenuItemElement*>(this)->CopyInnerTo(it);
   if (NS_SUCCEEDED(rv)) {
     switch (mType) {
       case CMD_TYPE_CHECKBOX:
       case CMD_TYPE_RADIO:
         if (mCheckedDirty) {
           // We no longer have our original checked state.  Set our
           // checked state on the clone.
           it->mCheckedDirty = true;
@@ -207,35 +208,35 @@ nsHTMLMenuItemElement::Clone(nsINodeInfo
 
     it.forget(aResult);
   }
 
   return rv;
 }
 
 
-NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLMenuItemElement, Type, type,
+NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLMenuItemElement, Type, type,
                                 kMenuItemDefaultType->tag)
 // GetText returns a whitespace compressed .textContent value.
-NS_IMPL_STRING_ATTR_WITH_FALLBACK(nsHTMLMenuItemElement, Label, label, GetText)
-NS_IMPL_URI_ATTR(nsHTMLMenuItemElement, Icon, icon)
-NS_IMPL_BOOL_ATTR(nsHTMLMenuItemElement, Disabled, disabled)
-NS_IMPL_BOOL_ATTR(nsHTMLMenuItemElement, DefaultChecked, checked)
-//NS_IMPL_BOOL_ATTR(nsHTMLMenuItemElement, Checked, checked)
-NS_IMPL_STRING_ATTR(nsHTMLMenuItemElement, Radiogroup, radiogroup)
+NS_IMPL_STRING_ATTR_WITH_FALLBACK(HTMLMenuItemElement, Label, label, GetText)
+NS_IMPL_URI_ATTR(HTMLMenuItemElement, Icon, icon)
+NS_IMPL_BOOL_ATTR(HTMLMenuItemElement, Disabled, disabled)
+NS_IMPL_BOOL_ATTR(HTMLMenuItemElement, DefaultChecked, checked)
+//NS_IMPL_BOOL_ATTR(HTMLMenuItemElement, Checked, checked)
+NS_IMPL_STRING_ATTR(HTMLMenuItemElement, Radiogroup, radiogroup)
 
 NS_IMETHODIMP
-nsHTMLMenuItemElement::GetChecked(bool* aChecked)
+HTMLMenuItemElement::GetChecked(bool* aChecked)
 {
   *aChecked = mChecked;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLMenuItemElement::SetChecked(bool aChecked)
+HTMLMenuItemElement::SetChecked(bool aChecked)
 {
   bool checkedChanged = mChecked != aChecked;
 
   mChecked = aChecked;
 
   if (mType == CMD_TYPE_RADIO) {
     if (checkedChanged) {
       if (mCheckedDirty) {
@@ -254,17 +255,17 @@ nsHTMLMenuItemElement::SetChecked(bool a
   } else {
     mCheckedDirty = true;
   }
 
   return NS_OK;
 }
 
 nsresult
-nsHTMLMenuItemElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
+HTMLMenuItemElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   if (aVisitor.mEvent->message == NS_MOUSE_CLICK) {
 
     bool originalCheckedValue = false;
     switch (mType) {
       case CMD_TYPE_CHECKBOX:
         originalCheckedValue = mChecked;
         SetChecked(!originalCheckedValue);
@@ -289,17 +290,17 @@ nsHTMLMenuItemElement::PreHandleEvent(ns
     // We must cache type because mType may change during JS event.
     aVisitor.mItemFlags |= mType;
   }
 
   return nsGenericHTMLElement::PreHandleEvent(aVisitor);
 }
 
 nsresult
-nsHTMLMenuItemElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
+HTMLMenuItemElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
 {
   // Check to see if the event was cancelled.
   if (aVisitor.mEvent->message == NS_MOUSE_CLICK &&
       aVisitor.mItemFlags & NS_CHECKED_IS_TOGGLED &&
       aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault) {
     bool originalCheckedValue =
       !!(aVisitor.mItemFlags & NS_ORIGINAL_CHECKED_VALUE);
     uint8_t oldType = NS_MENUITEM_TYPE(aVisitor.mItemFlags);
@@ -315,36 +316,36 @@ nsHTMLMenuItemElement::PostHandleEvent(n
       SetChecked(originalCheckedValue);
     }
   }
 
   return NS_OK;
 }
 
 nsresult
-nsHTMLMenuItemElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                                  nsIContent* aBindingParent,
-                                  bool aCompileEventHandlers)
+HTMLMenuItemElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                                nsIContent* aBindingParent,
+                                bool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
                                                  aBindingParent,
                                                  aCompileEventHandlers);
 
   if (NS_SUCCEEDED(rv) && aDocument && mType == CMD_TYPE_RADIO) {
     AddedToRadioGroup();
   }
 
   return rv;
 }
 
 bool
-nsHTMLMenuItemElement::ParseAttribute(int32_t aNamespaceID,
-                                      nsIAtom* aAttribute,
-                                      const nsAString& aValue,
-                                      nsAttrValue& aResult)
+HTMLMenuItemElement::ParseAttribute(int32_t aNamespaceID,
+                                    nsIAtom* aAttribute,
+                                    const nsAString& aValue,
+                                    nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::type) {
       bool success = aResult.ParseEnumValue(aValue, kMenuItemTypeTable,
                                               false);
       if (success) {
         mType = aResult.GetEnumValue();
       } else {
@@ -360,39 +361,39 @@ nsHTMLMenuItemElement::ParseAttribute(in
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
-nsHTMLMenuItemElement::DoneCreatingElement()
+HTMLMenuItemElement::DoneCreatingElement()
 {
   mParserCreating = false;
 
   if (mShouldInitChecked) {
     InitChecked();
     mShouldInitChecked = false;
   }
 }
 
 void
-nsHTMLMenuItemElement::GetText(nsAString& aText)
+HTMLMenuItemElement::GetText(nsAString& aText)
 {
   nsAutoString text;
   nsContentUtils::GetNodeTextContent(this, false, text);
 
   text.CompressWhitespace(true, true);
   aText = text;
 }
 
 nsresult
-nsHTMLMenuItemElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
-                                    const nsAttrValue* aValue, bool aNotify)
+HTMLMenuItemElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+                                  const nsAttrValue* aValue, bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     if ((aName == nsGkAtoms::radiogroup || aName == nsGkAtoms::type) &&
         mType == CMD_TYPE_RADIO &&
         !mParserCreating) {
       if (IsInDoc() && GetParent()) {
         AddedToRadioGroup();
       }
@@ -410,32 +411,32 @@ nsHTMLMenuItemElement::AfterSetAttr(int3
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
                                             aNotify);
 }
 
 void
-nsHTMLMenuItemElement::WalkRadioGroup(Visitor* aVisitor)
+HTMLMenuItemElement::WalkRadioGroup(Visitor* aVisitor)
 {
   nsIContent* parent = GetParent();
   if (!parent) {
     aVisitor->Visit(this);
     return;
   }
 
   nsAttrInfo info1(GetAttrInfo(kNameSpaceID_None,
                                nsGkAtoms::radiogroup));
   bool info1Empty = !info1.mValue || info1.mValue->IsEmptyString();
 
   for (nsIContent* cur = parent->GetFirstChild();
        cur;
        cur = cur->GetNextSibling()) {
-    nsHTMLMenuItemElement* menuitem = nsHTMLMenuItemElement::FromContent(cur);
+    HTMLMenuItemElement* menuitem = HTMLMenuItemElement::FromContent(cur);
 
     if (!menuitem || menuitem->GetType() != CMD_TYPE_RADIO) {
       continue;
     }
 
     nsAttrInfo info2(menuitem->GetAttrInfo(kNameSpaceID_None,
                                            nsGkAtoms::radiogroup));
     bool info2Empty = !info2.mValue || info2.mValue->IsEmptyString();
@@ -446,46 +447,56 @@ nsHTMLMenuItemElement::WalkRadioGroup(Vi
     }
 
     if (!aVisitor->Visit(menuitem)) {
       break;
     }
   }
 }
 
-nsHTMLMenuItemElement*
-nsHTMLMenuItemElement::GetSelectedRadio()
+HTMLMenuItemElement*
+HTMLMenuItemElement::GetSelectedRadio()
 {
-  nsHTMLMenuItemElement* result = nullptr;
+  HTMLMenuItemElement* result = nullptr;
 
   GetCheckedVisitor visitor(&result);
   WalkRadioGroup(&visitor);
 
   return result;
 }
 
 void
-nsHTMLMenuItemElement::AddedToRadioGroup()
+HTMLMenuItemElement::AddedToRadioGroup()
 {
   bool checkedDirty = mCheckedDirty;
   if (mChecked) {
     ClearCheckedVisitor visitor1(this);
     GetCheckedDirtyVisitor visitor2(&checkedDirty, this);
     CombinedVisitor visitor(&visitor1, &visitor2);
     WalkRadioGroup(&visitor);
   } else {
     GetCheckedDirtyVisitor visitor(&checkedDirty, this);
     WalkRadioGroup(&visitor);
   }
   mCheckedDirty = checkedDirty;
 }
 
 void
-nsHTMLMenuItemElement::InitChecked()
+HTMLMenuItemElement::InitChecked()
 {
   bool defaultChecked;
   GetDefaultChecked(&defaultChecked);
   mChecked = defaultChecked;
   if (mType == CMD_TYPE_RADIO) {
     ClearCheckedVisitor visitor(this);
     WalkRadioGroup(&visitor);
   }
 }
+
+JSObject*
+HTMLMenuItemElement::WrapNode(JSContext* aCx, JSObject* aScope,
+                              bool* aTriedToWrap)
+{
+  return HTMLMenuItemElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+}
+
+} // namespace dom
+} // namespace mozilla
rename from content/html/content/src/nsHTMLMenuItemElement.h
rename to content/html/content/src/HTMLMenuItemElement.h
--- a/content/html/content/src/nsHTMLMenuItemElement.h
+++ b/content/html/content/src/HTMLMenuItemElement.h
@@ -1,29 +1,35 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#ifndef mozilla_dom_HTMLMenuItemElement_h
+#define mozilla_dom_HTMLMenuItemElement_h
+
 #include "nsIDOMHTMLMenuItemElement.h"
 #include "nsGenericHTMLElement.h"
 
+namespace mozilla {
+namespace dom {
+
 class Visitor;
 
-class nsHTMLMenuItemElement : public nsGenericHTMLElement,
-                              public nsIDOMHTMLMenuItemElement
+class HTMLMenuItemElement : public nsGenericHTMLElement,
+                            public nsIDOMHTMLMenuItemElement
 {
 public:
   using mozilla::dom::Element::GetText;
 
-  nsHTMLMenuItemElement(already_AddRefed<nsINodeInfo> aNodeInfo,
-                        mozilla::dom::FromParser aFromParser);
-  virtual ~nsHTMLMenuItemElement();
+  HTMLMenuItemElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+                      mozilla::dom::FromParser aFromParser);
+  virtual ~HTMLMenuItemElement();
 
-  NS_IMPL_FROMCONTENT_HTML_WITH_TAG(nsHTMLMenuItemElement, menuitem)
+  NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLMenuItemElement, menuitem)
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
@@ -63,23 +69,81 @@ public:
   /**
    * Syntax sugar to make it easier to check for checked and checked dirty
    */
   bool IsChecked() const { return mChecked; }
   bool IsCheckedDirty() const { return mCheckedDirty; }
 
   void GetText(nsAString& aText);
 
+  // WebIDL
+
+  // The XPCOM GetType is OK for us
+  void SetType(const nsAString& aType, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::type, aType, aError);
+  }
+
+  // The XPCOM GetLabel is OK for us
+  void SetLabel(const nsAString& aLabel, ErrorResult& aError)
+  {
+    SetAttrHelper(nsGkAtoms::label, aLabel);
+  }
+
+  // The XPCOM GetIcon is OK for us
+  void SetIcon(const nsAString& aIcon, ErrorResult& aError)
+  {
+    SetAttrHelper(nsGkAtoms::icon, aIcon);
+  }
+
+  bool Disabled() const
+  {
+    return GetBoolAttr(nsGkAtoms::disabled);
+  }
+  void SetDisabled(bool aDisabled, ErrorResult& aError)
+  {
+    SetHTMLBoolAttr(nsGkAtoms::disabled, aDisabled, aError);
+  }
+
+  bool Checked() const
+  {
+    return mChecked;
+  }
+  void SetChecked(bool aChecked, ErrorResult& aError)
+  {
+    aError = SetChecked(aChecked);
+  }
+
+  // The XPCOM GetRadiogroup is OK for us
+  void SetRadiogroup(const nsAString& aRadiogroup, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::radiogroup, aRadiogroup, aError);
+  }
+
+  bool DefaultChecked() const
+  {
+    return GetBoolAttr(nsGkAtoms::checked);
+  }
+  void SetDefaultChecked(bool aDefault, ErrorResult& aError)
+  {
+    SetHTMLBoolAttr(nsGkAtoms::checked, aDefault, aError);
+  }
+
+protected:
+  virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope,
+                             bool *aTriedToWrap) MOZ_OVERRIDE;
+
+
 protected:
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
                                 const nsAttrValue* aValue, bool aNotify);
 
   void WalkRadioGroup(Visitor* aVisitor);
 
-  nsHTMLMenuItemElement* GetSelectedRadio();
+  HTMLMenuItemElement* GetSelectedRadio();
 
   void AddedToRadioGroup();
 
   void InitChecked();
 
   friend class ClearCheckedVisitor;
   friend class SetCheckedDirtyVisitor;
 
@@ -88,8 +152,13 @@ protected:
 
 private:
   uint8_t mType : 2;
   bool mParserCreating : 1;
   bool mShouldInitChecked : 1;
   bool mCheckedDirty : 1;
   bool mChecked : 1;
 };
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_HTMLMenuItemElement_h
--- a/content/html/content/src/HTMLOptGroupElement.cpp
+++ b/content/html/content/src/HTMLOptGroupElement.cpp
@@ -69,17 +69,17 @@ HTMLOptGroupElement::PreHandleEvent(nsEv
   // Do not process any DOM events if the element is disabled
   // XXXsmaug This is not the right thing to do. But what is?
   if (HasAttr(kNameSpaceID_None, nsGkAtoms::disabled)) {
     return NS_OK;
   }
 
   nsIFrame* frame = GetPrimaryFrame();
   if (frame) {
-    const nsStyleUserInterface* uiStyle = frame->GetStyleUserInterface();
+    const nsStyleUserInterface* uiStyle = frame->StyleUserInterface();
     if (uiStyle->mUserInput == NS_STYLE_USER_INPUT_NONE ||
         uiStyle->mUserInput == NS_STYLE_USER_INPUT_DISABLED) {
       return NS_OK;
     }
   }
 
   return nsGenericHTMLElement::PreHandleEvent(aVisitor);
 }
rename from content/html/content/src/nsHTMLOptionElement.cpp
rename to content/html/content/src/HTMLOptionElement.cpp
--- a/content/html/content/src/nsHTMLOptionElement.cpp
+++ b/content/html/content/src/HTMLOptionElement.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 sw=2 et tw=78: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsHTMLOptionElement.h"
+#include "mozilla/dom/HTMLOptionElement.h"
+#include "mozilla/dom/HTMLOptionElementBinding.h"
 #include "nsHTMLSelectElement.h"
 #include "nsIDOMHTMLOptGroupElement.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIDOMEventTarget.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsIFormControl.h"
 #include "nsIForm.h"
@@ -22,120 +23,123 @@
 #include "nsIDocument.h"
 #include "nsIDOMHTMLSelectElement.h"
 #include "nsNodeInfoManager.h"
 #include "nsCOMPtr.h"
 #include "nsEventStates.h"
 #include "nsContentCreatorFunctions.h"
 #include "mozAutoDocUpdate.h"
 
-using namespace mozilla::dom;
-
 /**
  * Implementation of &lt;option&gt;
  */
 
 nsGenericHTMLElement*
 NS_NewHTMLOptionElement(already_AddRefed<nsINodeInfo> aNodeInfo,
-                        FromParser aFromParser)
+                        mozilla::dom::FromParser aFromParser)
 {
   /*
-   * nsHTMLOptionElement's will be created without a nsINodeInfo passed in
+   * HTMLOptionElement's will be created without a nsINodeInfo passed in
    * if someone says "var opt = new Option();" in JavaScript, in a case like
    * that we request the nsINodeInfo from the document's nodeinfo list.
    */
   nsCOMPtr<nsINodeInfo> nodeInfo(aNodeInfo);
   if (!nodeInfo) {
     nsCOMPtr<nsIDocument> doc =
       do_QueryInterface(nsContentUtils::GetDocumentFromCaller());
     NS_ENSURE_TRUE(doc, nullptr);
 
     nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::option, nullptr,
                                                    kNameSpaceID_XHTML,
                                                    nsIDOMNode::ELEMENT_NODE);
     NS_ENSURE_TRUE(nodeInfo, nullptr);
   }
 
-  return new nsHTMLOptionElement(nodeInfo.forget());
+  return new mozilla::dom::HTMLOptionElement(nodeInfo.forget());
 }
 
-nsHTMLOptionElement::nsHTMLOptionElement(already_AddRefed<nsINodeInfo> aNodeInfo)
+DOMCI_NODE_DATA(HTMLOptionElement, mozilla::dom::HTMLOptionElement)
+
+namespace mozilla {
+namespace dom {
+
+HTMLOptionElement::HTMLOptionElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo),
     mSelectedChanged(false),
     mIsSelected(false),
     mIsInSetDefaultSelected(false)
 {
+  SetIsDOMBinding();
+
   // We start off enabled
   AddStatesSilently(NS_EVENT_STATE_ENABLED);
 }
 
-nsHTMLOptionElement::~nsHTMLOptionElement()
+HTMLOptionElement::~HTMLOptionElement()
 {
 }
 
 // ISupports
 
 
-NS_IMPL_ADDREF_INHERITED(nsHTMLOptionElement, Element)
-NS_IMPL_RELEASE_INHERITED(nsHTMLOptionElement, Element)
+NS_IMPL_ADDREF_INHERITED(HTMLOptionElement, Element)
+NS_IMPL_RELEASE_INHERITED(HTMLOptionElement, Element)
 
 
-DOMCI_NODE_DATA(HTMLOptionElement, nsHTMLOptionElement)
-
-// QueryInterface implementation for nsHTMLOptionElement
-NS_INTERFACE_TABLE_HEAD(nsHTMLOptionElement)
-  NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLOptionElement,
+// QueryInterface implementation for HTMLOptionElement
+NS_INTERFACE_TABLE_HEAD(HTMLOptionElement)
+  NS_HTML_CONTENT_INTERFACE_TABLE2(HTMLOptionElement,
                                    nsIDOMHTMLOptionElement,
                                    nsIJSNativeInitializer)
-  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLOptionElement,
+  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLOptionElement,
                                                nsGenericHTMLElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLOptionElement)
 
 
-NS_IMPL_ELEMENT_CLONE(nsHTMLOptionElement)
+NS_IMPL_ELEMENT_CLONE(HTMLOptionElement)
 
 
 NS_IMETHODIMP
-nsHTMLOptionElement::GetForm(nsIDOMHTMLFormElement** aForm)
+HTMLOptionElement::GetForm(nsIDOMHTMLFormElement** aForm)
 {
   NS_ENSURE_ARG_POINTER(aForm);
-  *aForm = nullptr;
-
-  nsHTMLSelectElement* selectControl = GetSelect();
-
-  if (selectControl) {
-    selectControl->GetForm(aForm);
-  }
-
+  *aForm = GetForm();
   return NS_OK;
 }
 
+nsHTMLFormElement*
+HTMLOptionElement::GetForm()
+{
+  nsHTMLSelectElement* selectControl = GetSelect();
+  return selectControl ? selectControl->GetForm() : nullptr;
+}
+
 void
-nsHTMLOptionElement::SetSelectedInternal(bool aValue, bool aNotify)
+HTMLOptionElement::SetSelectedInternal(bool aValue, bool aNotify)
 {
   mSelectedChanged = true;
   mIsSelected = aValue;
 
   // When mIsInSetDefaultSelected is true, the state change will be handled by
   // SetAttr/UnsetAttr.
   if (!mIsInSetDefaultSelected) {
     UpdateState(aNotify);
   }
 }
 
-NS_IMETHODIMP 
-nsHTMLOptionElement::GetSelected(bool* aValue)
+NS_IMETHODIMP
+HTMLOptionElement::GetSelected(bool* aValue)
 {
   NS_ENSURE_ARG_POINTER(aValue);
   *aValue = Selected();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLOptionElement::SetSelected(bool aValue)
+HTMLOptionElement::SetSelected(bool aValue)
 {
   // Note: The select content obj maintains all the PresState
   // so defer to it to get the answer
   nsHTMLSelectElement* selectInt = GetSelect();
   if (selectInt) {
     int32_t index;
     GetIndex(&index);
     // This should end up calling SetSelectedInternal
@@ -145,24 +149,24 @@ nsHTMLOptionElement::SetSelected(bool aV
   } else {
     SetSelectedInternal(aValue, true);
     return NS_OK;
   }
 
   return NS_OK;
 }
 
-NS_IMPL_BOOL_ATTR(nsHTMLOptionElement, DefaultSelected, selected)
+NS_IMPL_BOOL_ATTR(HTMLOptionElement, DefaultSelected, selected)
 // GetText returns a whitespace compressed .textContent value.
-NS_IMPL_STRING_ATTR_WITH_FALLBACK(nsHTMLOptionElement, Label, label, GetText)
-NS_IMPL_STRING_ATTR_WITH_FALLBACK(nsHTMLOptionElement, Value, value, GetText)
-NS_IMPL_BOOL_ATTR(nsHTMLOptionElement, Disabled, disabled)
+NS_IMPL_STRING_ATTR_WITH_FALLBACK(HTMLOptionElement, Label, label, GetText)
+NS_IMPL_STRING_ATTR_WITH_FALLBACK(HTMLOptionElement, Value, value, GetText)
+NS_IMPL_BOOL_ATTR(HTMLOptionElement, Disabled, disabled)
 
 NS_IMETHODIMP
-nsHTMLOptionElement::GetIndex(int32_t* aIndex)
+HTMLOptionElement::GetIndex(int32_t* aIndex)
 {
   // When the element is not in a list of options, the index is 0.
   *aIndex = 0;
 
   // Only select elements can contain a list of options.
   nsHTMLSelectElement* selectElement = GetSelect();
   if (!selectElement) {
     return NS_OK;
@@ -173,76 +177,76 @@ nsHTMLOptionElement::GetIndex(int32_t* a
     return NS_OK;
   }
 
   // aIndex will not be set if GetOptionsIndex fails.
   return options->GetOptionIndex(this, 0, true, aIndex);
 }
 
 bool
-nsHTMLOptionElement::Selected() const
+HTMLOptionElement::Selected() const
 {
   // If we haven't been explictly selected or deselected, use our default value
   if (!mSelectedChanged) {
     return DefaultSelected();
   }
 
   return mIsSelected;
 }
 
 bool
-nsHTMLOptionElement::DefaultSelected() const
+HTMLOptionElement::DefaultSelected() const
 {
   return HasAttr(kNameSpaceID_None, nsGkAtoms::selected);
 }
 
 nsChangeHint
-nsHTMLOptionElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
-                                            int32_t aModType) const
+HTMLOptionElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
+                                          int32_t aModType) const
 {
   nsChangeHint retval =
       nsGenericHTMLElement::GetAttributeChangeHint(aAttribute, aModType);
 
   if (aAttribute == nsGkAtoms::label ||
       aAttribute == nsGkAtoms::text) {
     NS_UpdateHint(retval, NS_STYLE_HINT_REFLOW);
   }
   return retval;
 }
 
 nsresult
-nsHTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
-                                   const nsAttrValueOrString* aValue,
-                                   bool aNotify)
+HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
+                                 const nsAttrValueOrString* aValue,
+                                 bool aNotify)
 {
   nsresult rv = nsGenericHTMLElement::BeforeSetAttr(aNamespaceID, aName,
                                                     aValue, aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aNamespaceID != kNameSpaceID_None || aName != nsGkAtoms::selected ||
       mSelectedChanged) {
     return NS_OK;
   }
-  
+
   // We just changed out selected state (since we look at the "selected"
   // attribute when mSelectedChanged is false).  Let's tell our select about
   // it.
   nsHTMLSelectElement* selectInt = GetSelect();
   if (!selectInt) {
     return NS_OK;
   }
 
   // Note that at this point mSelectedChanged is false and as long as that's
   // true it doesn't matter what value mIsSelected has.
   NS_ASSERTION(!mSelectedChanged, "Shouldn't be here");
-  
+
   bool newSelected = (aValue != nullptr);
   bool inSetDefaultSelected = mIsInSetDefaultSelected;
   mIsInSetDefaultSelected = true;
-  
+
   int32_t index;
   GetIndex(&index);
   // This should end up calling SetSelectedInternal, which we will allow to
   // take effect so that parts of SetOptionsSelectedByIndex that might depend
   // on it working don't get confused.
   rv = selectInt->SetOptionsSelectedByIndex(index, index, newSelected,
                                             false, true, aNotify,
                                             nullptr);
@@ -252,17 +256,17 @@ nsHTMLOptionElement::BeforeSetAttr(int32
   mIsInSetDefaultSelected = inSetDefaultSelected;
   mSelectedChanged = false;
   // mIsSelected doesn't matter while mSelectedChanged is false
 
   return rv;
 }
 
 NS_IMETHODIMP
-nsHTMLOptionElement::GetText(nsAString& aText)
+HTMLOptionElement::GetText(nsAString& aText)
 {
   nsAutoString text;
 
   nsIContent* child = nsINode::GetFirstChild();
   while (child) {
     if (child->NodeType() == nsIDOMNode::TEXT_NODE ||
         child->NodeType() == nsIDOMNode::CDATA_SECTION_NODE) {
       child->AppendTextTo(text);
@@ -277,48 +281,48 @@ nsHTMLOptionElement::GetText(nsAString& 
   // XXX No CompressWhitespace for nsAString.  Sad.
   text.CompressWhitespace(true, true);
   aText = text;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLOptionElement::SetText(const nsAString& aText)
+HTMLOptionElement::SetText(const nsAString& aText)
 {
   return nsContentUtils::SetNodeTextContent(this, aText, true);
 }
 
 nsresult
-nsHTMLOptionElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                                nsIContent* aBindingParent,
-                                bool aCompileEventHandlers)
+HTMLOptionElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                              nsIContent* aBindingParent,
+                              bool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
                                                  aBindingParent,
                                                  aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Our new parent might change :disabled/:enabled state.
   UpdateState(false);
 
   return NS_OK;
 }
 
 void
-nsHTMLOptionElement::UnbindFromTree(bool aDeep, bool aNullParent)
+HTMLOptionElement::UnbindFromTree(bool aDeep, bool aNullParent)
 {
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
 
   // Our previous parent could have been involved in :disabled/:enabled state.
   UpdateState(false);
 }
 
 nsEventStates
-nsHTMLOptionElement::IntrinsicState() const
+HTMLOptionElement::IntrinsicState() const
 {
   nsEventStates state = nsGenericHTMLElement::IntrinsicState();
   if (Selected()) {
     state |= NS_EVENT_STATE_CHECKED;
   }
   if (DefaultSelected()) {
     state |= NS_EVENT_STATE_DEFAULT;
   }
@@ -340,39 +344,39 @@ nsHTMLOptionElement::IntrinsicState() co
     }
   }
 
   return state;
 }
 
 // Get the select content element that contains this option
 nsHTMLSelectElement*
-nsHTMLOptionElement::GetSelect()
+HTMLOptionElement::GetSelect()
 {
   nsIContent* parent = this;
   while ((parent = parent->GetParent()) &&
          parent->IsHTML()) {
     nsHTMLSelectElement* select = nsHTMLSelectElement::FromContent(parent);
     if (select) {
       return select;
     }
     if (parent->Tag() != nsGkAtoms::optgroup) {
       break;
     }
   }
-  
+
   return nullptr;
 }
 
-NS_IMETHODIMP    
-nsHTMLOptionElement::Initialize(nsISupports* aOwner,
-                                JSContext* aContext,
-                                JSObject *aObj,
-                                uint32_t argc, 
-                                jsval *argv)
+NS_IMETHODIMP
+HTMLOptionElement::Initialize(nsISupports* aOwner,
+                              JSContext* aContext,
+                              JSObject *aObj,
+                              uint32_t argc,
+                              jsval *argv)
 {
   nsresult result = NS_OK;
 
   if (argc > 0) {
     // The first (optional) parameter is the text of the option
     JSString* jsstr = JS_ValueToString(aContext, argv[0]);
     if (!jsstr) {
       return NS_ERROR_FAILURE;
@@ -388,17 +392,17 @@ nsHTMLOptionElement::Initialize(nsISuppo
 
     size_t length;
     const jschar *chars = JS_GetStringCharsAndLength(aContext, jsstr, &length);
     if (!chars) {
       return NS_ERROR_FAILURE;
     }
 
     textContent->SetText(chars, length, false);
-    
+
     result = AppendChildTo(textContent, false);
     if (NS_FAILED(result)) {
       return result;
     }
 
     if (argc > 1) {
       // The second (optional) parameter is the value of the option
       jsstr = JS_ValueToString(aContext, argv[1]);
@@ -441,19 +445,27 @@ nsHTMLOptionElement::Initialize(nsISuppo
       }
     }
   }
 
   return result;
 }
 
 nsresult
-nsHTMLOptionElement::CopyInnerTo(Element* aDest)
+HTMLOptionElement::CopyInnerTo(Element* aDest)
 {
   nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDest->OwnerDoc()->IsStaticDocument()) {
-    static_cast<nsHTMLOptionElement*>(aDest)->SetSelected(Selected());
+    static_cast<HTMLOptionElement*>(aDest)->SetSelected(Selected());
   }
   return NS_OK;
 }
 
+JSObject*
+HTMLOptionElement::WrapNode(JSContext* aCx, JSObject* aScope, bool* aTriedToWrap)
+{
+  return HTMLOptionElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+}
+
+} // namespace dom
+} // namespace mozilla
rename from content/html/content/src/nsHTMLOptionElement.h
rename to content/html/content/src/HTMLOptionElement.h
--- a/content/html/content/src/nsHTMLOptionElement.h
+++ b/content/html/content/src/HTMLOptionElement.h
@@ -1,32 +1,36 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 sw=2 et tw=78: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef nsHTMLOptionElement_h__
-#define nsHTMLOptionElement_h__
+#ifndef mozilla_dom_HTMLOptionElement_h__
+#define mozilla_dom_HTMLOptionElement_h__
 
 #include "nsGenericHTMLElement.h"
 #include "nsIDOMHTMLOptionElement.h"
 #include "nsIJSNativeInitializer.h"
+#include "nsHTMLFormElement.h"
 
 class nsHTMLSelectElement;
 
-class nsHTMLOptionElement : public nsGenericHTMLElement,
-                            public nsIDOMHTMLOptionElement,
-                            public nsIJSNativeInitializer
+namespace mozilla {
+namespace dom {
+
+class HTMLOptionElement : public nsGenericHTMLElement,
+                          public nsIDOMHTMLOptionElement,
+                          public nsIJSNativeInitializer
 {
 public:
-  nsHTMLOptionElement(already_AddRefed<nsINodeInfo> aNodeInfo);
-  virtual ~nsHTMLOptionElement();
+  HTMLOptionElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+  virtual ~HTMLOptionElement();
 
-  NS_IMPL_FROMCONTENT_HTML_WITH_TAG(nsHTMLOptionElement, option)
+  NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLOptionElement, option)
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
@@ -40,17 +44,17 @@ public:
   using mozilla::dom::Element::GetText;
   NS_DECL_NSIDOMHTMLOPTIONELEMENT
 
   bool Selected() const;
   bool DefaultSelected() const;
 
   // nsIJSNativeInitializer
   NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aContext,
-                        JSObject *aObj, uint32_t argc, jsval *argv);
+                        JSObject* aObj, uint32_t argc, jsval* argv);
 
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               int32_t aModType) const;
 
   virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify);
 
@@ -60,36 +64,92 @@ public:
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers);
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true);
 
   // nsIContent
   virtual nsEventStates IntrinsicState() const;
 
-  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+  virtual nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const;
 
   nsresult CopyInnerTo(mozilla::dom::Element* aDest);
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual nsIDOMNode* AsDOMNode() { return this; }
 
   virtual bool IsDisabled() const {
     return HasAttr(kNameSpaceID_None, nsGkAtoms::disabled);
   }
+
+  bool Disabled() const
+  {
+    return GetBoolAttr(nsGkAtoms::disabled);
+  }
+
+  void SetDisabled(bool aValue, ErrorResult& aRv)
+  {
+    SetHTMLBoolAttr(nsGkAtoms::disabled, aValue, aRv);
+  }
+
+  nsHTMLFormElement* GetForm();
+
+  // The XPCOM GetLabel is OK for us
+  void SetLabel(const nsAString& aLabel, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::label, aLabel, aError);
+  }
+
+  // The XPCOM DefaultSelected is OK for us
+  void SetDefaultSelected(bool aValue, ErrorResult& aRv)
+  {
+    SetHTMLBoolAttr(nsGkAtoms::selected, aValue, aRv);
+  }
+
+  // The XPCOM Selected is OK for us
+  void SetSelected(bool aValue, ErrorResult& aRv)
+  {
+    aRv = SetSelected(aValue);
+  }
+
+  // The XPCOM GetValue is OK for us
+  void SetValue(const nsAString& aValue, ErrorResult& aRv)
+  {
+    SetHTMLAttr(nsGkAtoms::value, aValue, aRv);
+  }
+
+  // The XPCOM GetText is OK for us
+  void SetText(const nsAString& aValue, ErrorResult& aRv)
+  {
+    aRv = SetText(aValue);
+  }
+
+  int32_t GetIndex(ErrorResult& aRv)
+  {
+    int32_t id = 0;
+    aRv = GetIndex(&id);
+    return id;
+  }
+
 protected:
+  virtual JSObject* WrapNode(JSContext* aCx, JSObject* aScope,
+                             bool* aTriedToWrap) MOZ_OVERRIDE;
+
   /**
    * Get the select content element that contains this option, this
    * intentionally does not return nsresult, all we care about is if
    * there's a select associated with this option or not.
    */
   nsHTMLSelectElement* GetSelect();
 
   bool mSelectedChanged;
   bool mIsSelected;
 
   // True only while we're under the SetOptionsSelectedByIndex call when our
   // "selected" attribute is changing and mSelectedChanged is false.
   bool mIsInSetDefaultSelected;
 };
 
-#endif
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_HTMLOptionElement_h__
--- a/content/html/content/src/Makefile.in
+++ b/content/html/content/src/Makefile.in
@@ -34,27 +34,32 @@ EXPORTS_mozilla/dom = \
 		HTMLAreaElement.h \
 		HTMLBodyElement.h \
 		HTMLBRElement.h \
 		HTMLButtonElement.h \
 		HTMLDataListElement.h \
 		HTMLDivElement.h \
 		HTMLFieldSetElement.h \
 		HTMLFontElement.h \
+		HTMLFrameElement.h \
 		HTMLFrameSetElement.h \
 		HTMLHeadingElement.h \
 		HTMLHRElement.h \
 		HTMLImageElement.h \
 		HTMLLabelElement.h \
+		HTMLLegendElement.h \
 		HTMLLIElement.h \
 		HTMLLinkElement.h \
 		HTMLMapElement.h \
+		HTMLMenuElement.h \
+		HTMLMenuItemElement.h \
 		HTMLMetaElement.h \
 		HTMLMeterElement.h \
 		HTMLModElement.h \
+		HTMLOptionElement.h \
 		HTMLOptGroupElement.h \
 		HTMLOutputElement.h \
 		HTMLParagraphElement.h \
 		HTMLPreElement.h \
 		HTMLProgressElement.h \
 		HTMLScriptElement.h \
 		HTMLSharedElement.h \
 		HTMLSharedListElement.h \
@@ -87,36 +92,36 @@ CPPSRCS		= \
 		HTMLBodyElement.cpp \
 		HTMLButtonElement.cpp \
 		HTMLCanvasElement.cpp \
 		HTMLDataListElement.cpp \
 		HTMLDivElement.cpp \
 		HTMLFieldSetElement.cpp \
 		HTMLFontElement.cpp \
 		nsHTMLFormElement.cpp \
-		nsHTMLFrameElement.cpp \
+		HTMLFrameElement.cpp \
 		HTMLFrameSetElement.cpp \
 		HTMLHRElement.cpp \
 		HTMLHeadingElement.cpp \
 		nsHTMLIFrameElement.cpp \
 		HTMLImageElement.cpp \
 		nsHTMLInputElement.cpp \
 		HTMLLIElement.cpp \
 		HTMLLabelElement.cpp \
-		nsHTMLLegendElement.cpp \
+		HTMLLegendElement.cpp \
 		HTMLLinkElement.cpp \
 		HTMLMapElement.cpp \
-		nsHTMLMenuElement.cpp \
-		nsHTMLMenuItemElement.cpp \
+		HTMLMenuElement.cpp \
+		HTMLMenuItemElement.cpp \
 		HTMLMetaElement.cpp \
 		HTMLMeterElement.cpp \
 		HTMLModElement.cpp \
 		HTMLObjectElement.cpp \
 		nsHTMLSharedObjectElement.cpp \
-		nsHTMLOptionElement.cpp \
+		HTMLOptionElement.cpp \
 		HTMLOptGroupElement.cpp \
 		HTMLOutputElement.cpp \
 		HTMLParagraphElement.cpp \
 		HTMLPreElement.cpp \
 		HTMLProgressElement.cpp \
 		HTMLScriptElement.cpp \
 		nsHTMLSelectElement.cpp \
 		HTMLSharedElement.cpp \
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -75,17 +75,17 @@
 #include "nsIEditorIMESupport.h"
 #include "nsEventDispatcher.h"
 #include "nsLayoutUtils.h"
 #include "mozAutoDocUpdate.h"
 #include "nsHtml5Module.h"
 #include "nsITextControlElement.h"
 #include "mozilla/dom/Element.h"
 #include "HTMLFieldSetElement.h"
-#include "nsHTMLMenuElement.h"
+#include "HTMLMenuElement.h"
 #include "nsAsyncDOMEvent.h"
 #include "nsDOMMutationObserver.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/FromParser.h"
 #include "mozilla/dom/UndoManager.h"
 #include "mozilla/BloomFilter.h"
 
 #include "HTMLPropertiesCollection.h"
@@ -465,18 +465,18 @@ nsGenericHTMLElement::GetOffsetRect(nsRe
       if (html_doc) {
         offsetParent = static_cast<nsHTMLDocument*>(html_doc.get())->GetBody();
       }
     }
   }
 
   // Subtract the parent border unless it uses border-box sizing.
   if (parent &&
-      parent->GetStylePosition()->mBoxSizing != NS_STYLE_BOX_SIZING_BORDER) {
-    const nsStyleBorder* border = parent->GetStyleBorder();
+      parent->StylePosition()->mBoxSizing != NS_STYLE_BOX_SIZING_BORDER) {
+    const nsStyleBorder* border = parent->StyleBorder();
     origin.x -= border->GetComputedBorderWidth(NS_SIDE_LEFT);
     origin.y -= border->GetComputedBorderWidth(NS_SIDE_TOP);
   }
 
   // XXX We should really consider subtracting out padding for
   // content-box sizing, but we should see what IE does....
 
   // Convert to pixels.
@@ -2050,25 +2050,25 @@ nsGenericHTMLElement::GetEnumAttr(nsIAto
     if (attrVal->Type() == nsAttrValue::eEnum) {
       attrVal->GetEnumString(aResult, true);
     } else if (aDefaultInvalid) {
       AppendASCIItoUTF16(nsDependentCString(aDefaultInvalid), aResult);
     }
   }
 }
 
-nsHTMLMenuElement*
+HTMLMenuElement*
 nsGenericHTMLElement::GetContextMenu() const
 {
   nsAutoString value;
   GetHTMLAttr(nsGkAtoms::contextmenu, value);
   if (!value.IsEmpty()) {
     nsIDocument* doc = GetCurrentDoc();
     if (doc) {
-      return nsHTMLMenuElement::FromContentOrNull(doc->GetElementById(value));
+      return HTMLMenuElement::FromContentOrNull(doc->GetElementById(value));
     }
   }
   return nullptr;
 }
 
 void
 nsGenericHTMLElement::GetContextMenu(nsIDOMHTMLMenuElement** aContextMenu) const
 {
@@ -2193,16 +2193,24 @@ nsGenericHTMLFormElement::~nsGenericHTML
   // Check that this element doesn't know anything about its form at this point.
   NS_ASSERTION(!mForm, "mForm should be null at this point!");
 }
 
 NS_IMPL_QUERY_INTERFACE_INHERITED1(nsGenericHTMLFormElement,
                                    nsGenericHTMLElement,
                                    nsIFormControl)
 
+nsINode*
+nsGenericHTMLFormElement::GetParentObject() const
+{
+  // We use the parent chain to implement the scope for event handlers.
+  return mForm ? static_cast<nsINode*>(mForm)
+               : static_cast<nsINode*>(OwnerDoc());
+}
+
 bool
 nsGenericHTMLFormElement::IsNodeOfType(uint32_t aFlags) const
 {
   return !(aFlags & ~(eCONTENT | eHTML_FORM_CONTROL));
 }
 
 void
 nsGenericHTMLFormElement::SaveSubtreeState()
@@ -2686,17 +2694,17 @@ nsGenericHTMLFormElement::FormIdUpdated(
 }
 
 bool 
 nsGenericHTMLFormElement::IsElementDisabledForEvents(uint32_t aMessage, 
                                                     nsIFrame* aFrame)
 {
   bool disabled = IsDisabled();
   if (!disabled && aFrame) {
-    const nsStyleUserInterface* uiStyle = aFrame->GetStyleUserInterface();
+    const nsStyleUserInterface* uiStyle = aFrame->StyleUserInterface();
     disabled = uiStyle->mUserInput == NS_STYLE_USER_INPUT_NONE ||
       uiStyle->mUserInput == NS_STYLE_USER_INPUT_DISABLED;
 
   }
   return disabled && aMessage != NS_MOUSE_MOVE;
 }
 
 void
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -18,17 +18,16 @@
 
 class nsIDOMAttr;
 class nsIDOMEventListener;
 class nsIDOMNodeList;
 class nsIFrame;
 class nsIStyleRule;
 class nsChildContentList;
 class nsDOMCSSDeclaration;
-class nsHTMLMenuElement;
 class nsIDOMCSSStyleDeclaration;
 class nsIURI;
 class nsIFormControlFrame;
 class nsIForm;
 class nsPresState;
 class nsILayoutHistoryState;
 class nsIEditor;
 struct nsRect;
@@ -36,16 +35,17 @@ struct nsSize;
 class nsHTMLFormElement;
 class nsIDOMHTMLMenuElement;
 class nsIDOMHTMLCollection;
 class nsDOMSettableTokenList;
 
 namespace mozilla {
 namespace dom{
 class HTMLPropertiesCollection;
+class HTMLMenuElement;
 }
 }
 
 typedef nsMappedAttributeElement nsGenericHTMLElementBase;
 
 /**
  * A common superclass for HTML elements
  */
@@ -215,17 +215,17 @@ public:
         ContentEditableTristate value = element->GetContentEditableValue();
         if (value != eInherit) {
           return value == eTrue;
         }
       }
     }
     return false;
   }
-  nsHTMLMenuElement* GetContextMenu() const;
+  mozilla::dom::HTMLMenuElement* GetContextMenu() const;
   bool Spellcheck();
   void SetSpellcheck(bool aSpellcheck, mozilla::ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::spellcheck,
                 aSpellcheck ? NS_LITERAL_STRING("true")
                             : NS_LITERAL_STRING("false"),
                 aError);
   }
@@ -1054,16 +1054,18 @@ class nsGenericHTMLFormElement : public 
                                  public nsIFormControl
 {
 public:
   nsGenericHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsGenericHTMLFormElement();
 
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
 
+  nsINode* GetParentObject() const;
+
   virtual bool IsNodeOfType(uint32_t aFlags) const;
   virtual void SaveSubtreeState();
 
   // nsIFormControl
   virtual mozilla::dom::Element* GetFormElement();
   nsHTMLFormElement* GetForm() const
   {
     return mForm;
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -179,16 +179,17 @@ ShouldBeInElements(nsIFormControl* aForm
   case NS_FORM_INPUT_PASSWORD :
   case NS_FORM_INPUT_RADIO :
   case NS_FORM_INPUT_SEARCH :
   case NS_FORM_INPUT_SUBMIT :
   case NS_FORM_INPUT_TEXT :
   case NS_FORM_INPUT_TEL :
   case NS_FORM_INPUT_URL :
   case NS_FORM_INPUT_NUMBER :
+  case NS_FORM_INPUT_RANGE :
   case NS_FORM_INPUT_DATE :
   case NS_FORM_INPUT_TIME :
   case NS_FORM_SELECT :
   case NS_FORM_TEXTAREA :
   case NS_FORM_FIELDSET :
   case NS_FORM_OBJECT :
   case NS_FORM_OUTPUT :
     return true;
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -125,27 +125,28 @@ static const nsAttrValue::EnumTable kInp
   { "email", NS_FORM_INPUT_EMAIL },
   { "file", NS_FORM_INPUT_FILE },
   { "hidden", NS_FORM_INPUT_HIDDEN },
   { "reset", NS_FORM_INPUT_RESET },
   { "image", NS_FORM_INPUT_IMAGE },
   { "number", NS_FORM_INPUT_NUMBER },
   { "password", NS_FORM_INPUT_PASSWORD },
   { "radio", NS_FORM_INPUT_RADIO },
+  { "range", NS_FORM_INPUT_RANGE },
   { "search", NS_FORM_INPUT_SEARCH },
   { "submit", NS_FORM_INPUT_SUBMIT },
   { "tel", NS_FORM_INPUT_TEL },
   { "text", NS_FORM_INPUT_TEXT },
   { "time", NS_FORM_INPUT_TIME },
   { "url", NS_FORM_INPUT_URL },
   { 0 }
 };
 
 // Default type is 'text'.
-static const nsAttrValue::EnumTable* kInputDefaultType = &kInputTypeTable[14];
+static const nsAttrValue::EnumTable* kInputDefaultType = &kInputTypeTable[15];
 
 static const uint8_t NS_INPUT_AUTOCOMPLETE_OFF     = 0;
 static const uint8_t NS_INPUT_AUTOCOMPLETE_ON      = 1;
 static const uint8_t NS_INPUT_AUTOCOMPLETE_DEFAULT = 2;
 
 static const nsAttrValue::EnumTable kInputAutocompleteTable[] = {
   { "", NS_INPUT_AUTOCOMPLETE_DEFAULT },
   { "on", NS_INPUT_AUTOCOMPLETE_ON },
@@ -174,17 +175,17 @@ static const nsAttrValue::EnumTable kInp
   { "autocapitalized", NS_INPUT_INPUTMODE_AUTOCAPITALIZED },
   { 0 }
 };
 
 // Default inputmode value is "auto".
 static const nsAttrValue::EnumTable* kInputDefaultInputmode = &kInputInputmodeTable[0];
 
 const double nsHTMLInputElement::kStepScaleFactorDate = 86400000;
-const double nsHTMLInputElement::kStepScaleFactorNumber = 1;
+const double nsHTMLInputElement::kStepScaleFactorNumberRange = 1;
 const double nsHTMLInputElement::kStepScaleFactorTime = 1000;
 const double nsHTMLInputElement::kDefaultStepBase = 0;
 const double nsHTMLInputElement::kDefaultStep = 1;
 const double nsHTMLInputElement::kDefaultStepTime = 60;
 const double nsHTMLInputElement::kStepAny = 0;
 
 #define NS_INPUT_ELEMENT_STATE_IID                 \
 { /* dc3b3d14-23e2-4479-b513-7b369343e3a0 */       \
@@ -706,16 +707,17 @@ nsHTMLInputElement::Clone(nsINodeInfo *a
     case NS_FORM_INPUT_SEARCH:
     case NS_FORM_INPUT_TEXT:
     case NS_FORM_INPUT_PASSWORD:
     case NS_FORM_INPUT_TEL:
     case NS_FORM_INPUT_URL:
     case NS_FORM_INPUT_NUMBER:
     case NS_FORM_INPUT_DATE:
     case NS_FORM_INPUT_TIME:
+    case NS_FORM_INPUT_RANGE:
       if (mValueChanged) {
         // We don't have our default value anymore.  Set our value on
         // the clone.
         nsAutoString value;
         GetValueInternal(value);
         // SetValueInternal handles setting the VALUE_CHANGED bit for us
         it->SetValueInternal(value, false, true);
       }
@@ -876,22 +878,56 @@ nsHTMLInputElement::AfterSetAttr(int32_t
       UpdateTooLongValidityState();
     } else if (aName == nsGkAtoms::pattern) {
       UpdatePatternMismatchValidityState();
     } else if (aName == nsGkAtoms::multiple) {
       UpdateTypeMismatchValidityState();
     } else if (aName == nsGkAtoms::max) {
       UpdateHasRange();
       UpdateRangeOverflowValidityState();
+      if (mType == NS_FORM_INPUT_RANGE) {
+        // The value may need to change when @max changes since the value may
+        // have been invalid and can now change to a valid value, or vice
+        // versa. For example, consider:
+        // <input type=range value=-1 max=1 step=3>. The valid range is 0 to 1
+        // while the nearest valid steps are -1 and 2 (the max value having
+        // prevented there being a valid step in range). Changing @max to/from
+        // 1 and a number greater than on equal to 3 should change whether we
+        // have a step mismatch or not.
+        // The value may also need to change between a value that results in
+        // a step mismatch and a value that results in overflow. For example,
+        // if @max in the example above were to change from 1 to -1.
+        nsAutoString value;
+        GetValue(value);
+        SetValueInternal(value, false, false);
+        MOZ_ASSERT(!GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW),
+                   "HTML5 spec does not allow this");
+      }
     } else if (aName == nsGkAtoms::min) {
       UpdateHasRange();
       UpdateRangeUnderflowValidityState();
       UpdateStepMismatchValidityState();
+      if (mType == NS_FORM_INPUT_RANGE) {
+        // See @max comment
+        nsAutoString value;
+        GetValue(value);
+        SetValueInternal(value, false, false);
+        MOZ_ASSERT(!GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW),
+                   "HTML5 spec does not allow this");
+      }
     } else if (aName == nsGkAtoms::step) {
       UpdateStepMismatchValidityState();
+      if (mType == NS_FORM_INPUT_RANGE) {
+        // See @max comment
+        nsAutoString value;
+        GetValue(value);
+        SetValueInternal(value, false, false);
+        MOZ_ASSERT(!GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW),
+                   "HTML5 spec does not allow this");
+      }
     } else if (aName == nsGkAtoms::dir &&
                aValue && aValue->Equals(nsGkAtoms::_auto, eIgnoreCase)) {
       SetDirectionIfAuto(true, aNotify);
     }
 
     UpdateState(aNotify);
   }
 
@@ -1078,16 +1114,17 @@ bool
 nsHTMLInputElement::ConvertStringToNumber(nsAString& aValue,
                                           double& aResultValue) const
 {
   MOZ_ASSERT(DoesValueAsNumberApply(),
              "ConvertStringToNumber only applies if .valueAsNumber applies");
 
   switch (mType) {
     case NS_FORM_INPUT_NUMBER:
+    case NS_FORM_INPUT_RANGE:
       {
         nsresult ec;
         aResultValue = PromiseFlatString(aValue).ToDouble(&ec);
         if (NS_FAILED(ec) || !MOZ_DOUBLE_IS_FINITE(aResultValue)) {
           return false;
         }
 
         return true;
@@ -1251,16 +1288,17 @@ nsHTMLInputElement::ConvertNumberToStrin
              "ConvertNumberToString is only implemented for types implementing .valueAsNumber");
   MOZ_ASSERT(!MOZ_DOUBLE_IS_NaN(aValue) && !MOZ_DOUBLE_IS_INFINITE(aValue),
              "aValue must be a valid non-Infinite number.");
 
   aResultString.Truncate();
 
   switch (mType) {
     case NS_FORM_INPUT_NUMBER:
+    case NS_FORM_INPUT_RANGE:
       aResultString.AppendFloat(aValue);
       return true;
     case NS_FORM_INPUT_DATE:
       {
         SafeAutoJSContext ctx;
         JSAutoRequest ar(ctx);
 
         // The specs require |aValue| to be truncated.
@@ -1451,56 +1489,59 @@ nsHTMLInputElement::SetValueAsNumber(dou
 }
 
 double
 nsHTMLInputElement::GetMinimum() const
 {
   MOZ_ASSERT(DoesValueAsNumberApply(),
              "GetMinAsDouble() should only be used for types that allow .valueAsNumber");
 
-  // Once we add support for types that have a default minimum/maximum, take
-  // account of the default minimum here.
+  // Only type=range has a default minimum
+  double defaultMinimum =
+    mType == NS_FORM_INPUT_RANGE ? 0.0 : MOZ_DOUBLE_NaN();
 
   if (!HasAttr(kNameSpaceID_None, nsGkAtoms::min)) {
-    return MOZ_DOUBLE_NaN();
+    return defaultMinimum;
   }
 
   nsAutoString minStr;
   GetAttr(kNameSpaceID_None, nsGkAtoms::min, minStr);
 
   double min;
-  return ConvertStringToNumber(minStr, min) ? min : MOZ_DOUBLE_NaN();
+  return ConvertStringToNumber(minStr, min) ? min : defaultMinimum;
 }
 
 double
 nsHTMLInputElement::GetMaximum() const
 {
   MOZ_ASSERT(DoesValueAsNumberApply(),
              "GetMaxAsDouble() should only be used for types that allow .valueAsNumber");
 
-  // Once we add support for types that have a default minimum/maximum, take
-  // account of the default maximum here.
+  // Only type=range has a default maximum
+  double defaultMaximum =
+    mType == NS_FORM_INPUT_RANGE ? 100.0 : MOZ_DOUBLE_NaN();
 
   if (!HasAttr(kNameSpaceID_None, nsGkAtoms::max)) {
-    return MOZ_DOUBLE_NaN();
+    return defaultMaximum;
   }
 
   nsAutoString maxStr;
   GetAttr(kNameSpaceID_None, nsGkAtoms::max, maxStr);
 
   double max;
-  return ConvertStringToNumber(maxStr, max) ? max : MOZ_DOUBLE_NaN();
+  return ConvertStringToNumber(maxStr, max) ? max : defaultMaximum;
 }
 
 double
 nsHTMLInputElement::GetStepBase() const
 {
   MOZ_ASSERT(mType == NS_FORM_INPUT_NUMBER ||
              mType == NS_FORM_INPUT_DATE ||
-             mType == NS_FORM_INPUT_TIME,
+             mType == NS_FORM_INPUT_TIME ||
+             mType == NS_FORM_INPUT_RANGE,
              "Check that kDefaultStepBase is correct for this new type");
 
   double stepBase;
 
   // Do NOT use GetMinimum here - the spec says to use "the min content
   // attribute", not "the minimum".
   nsAutoString minStr;
   if (GetAttr(kNameSpaceID_None, nsGkAtoms::min, minStr) &&
@@ -3075,16 +3116,83 @@ nsHTMLInputElement::SanitizeValue(nsAStr
       {
         nsresult ec;
         double val = PromiseFlatString(aValue).ToDouble(&ec);
         if (NS_FAILED(ec) || !MOZ_DOUBLE_IS_FINITE(val)) {
           aValue.Truncate();
         }
       }
       break;
+    case NS_FORM_INPUT_RANGE:
+      {
+        double minimum = GetMinimum();
+        double maximum = GetMaximum();
+        MOZ_ASSERT(MOZ_DOUBLE_IS_FINITE(minimum) &&
+                   MOZ_DOUBLE_IS_FINITE(maximum),
+                   "type=range should have a default maximum/minimum");
+
+        // We use this to avoid modifying the string unnecessarily, since that
+        // may introduce rounding. This is set to true only if the value we
+        // parse out from aValue needs to be sanitized.
+        bool needSanitization = false;
+
+        double value;
+        bool ok = ConvertStringToNumber(aValue, value);
+        if (!ok) {
+          needSanitization = true;
+          // Set value to midway between minimum and maximum.
+          value = maximum <= minimum ? minimum : minimum + (maximum - minimum)/2.0;
+        } else if (value < minimum || maximum < minimum) {
+          needSanitization = true;
+          value = minimum;
+        } else if (value > maximum) {
+          needSanitization = true;
+          value = maximum;
+        }
+
+        double step = GetStep();
+        if (step != kStepAny) {
+          double stepBase = GetStepBase();
+          // There could be rounding issues below when dealing with fractional
+          // numbers, but let's ignore that until ECMAScript supplies us with a
+          // decimal number type.
+          double deltaToStep = NS_floorModulo(value - stepBase, step);
+          if (deltaToStep != 0) {
+            // "suffering from a step mismatch"
+            // Round the element's value to the nearest number for which the
+            // element would not suffer from a step mismatch, and which is
+            // greater than or equal to the minimum, and, if the maximum is not
+            // less than the minimum, which is less than or equal to the
+            // maximum, if there is a number that matches these constraints:
+            MOZ_ASSERT(deltaToStep > 0, "stepBelow/stepAbove will be wrong");
+            double stepBelow = value - deltaToStep;
+            double stepAbove = value - deltaToStep + step;
+            double halfStep = step / 2;
+            bool stepAboveIsClosest = (stepAbove - value) <= halfStep;
+            bool stepAboveInRange = stepAbove >= minimum &&
+                                    stepAbove <= maximum;
+            bool stepBelowInRange = stepBelow >= minimum &&
+                                    stepBelow <= maximum;
+
+            if ((stepAboveIsClosest || !stepBelowInRange) && stepAboveInRange) {
+              needSanitization = true;
+              value = stepAbove;
+            } else if ((!stepAboveIsClosest || !stepAboveInRange) && stepBelowInRange) {
+              needSanitization = true;
+              value = stepBelow;
+            }
+          }
+        }
+
+        if (needSanitization) {
+          aValue.Truncate();
+          aValue.AppendFloat(value);
+        }
+      }
+      break;
     case NS_FORM_INPUT_DATE:
       {
         if (!aValue.IsEmpty() && !IsValidDate(aValue)) {
           aValue.Truncate();
         }
       }
       break;
     case NS_FORM_INPUT_TIME:
@@ -3294,18 +3402,20 @@ nsHTMLInputElement::ParseAttribute(int32
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::type) {
       // XXX ARG!! This is major evilness. ParseAttribute
       // shouldn't set members. Override SetAttr instead
       int32_t newType;
       bool success = aResult.ParseEnumValue(aValue, kInputTypeTable, false);
       if (success) {
         newType = aResult.GetEnumValue();
-        if (IsExperimentalMobileType(newType) &&
-            !Preferences::GetBool("dom.experimental_forms", false)) {
+        if ((IsExperimentalMobileType(newType) &&
+             !Preferences::GetBool("dom.experimental_forms", false)) ||
+            (newType == NS_FORM_INPUT_RANGE &&
+             !Preferences::GetBool("dom.experimental_forms_range", false))) {
           newType = kInputDefaultType->value;
           aResult.SetTo(newType, &aValue);
         }
         if (newType == NS_FORM_INPUT_FILE &&
             Preferences::GetBool("dom.disable_input_file", false)) {
           newType = kInputDefaultType->value;
           aResult.SetTo(newType, &aValue);
         }
@@ -3927,16 +4037,17 @@ nsHTMLInputElement::SaveState()
     case NS_FORM_INPUT_SEARCH:
     case NS_FORM_INPUT_TEXT:
     case NS_FORM_INPUT_TEL:
     case NS_FORM_INPUT_URL:
     case NS_FORM_INPUT_HIDDEN:
     case NS_FORM_INPUT_NUMBER:
     case NS_FORM_INPUT_DATE:
     case NS_FORM_INPUT_TIME:
+    case NS_FORM_INPUT_RANGE:
       {
         if (mValueChanged) {
           inputState = new nsHTMLInputElementState();
           nsAutoString value;
           GetValue(value);
           DebugOnly<nsresult> rv =
             nsLinebreakConverter::ConvertStringLineBreaks(
                  value,
@@ -4113,16 +4224,17 @@ nsHTMLInputElement::RestoreState(nsPresS
       case NS_FORM_INPUT_SEARCH:
       case NS_FORM_INPUT_TEXT:
       case NS_FORM_INPUT_TEL:
       case NS_FORM_INPUT_URL:
       case NS_FORM_INPUT_HIDDEN:
       case NS_FORM_INPUT_NUMBER:
       case NS_FORM_INPUT_DATE:
       case NS_FORM_INPUT_TIME:
+      case NS_FORM_INPUT_RANGE:
         {
           SetValueInternal(inputState->GetValue(), false, true);
           break;
         }
       case NS_FORM_INPUT_FILE:
         {
           const nsCOMArray<nsIDOMFile>& files = inputState->GetFiles();
           SetFiles(files, true);
@@ -4337,16 +4449,17 @@ nsHTMLInputElement::GetValueMode() const
 #ifdef DEBUG
     case NS_FORM_INPUT_TEXT:
     case NS_FORM_INPUT_PASSWORD:
     case NS_FORM_INPUT_SEARCH:
     case NS_FORM_INPUT_TEL:
     case NS_FORM_INPUT_EMAIL:
     case NS_FORM_INPUT_URL:
     case NS_FORM_INPUT_NUMBER:
+    case NS_FORM_INPUT_RANGE:
     case NS_FORM_INPUT_DATE:
     case NS_FORM_INPUT_TIME:
       return VALUE_MODE_VALUE;
     default:
       NS_NOTYETIMPLEMENTED("Unexpected input type in GetValueMode()");
       return VALUE_MODE_VALUE;
 #else // DEBUG
     default:
@@ -4371,19 +4484,19 @@ nsHTMLInputElement::DoesReadOnlyApply() 
     case NS_FORM_INPUT_HIDDEN:
     case NS_FORM_INPUT_BUTTON:
     case NS_FORM_INPUT_IMAGE:
     case NS_FORM_INPUT_RESET:
     case NS_FORM_INPUT_SUBMIT:
     case NS_FORM_INPUT_RADIO:
     case NS_FORM_INPUT_FILE:
     case NS_FORM_INPUT_CHECKBOX:
+    case NS_FORM_INPUT_RANGE:
     // TODO:
     // case NS_FORM_INPUT_COLOR:
-    // case NS_FORM_INPUT_RANGE:
       return false;
 #ifdef DEBUG
     case NS_FORM_INPUT_TEXT:
     case NS_FORM_INPUT_PASSWORD:
     case NS_FORM_INPUT_SEARCH:
     case NS_FORM_INPUT_TEL:
     case NS_FORM_INPUT_EMAIL:
     case NS_FORM_INPUT_URL:
@@ -4406,19 +4519,19 @@ nsHTMLInputElement::DoesRequiredApply() 
 {
   switch (mType)
   {
     case NS_FORM_INPUT_HIDDEN:
     case NS_FORM_INPUT_BUTTON:
     case NS_FORM_INPUT_IMAGE:
     case NS_FORM_INPUT_RESET:
     case NS_FORM_INPUT_SUBMIT:
+    case NS_FORM_INPUT_RANGE:
     // TODO:
     // case NS_FORM_INPUT_COLOR:
-    // case NS_FORM_INPUT_RANGE:
       return false;
 #ifdef DEBUG
     case NS_FORM_INPUT_RADIO:
     case NS_FORM_INPUT_CHECKBOX:
     case NS_FORM_INPUT_FILE:
     case NS_FORM_INPUT_TEXT:
     case NS_FORM_INPUT_PASSWORD:
     case NS_FORM_INPUT_SEARCH:
@@ -4464,18 +4577,18 @@ nsHTMLInputElement::DoesPatternApply() c
 bool
 nsHTMLInputElement::DoesMinMaxApply() const
 {
   switch (mType)
   {
     case NS_FORM_INPUT_NUMBER:
     case NS_FORM_INPUT_DATE:
     case NS_FORM_INPUT_TIME:
+    case NS_FORM_INPUT_RANGE:
     // TODO:
-    // case NS_FORM_INPUT_RANGE:
     // All date/time types.
       return true;
 #ifdef DEBUG
     case NS_FORM_INPUT_RESET:
     case NS_FORM_INPUT_SUBMIT:
     case NS_FORM_INPUT_IMAGE:
     case NS_FORM_INPUT_BUTTON:
     case NS_FORM_INPUT_HIDDEN:
@@ -4942,17 +5055,18 @@ nsHTMLInputElement::GetValidationMessage
       aValidationMessage = message;
       break;
     }
     case VALIDITY_STATE_RANGE_OVERFLOW:
     {
       nsXPIDLString message;
 
       nsAutoString maxStr;
-      if (mType == NS_FORM_INPUT_NUMBER) {
+      if (mType == NS_FORM_INPUT_NUMBER ||
+          mType == NS_FORM_INPUT_RANGE) {
         //We want to show the value as parsed when it's a number
         double maximum = GetMaximum();
         MOZ_ASSERT(!MOZ_DOUBLE_IS_NaN(maximum));
 
         maxStr.AppendFloat(maximum);
       } else if (mType == NS_FORM_INPUT_DATE || mType == NS_FORM_INPUT_TIME) {
         GetAttr(kNameSpaceID_None, nsGkAtoms::max, maxStr);
       } else {
@@ -4966,17 +5080,18 @@ nsHTMLInputElement::GetValidationMessage
       aValidationMessage = message;
       break;
     }
     case VALIDITY_STATE_RANGE_UNDERFLOW:
     {
       nsXPIDLString message;
 
       nsAutoString minStr;
-      if (mType == NS_FORM_INPUT_NUMBER) {
+      if (mType == NS_FORM_INPUT_NUMBER ||
+          mType == NS_FORM_INPUT_RANGE) {
         double minimum = GetMinimum();
         MOZ_ASSERT(!MOZ_DOUBLE_IS_NaN(minimum));
 
         minStr.AppendFloat(minimum);
       } else if (mType == NS_FORM_INPUT_DATE || mType == NS_FORM_INPUT_TIME) {
         GetAttr(kNameSpaceID_None, nsGkAtoms::min, minStr);
       } else {
         NS_NOTREACHED("Unexpected input type");
@@ -5441,33 +5556,35 @@ double
 nsHTMLInputElement::GetStepScaleFactor() const
 {
   MOZ_ASSERT(DoesStepApply());
 
   switch (mType) {
     case NS_FORM_INPUT_DATE:
       return kStepScaleFactorDate;
     case NS_FORM_INPUT_NUMBER:
-      return kStepScaleFactorNumber;
+    case NS_FORM_INPUT_RANGE:
+      return kStepScaleFactorNumberRange;
     case NS_FORM_INPUT_TIME:
       return kStepScaleFactorTime;
     default:
       MOZ_NOT_REACHED();
       return MOZ_DOUBLE_NaN();
   }
 }
 
 double
 nsHTMLInputElement::GetDefaultStep() const
 {
   MOZ_ASSERT(DoesStepApply());
 
   switch (mType) {
     case NS_FORM_INPUT_DATE:
     case NS_FORM_INPUT_NUMBER:
+    case NS_FORM_INPUT_RANGE:
       return kDefaultStep;
     case NS_FORM_INPUT_TIME:
       return kDefaultStepTime;
     default:
       MOZ_NOT_REACHED();
       return MOZ_DOUBLE_NaN();
   }
 }
--- a/content/html/content/src/nsHTMLInputElement.h
+++ b/content/html/content/src/nsHTMLInputElement.h
@@ -278,16 +278,44 @@ public:
   bool Indeterminate() const { return mIndeterminate; }
   bool Checked() const { return mChecked; }
 
   /**
    * Fires change event if mFocusedValue and current value held are unequal.
    */
   void FireChangeEventIfNeeded();
 
+  /**
+   * Returns the input element's value as a double-precision float.
+   * Returns NaN if the current element's value is not a floating point number.
+   *
+   * @return the input element's value as a double-precision float.
+   */
+  double GetValueAsDouble() const;
+
+  /**
+   * Returns the input's "minimum" (as defined by the HTML5 spec) as a double.
+   * Note this takes account of any default minimum that the type may have.
+   * Returns NaN if the min attribute isn't a valid floating point number and
+   * the input's type does not have a default minimum.
+   *
+   * NOTE: Only call this if you know DoesMinMaxApply() returns true.
+   */
+  double GetMinimum() const;
+
+  /**
+   * Returns the input's "maximum" (as defined by the HTML5 spec) as a double.
+   * Note this takes account of any default maximum that the type may have.
+   * Returns NaN if the max attribute isn't a valid floating point number and
+   * the input's type does not have a default maximum.
+   *
+   * NOTE:Only call this if you know DoesMinMaxApply() returns true.
+   */
+  double GetMaximum() const;
+
 protected:
   // Pull IsSingleLineTextControl into our scope, otherwise it'd be hidden
   // by the nsITextControlElement version.
   using nsGenericHTMLFormElement::IsSingleLineTextControl;
 
   /**
    * The ValueModeType specifies how the value IDL attribute should behave.
    *
@@ -565,24 +593,16 @@ protected:
    * Returns the radio group container if the element has one, null otherwise.
    * The radio group container will be the form owner if there is one.
    * The current document otherwise.
    * @return the radio group container if the element has one, null otherwise.
    */
   nsIRadioGroupContainer* GetRadioGroupContainer() const;
 
   /**
-   * Returns the input element's value as a double-precision float.
-   * Returns NaN if the current element's value is not a floating point number.
-   *
-   * @return the input element's value as a double-precision float.
-   */
-  double GetValueAsDouble() const;
-
-  /**
    * Convert a string to a number in a type specific way,
    * http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#concept-input-value-string-number
    * ie parse a date string to a timestamp if type=date,
    * or parse a number string to its value if type=number.
    * @param aValue the string to be parsed.
    * @param aResultValue the timestamp as a double.
    * @result whether the parsing was successful.
    */
@@ -654,38 +674,16 @@ protected:
    */
   void SetValue(double aValue);
 
   /**
    * Update the HAS_RANGE bit field value.
    */
   void UpdateHasRange();
 
-  /**
-   * Returns the input's "minimum" (as defined by the HTML5 spec) as a double.
-   * Note this takes account of any default minimum that the type may have.
-   * Returns NaN if the min attribute isn't a valid floating point number and
-   * the input's type does not have a default minimum. Otherwise, guaranteed
-   * to return a finite value.
-   *
-   * NOTE: Only call this if you know DoesMinMaxApply() returns true.
-   */
-  double GetMinimum() const;
-
-  /**
-   * Returns the input's "maximum" (as defined by the HTML5 spec) as a double.
-   * Note this takes account of any default maximum that the type may have.
-   * Returns NaN if the max attribute isn't a valid floating point number and
-   * the input's type does not have a default maximum. Otherwise, guaranteed
-   * to return a finite value.
-   *
-   * NOTE:Only call this if you know DoesMinMaxApply() returns true.
-   */
-  double GetMaximum() const;
-
    /**
     * Get the step scale value for the current type.
     * See:
     * http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#concept-input-step-scale
     */
   double GetStepScaleFactor() const;
 
   /**
@@ -769,17 +767,17 @@ protected:
    * a change event. This is to ensure correct future change event firing.
    * NB: This is ONLY applicable where the element is a text control. ie,
    * where type= "text", "email", "search", "tel", "url" or "password".
    */
   nsString mFocusedValue;  
 
   // Step scale factor values, for input types that have one.
   static const double kStepScaleFactorDate;
-  static const double kStepScaleFactorNumber;
+  static const double kStepScaleFactorNumberRange;
   static const double kStepScaleFactorTime;
 
   // Default step base value when a type do not have specific one.
   static const double kDefaultStepBase;
 
   // Default step used when there is no specified step.
   static const double kDefaultStep;
   static const double kDefaultStepTime;
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -1086,21 +1086,16 @@ nsresult nsHTMLMediaElement::LoadResourc
 
   // Set the media element's CORS mode only when loading a resource
   mCORSMode = AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin));
 
   nsHTMLMediaElement* other = LookupMediaElementURITable(mLoadingSrc);
   if (other && other->mDecoder) {
     // Clone it.
     nsresult rv = InitializeDecoderAsClone(other->mDecoder);
-    // Get the mimetype from the element we clone, since we will not get it via
-    // the channel, and we won't be able to sniff for it, because we will not
-    // open a channel to get the beginning of the media (it is likely to already
-    // be in the cache).
-    mMimeType = other->mMimeType;
     if (NS_SUCCEEDED(rv))
       return rv;
   }
 
   if (IsMediaStreamURI(mLoadingSrc)) {
     nsCOMPtr<nsIDOMMediaStream> stream;
     rv = NS_GetStreamForMediaStreamURI(mLoadingSrc, getter_AddRefs(stream));
     if (NS_FAILED(rv)) {
@@ -1243,17 +1238,16 @@ NS_IMETHODIMP nsHTMLMediaElement::MozLoa
   ChangeDelayLoadStatus(true);
 
   mLoadingSrc = other->mLoadingSrc;
   nsresult rv = InitializeDecoderAsClone(other->mDecoder);
   if (NS_FAILED(rv)) {
     ChangeDelayLoadStatus(false);
     return rv;
   }
-  mMimeType = other->mMimeType;
 
   SetPlaybackRate(mDefaultPlaybackRate);
   DispatchAsyncEvent(NS_LITERAL_STRING("loadstart"));
 
   return NS_OK;
 }
 
 /* readonly attribute unsigned short readyState; */
@@ -2317,30 +2311,30 @@ nsresult nsHTMLMediaElement::InitializeD
 nsresult nsHTMLMediaElement::InitializeDecoderForChannel(nsIChannel *aChannel,
                                                          nsIStreamListener **aListener)
 {
   NS_ASSERTION(mLoadingSrc, "mLoadingSrc must already be set");
   NS_ASSERTION(mDecoder == nullptr, "Shouldn't have a decoder");
 
   nsAutoCString mimeType;
 
-  aChannel->GetContentType(mMimeType);
-  NS_ASSERTION(!mMimeType.IsEmpty(), "We should have the Content-Type.");
-
-  nsRefPtr<MediaDecoder> decoder = CreateDecoder(mMimeType);
+  aChannel->GetContentType(mimeType);
+  NS_ASSERTION(!mimeType.IsEmpty(), "We should have the Content-Type.");
+
+  nsRefPtr<MediaDecoder> decoder = CreateDecoder(mimeType);
   if (!decoder) {
     nsAutoString src;
     GetCurrentSrc(src);
-    NS_ConvertUTF8toUTF16 mimeUTF16(mMimeType);
+    NS_ConvertUTF8toUTF16 mimeUTF16(mimeType);
     const PRUnichar* params[] = { mimeUTF16.get(), src.get() };
     ReportLoadError("MediaLoadUnsupportedMimeType", params, ArrayLength(params));
     return NS_ERROR_FAILURE;
   }
 
-  LOG(PR_LOG_DEBUG, ("%p Created decoder %p for type %s", this, decoder.get(), mMimeType.get()));
+  LOG(PR_LOG_DEBUG, ("%p Created decoder %p for type %s", this, decoder.get(), mimeType.get()));
 
   MediaResource* resource = MediaResource::Create(decoder, aChannel);
   if (!resource)
     return NS_ERROR_OUT_OF_MEMORY;
 
   // stream successfully created, the stream now owns the channel.
   mChannel = nullptr;
 
@@ -3501,21 +3495,16 @@ NS_IMETHODIMP nsHTMLMediaElement::GetMoz
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If there is no end fragment, or the fragment end is greater than the
   // duration, return the duration.
   *aTime = (mFragmentEnd < 0.0 || mFragmentEnd > duration) ? duration : mFragmentEnd;
   return NS_OK;
 }
 
-void nsHTMLMediaElement::GetMimeType(nsCString& aMimeType)
-{
-  aMimeType = mMimeType;
-}
-
 void nsHTMLMediaElement::NotifyAudioAvailableListener()
 {
   if (mDecoder) {
     mDecoder->NotifyAudioAvailableListener();
   }
 }
 
 static double ClampPlaybackRate(double aPlaybackRate)
--- a/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/content/html/content/src/nsHTMLSelectElement.cpp
@@ -2,17 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Util.h"
 
 #include "nsHTMLSelectElement.h"
 
-#include "nsHTMLOptionElement.h"
+#include "mozilla/dom/HTMLOptionElement.h"
 #include "nsIDOMEventTarget.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsLayoutUtils.h"
 #include "nsMappedAttributes.h"
 #include "nsIForm.h"
 #include "nsFormSubmission.h"
@@ -330,17 +330,17 @@ nsHTMLSelectElement::InsertOptionsIntoLi
                                                   int32_t* aInsertIndex,
                                                   int32_t aDepth)
 {
   // We *assume* here that someone's brain has not gone horribly
   // wrong by putting <option> inside of <option>.  I'm sorry, I'm
   // just not going to look for an option inside of an option.
   // Sue me.
 
-  nsHTMLOptionElement *optElement = nsHTMLOptionElement::FromContent(aOptions);
+  HTMLOptionElement* optElement = HTMLOptionElement::FromContent(aOptions);
   if (optElement) {
     mOptions->InsertOptionAt(optElement, *aInsertIndex);
     (*aInsertIndex)++;
     return NS_OK;
   }
 
   // If it's at the top level, then we just found out there are non-options
   // at the top level, which will throw off the insert count
@@ -440,17 +440,17 @@ nsHTMLSelectElement::WillAddOptions(nsIC
     if (aContentIndex >= children) {
       // If the content insert is after the end of the parent, then we want to get
       // the next index *after* the parent and insert there.
       ind = GetOptionIndexAfter(aParent);
     } else {
       // If the content insert is somewhere in the middle of the container, then
       // we want to get the option currently at the index and insert in front of
       // that.
-      nsIContent *currentKid = aParent->GetChildAt(aContentIndex);
+      nsIContent* currentKid = aParent->GetChildAt(aContentIndex);
       NS_ASSERTION(currentKid, "Child not found!");
       if (currentKid) {
         ind = GetOptionIndexAt(currentKid);
       } else {
         ind = -1;
       }
     }
   }
@@ -465,17 +465,17 @@ nsHTMLSelectElement::WillRemoveOptions(n
 {
   int32_t level = GetContentDepth(aParent);
   NS_ASSERTION(level >= 0, "getting notified by unexpected content");
   if (level == -1) {
     return NS_ERROR_FAILURE;
   }
 
   // Get the index where the options will be removed
-  nsIContent *currentKid = aParent->GetChildAt(aContentIndex);
+  nsIContent* currentKid = aParent->GetChildAt(aContentIndex);
   if (currentKid) {
     int32_t ind;
     if (!mNonOptionChildren) {
       // If there are no artifacts, aContentIndex == ind
       ind = aContentIndex;
     } else {
       // If there are artifacts, we have to get the index of the option the
       // hard way
@@ -551,17 +551,17 @@ nsHTMLSelectElement::GetOptionIndexAfter
 
   return retval;
 }
 
 int32_t
 nsHTMLSelectElement::GetFirstOptionIndex(nsIContent* aOptions)
 {
   int32_t listIndex = -1;
-  nsHTMLOptionElement *optElement = nsHTMLOptionElement::FromContent(aOptions);
+  HTMLOptionElement* optElement = HTMLOptionElement::FromContent(aOptions);
   if (optElement) {
     GetOptionIndex(optElement, 0, true, &listIndex);
     // If you nested stuff under the option, you're just plain
     // screwed.  *I'm* not going to aid and abet your evil deed.
     return listIndex;
   }
 
   listIndex = GetFirstChildOptionIndex(aOptions, 0, aOptions->GetChildCount());
@@ -581,22 +581,22 @@ nsHTMLSelectElement::GetFirstChildOption
     if (retval != -1) {
       break;
     }
   }
 
   return retval;
 }
 
-nsISelectControlFrame *
+nsISelectControlFrame*
 nsHTMLSelectElement::GetSelectFrame()
 {
   nsIFormControlFrame* form_control_frame = GetFormControlFrame(false);
 
-  nsISelectControlFrame *select_frame = nullptr;
+  nsISelectControlFrame* select_frame = nullptr;
 
   if (form_control_frame) {
     select_frame = do_QueryFrame(form_control_frame);
   }
 
   return select_frame;
 }
 
@@ -822,17 +822,17 @@ nsHTMLSelectElement::GetOptionIndex(nsID
 {
   nsCOMPtr<nsINode> option = do_QueryInterface(aOption);
   return mOptions->GetOptionIndex(option->AsElement(), aStartIndex, aForward, aIndex);
 }
 
 bool
 nsHTMLSelectElement::IsOptionSelectedByIndex(int32_t aIndex)
 {
-  nsIDOMHTMLOptionElement *option = mOptions->ItemAsOption(aIndex);
+  nsIDOMHTMLOptionElement* option = mOptions->ItemAsOption(aIndex);
   bool isSelected = false;
   if (option) {
     option->GetSelected(&isSelected);
   }
   return isSelected;
 }
 
 void
@@ -850,18 +850,18 @@ nsHTMLSelectElement::OnOptionSelected(ns
     FindSelectedIndex(aIndex + 1, aNotify);
   }
 
   if (aChangeOptionState) {
     // Tell the option to get its bad self selected
     nsCOMPtr<nsIDOMNode> option;
     Item(aIndex, getter_AddRefs(option));
     if (option) {
-      nsRefPtr<nsHTMLOptionElement> optionElement = 
-        static_cast<nsHTMLOptionElement*>(option.get());
+      nsRefPtr<HTMLOptionElement> optionElement =
+        static_cast<HTMLOptionElement*>(option.get());
       optionElement->SetSelectedInternal(aSelected, aNotify);
     }
   }
 
   // Let the frame know too
   if (aSelectFrame) {
     aSelectFrame->OnOptionSelected(aIndex, aSelected);
   }
@@ -943,17 +943,17 @@ nsHTMLSelectElement::SetOptionsSelectedB
   // First, find out whether multiple items can be selected
   bool isMultiple = HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
 
   // These variables tell us whether any options were selected
   // or deselected.
   bool optionsSelected = false;
   bool optionsDeselected = false;
 
-  nsISelectControlFrame *selectFrame = nullptr;
+  nsISelectControlFrame* selectFrame = nullptr;
   bool didGetFrame = false;
   nsWeakFrame weakSelectFrame;
 
   if (aIsSelected) {
     // Setting selectedIndex to an out-of-bounds index means -1. (HTML5)
     if (aStartIndex >= (int32_t)numItems || aStartIndex < 0 ||
         aEndIndex >= (int32_t)numItems || aEndIndex < 0) {
       aStartIndex = -1;
@@ -992,17 +992,17 @@ nsHTMLSelectElement::SetOptionsSelectedB
 
           if (isDisabled) {
             continue;
           } else {
             allDisabled = false;
           }
         }
 
-        nsIDOMHTMLOptionElement *option = mOptions->ItemAsOption(optIndex);
+        nsIDOMHTMLOptionElement* option = mOptions->ItemAsOption(optIndex);
         if (option) {
           // If the index is already selected, ignore it.
           bool isSelected = false;
           option->GetSelected(&isSelected);
           if (!isSelected) {
             // To notify the frame if anything gets changed. No need
             // to flush here, if there's no frame yet we don't need to
             // force it to be created just to notify it about a change
@@ -1023,17 +1023,17 @@ nsHTMLSelectElement::SetOptionsSelectedB
     if (((!isMultiple && optionsSelected)
        || (aClearAll && !allDisabled)
        || aStartIndex == -1)
        && previousSelectedIndex != -1) {
       for (int32_t optIndex = previousSelectedIndex;
            optIndex < int32_t(numItems);
            optIndex++) {
         if (optIndex < aStartIndex || optIndex > aEndIndex) {
-          nsIDOMHTMLOptionElement *option = mOptions->ItemAsOption(optIndex);
+          nsIDOMHTMLOptionElement* option = mOptions->ItemAsOption(optIndex);
           if (option) {
             // If the index is already selected, ignore it.
             bool isSelected = false;
             option->GetSelected(&isSelected);
             if (isSelected) {
               if (!didGetFrame || (selectFrame && !weakSelectFrame.IsAlive())) {
                 // To notify the frame if anything gets changed, don't
                 // flush, if the frame doesn't exist we don't need to
@@ -1066,17 +1066,17 @@ nsHTMLSelectElement::SetOptionsSelectedB
       if (!aSetDisabled) {
         bool isDisabled;
         IsOptionDisabled(optIndex, &isDisabled);
         if (isDisabled) {
           continue;
         }
       }
 
-      nsIDOMHTMLOptionElement *option = mOptions->ItemAsOption(optIndex);
+      nsIDOMHTMLOptionElement* option = mOptions->ItemAsOption(optIndex);
       if (option) {
         // If the index is already selected, ignore it.
         bool isSelected = false;
         option->GetSelected(&isSelected);
         if (isSelected) {
           if (!didGetFrame || (selectFrame && !weakSelectFrame.IsAlive())) {
             // To notify the frame if anything gets changed, don't
             // flush, if the frame doesn't exist we don't need to
@@ -1230,17 +1230,17 @@ NS_IMPL_UINT_ATTR(nsHTMLSelectElement, S
 int32_t
 nsHTMLSelectElement::TabIndexDefault()
 {
   return 0;
 }
 
 bool
 nsHTMLSelectElement::IsHTMLFocusable(bool aWithMouse,
-                                     bool *aIsFocusable, int32_t *aTabIndex)
+                                     bool* aIsFocusable, int32_t* aTabIndex)
 {
   if (nsGenericHTMLFormElement::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex)) {
     return true;
   }
 
   *aIsFocusable = !IsDisabled();
 
   return false;
@@ -1583,29 +1583,29 @@ NS_IMETHODIMP
 nsHTMLSelectElement::SaveState()
 {
   nsRefPtr<nsSelectState> state = new nsSelectState();
 
   uint32_t len;
   GetLength(&len);
 
   for (uint32_t optIndex = 0; optIndex < len; optIndex++) {
-    nsIDOMHTMLOptionElement *option = mOptions->ItemAsOption(optIndex);
+    nsIDOMHTMLOptionElement* option = mOptions->ItemAsOption(optIndex);
     if (option) {
       bool isSelected;
       option->GetSelected(&isSelected);
       if (isSelected) {
         nsAutoString value;
         option->GetValue(value);
         state->PutOption(optIndex, value);
       }
     }
   }
 
-  nsPresState *presState = nullptr;
+  nsPresState* presState = nullptr;
   nsresult rv = GetPrimaryPresState(this, &presState);
   if (presState) {
     presState->SetStateProperty(state);
 
     if (mDisabledChanged) {
       // We do not want to save the real disabled state but the disabled
       // attribute.
       presState->SetDisabled(HasAttr(kNameSpaceID_None, nsGkAtoms::disabled));
@@ -1648,17 +1648,17 @@ nsHTMLSelectElement::RestoreStateTo(nsSe
   uint32_t len;
   GetLength(&len);
 
   // First clear all
   SetOptionsSelectedByIndex(-1, -1, true, true, true, true, nullptr);
 
   // Next set the proper ones
   for (int32_t i = 0; i < int32_t(len); i++) {
-    nsIDOMHTMLOptionElement *option = mOptions->ItemAsOption(i);
+    nsIDOMHTMLOptionElement* option = mOptions->ItemAsOption(i);
     if (option) {
       nsAutoString value;
       nsresult rv = option->GetValue(value);
       if (NS_SUCCEEDED(rv) && aNewSelected->ContainsOption(i, value)) {
         SetOptionsSelectedByIndex(i, i, true, false, true, true, nullptr);
       }
     }
   }
@@ -1753,17 +1753,17 @@ nsHTMLSelectElement::SubmitNamesValues(n
   for (uint32_t optIndex = 0; optIndex < len; optIndex++) {
     // Don't send disabled options
     bool disabled;
     nsresult rv = IsOptionDisabled(optIndex, &disabled);
     if (NS_FAILED(rv) || disabled) {
       continue;
     }
 
-    nsIDOMHTMLOptionElement *option = mOptions->ItemAsOption(optIndex);
+    nsIDOMHTMLOptionElement* option = mOptions->ItemAsOption(optIndex);
     NS_ENSURE_TRUE(option, NS_ERROR_UNEXPECTED);
 
     bool isSelected;
     rv = option->GetSelected(&isSelected);
     NS_ENSURE_SUCCESS(rv, rv);
     if (!isSelected) {
       continue;
     }
@@ -1811,17 +1811,17 @@ nsHTMLSelectElement::DispatchContentRese
 }
 
 static void
 AddOptionsRecurse(nsIContent* aRoot, nsHTMLOptionCollection* aArray)
 {
   for (nsIContent* cur = aRoot->GetFirstChild();
        cur;
        cur = cur->GetNextSibling()) {
-    nsHTMLOptionElement* opt = nsHTMLOptionElement::FromContent(cur);
+    HTMLOptionElement* opt = HTMLOptionElement::FromContent(cur);
     if (opt) {
       aArray->AppendOption(opt);
     } else if (cur->IsHTML(nsGkAtoms::optgroup)) {
       AddOptionsRecurse(cur, aArray);
     }
   }
 }
 
@@ -2016,18 +2016,18 @@ NS_INTERFACE_TABLE_HEAD(nsHTMLOptionColl
 NS_INTERFACE_MAP_END
 
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHTMLOptionCollection)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHTMLOptionCollection)
 
 
 JSObject*
-nsHTMLOptionCollection::WrapObject(JSContext *cx, JSObject *scope,
-                                   bool *triedToWrap)
+nsHTMLOptionCollection::WrapObject(JSContext* cx, JSObject* scope,
+                                   bool* triedToWrap)
 {
   return HTMLOptionsCollectionBinding::Wrap(cx, scope, this, triedToWrap);
 }
 
 NS_IMETHODIMP
 nsHTMLOptionCollection::GetLength(uint32_t* aLength)
 {
   *aLength = mElements.Length();
@@ -2042,17 +2042,17 @@ nsHTMLOptionCollection::SetLength(uint32
     return NS_ERROR_UNEXPECTED;
   }
 
   return mSelect->SetLength(aLength);
 }
 
 NS_IMETHODIMP
 nsHTMLOptionCollection::SetOption(uint32_t aIndex,
-                                  nsIDOMHTMLOptionElement *aOption)
+                                  nsIDOMHTMLOptionElement* aOption)
 {
   if (!mSelect) {
     return NS_OK;
   }
 
   // if the new option is null, just remove this option.  Note that it's safe
   // to pass a too-large aIndex in here.
   if (!aOption) {
@@ -2104,17 +2104,17 @@ nsHTMLOptionCollection::GetSelectedIndex
   }
 
   int32_t selectedIndex;
   aError = mSelect->GetSelectedIndex(&selectedIndex);
   return selectedIndex;
 }
 
 NS_IMETHODIMP
-nsHTMLOptionCollection::GetSelectedIndex(int32_t *aSelectedIndex)
+nsHTMLOptionCollection::GetSelectedIndex(int32_t* aSelectedIndex)
 {
   ErrorResult rv;
   *aSelectedIndex = GetSelectedIndex(rv);
   return rv.ErrorCode();
 }
 
 void
 nsHTMLOptionCollection::SetSelectedIndex(int32_t aSelectedIndex,
@@ -2150,23 +2150,23 @@ nsHTMLOptionCollection::Item(uint32_t aI
 }
 
 Element*
 nsHTMLOptionCollection::GetElementAt(uint32_t aIndex)
 {
   return ItemAsOption(aIndex);
 }
 
-static nsHTMLOptionElement*
-GetNamedItemHelper(nsTArray<nsRefPtr<nsHTMLOptionElement> > &aElements,
+static HTMLOptionElement*
+GetNamedItemHelper(nsTArray<nsRefPtr<HTMLOptionElement> > &aElements,
                    const nsAString& aName)
 {
   uint32_t count = aElements.Length();
   for (uint32_t i = 0; i < count; i++) {
-    nsHTMLOptionElement *content = aElements.ElementAt(i);
+    HTMLOptionElement* content = aElements.ElementAt(i);
     if (content &&
         (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, aName,
                               eCaseMatters) ||
          content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::id, aName,
                               eCaseMatters))) {
       return content;
     }
   }
@@ -2188,17 +2188,17 @@ nsHTMLOptionCollection::NamedItem(const 
 
   return NS_OK;
 }
 
 JSObject*
 nsHTMLOptionCollection::NamedItem(JSContext* cx, const nsAString& name,
                                   ErrorResult& error)
 {
-  nsINode *item = GetNamedItemHelper(mElements, name);
+  nsINode* item = GetNamedItemHelper(mElements, name);
   if (!item) {
     return nullptr;
   }
   JSObject* wrapper = nsWrapperCache::GetWrapper();
   JSAutoCompartment ac(cx, wrapper);
   JS::Value v;
   if (!mozilla::dom::WrapObject(cx, wrapper, item, item, nullptr, &v)) {
     error.Throw(NS_ERROR_FAILURE);
@@ -2207,17 +2207,17 @@ nsHTMLOptionCollection::NamedItem(JSCont
   return &v.toObject();
 }
 
 void
 nsHTMLOptionCollection::GetSupportedNames(nsTArray<nsString>& aNames)
 {
   nsAutoTArray<nsIAtom*, 8> atoms;
   for (uint32_t i = 0; i < mElements.Length(); ++i) {
-    nsHTMLOptionElement *content = mElements.ElementAt(i);
+    HTMLOptionElement* content = mElements.ElementAt(i);
     if (content) {
       // Note: HasName means the names is exposed on the document,
       // which is false for options, so we don't check it here.
       const nsAttrValue* val = content->GetParsedAttr(nsGkAtoms::name);
       if (val && val->Type() == nsAttrValue::eAtom) {
         nsIAtom* name = val->GetAtomValue();
         if (!atoms.Contains(name)) {
           atoms.AppendElement(name);
@@ -2234,25 +2234,25 @@ nsHTMLOptionCollection::GetSupportedName
 
   aNames.SetCapacity(atoms.Length());
   for (uint32_t i = 0; i < atoms.Length(); ++i) {
     aNames.AppendElement(nsDependentAtomString(atoms[i]));
   }
 }
 
 NS_IMETHODIMP
-nsHTMLOptionCollection::GetSelect(nsIDOMHTMLSelectElement **aReturn)
+nsHTMLOptionCollection::GetSelect(nsIDOMHTMLSelectElement** aReturn)
 {
   NS_IF_ADDREF(*aReturn = mSelect);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLOptionCollection::Add(nsIDOMHTMLOptionElement *aOption,
-                            nsIVariant *aBefore)
+nsHTMLOptionCollection::Add(nsIDOMHTMLOptionElement* aOption,
+                            nsIVariant* aBefore)
 {
   if (!aOption) {
     return NS_ERROR_INVALID_ARG;
   }
 
   if (!mSelect) {
     return NS_ERROR_NOT_INITIALIZED;
   }
--- a/content/html/content/src/nsHTMLSelectElement.h
+++ b/content/html/content/src/nsHTMLSelectElement.h
@@ -19,17 +19,17 @@
 
 // PresState
 #include "nsXPCOM.h"
 #include "nsPresState.h"
 #include "nsIComponentManager.h"
 #include "nsCheapSets.h"
 #include "nsError.h"
 #include "HTMLOptGroupElement.h"
-#include "nsHTMLOptionElement.h"
+#include "mozilla/dom/HTMLOptionElement.h"
 #include "nsHTMLFormElement.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/UnionTypes.h"
 
 class nsHTMLSelectElement;
 
 /**
  * The collection of options in the select (what you get back when you do
@@ -42,18 +42,18 @@ class nsHTMLOptionCollection: public nsI
 typedef mozilla::dom::HTMLOptionElementOrHTMLOptGroupElement HTMLOptionOrOptGroupElement;
 typedef mozilla::dom::HTMLElementOrLong HTMLElementOrLong;
 public:
   nsHTMLOptionCollection(nsHTMLSelectElement* aSelect);
   virtual ~nsHTMLOptionCollection();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
-  virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
-                               bool *triedToWrap);
+  virtual JSObject* WrapObject(JSContext* cx, JSObject* scope,
+                               bool* triedToWrap);
 
   // nsIDOMHTMLOptionsCollection interface
   NS_DECL_NSIDOMHTMLOPTIONSCOLLECTION
 
   // nsIDOMHTMLCollection interface, all its methods are defined in
   // nsIDOMHTMLOptionsCollection
 
   virtual mozilla::dom::Element* GetElementAt(uint32_t aIndex);
@@ -63,17 +63,17 @@ public:
                                                          nsIHTMLCollection)
 
   // Helpers for nsHTMLSelectElement
   /**
    * Insert an option
    * @param aOption the option to insert
    * @param aIndex the index to insert at
    */
-  void InsertOptionAt(nsHTMLOptionElement* aOption, uint32_t aIndex)
+  void InsertOptionAt(mozilla::dom::HTMLOptionElement* aOption, uint32_t aIndex)
   {
     mElements.InsertElementAt(aIndex, aOption);
   }
 
   /**
    * Remove an option
    * @param aIndex the index of the option to remove
    */
@@ -82,33 +82,33 @@ public:
     mElements.RemoveElementAt(aIndex);
   }
 
   /**
    * Get the option at the index
    * @param aIndex the index
    * @param aReturn the option returned [OUT]
    */
-  nsHTMLOptionElement *ItemAsOption(uint32_t aIndex)
+  mozilla::dom::HTMLOptionElement* ItemAsOption(uint32_t aIndex)
   {
     return mElements.SafeElementAt(aIndex, nullptr);
   }
 
   /**
    * Clears out all options
    */
   void Clear()
   {
     mElements.Clear();
   }
 
   /**
    * Append an option to end of array
    */
-  void AppendOption(nsHTMLOptionElement* aOption)
+  void AppendOption(mozilla::dom::HTMLOptionElement* aOption)
   {
     mElements.AppendElement(aOption);
   }
 
   /**
    * Drop the reference to the select.  Called during select destruction.
    */
   void DropReference();
@@ -131,27 +131,27 @@ public:
                               mozilla::ErrorResult& error);
 
   inline void Add(const HTMLOptionOrOptGroupElement& aElement,
                   const Nullable<HTMLElementOrLong>& aBefore,
                   mozilla::ErrorResult& aError);
   void Remove(int32_t aIndex, mozilla::ErrorResult& aError);
   int32_t GetSelectedIndex(mozilla::ErrorResult& aError);
   void SetSelectedIndex(int32_t aSelectedIndex, mozilla::ErrorResult& aError);
-  void IndexedSetter(uint32_t aIndex, nsIDOMHTMLOptionElement *aOption,
+  void IndexedSetter(uint32_t aIndex, nsIDOMHTMLOptionElement* aOption,
                      mozilla::ErrorResult& aError)
   {
     aError = SetOption(aIndex, aOption);
   }
   virtual void GetSupportedNames(nsTArray<nsString>& aNames);
 
 private:
   /** The list of options (holds strong references).  This is infallible, so
    * various members such as InsertOptionAt are also infallible. */
-  nsTArray<nsRefPtr<nsHTMLOptionElement> > mElements;
+  nsTArray<nsRefPtr<mozilla::dom::HTMLOptionElement> > mElements;
   /** The select element that contains this array */
   nsHTMLSelectElement* mSelect;
 };
 
 #define NS_SELECT_STATE_IID                        \
 { /* 4db54c7c-d159-455f-9d8e-f60ee466dbf3 */       \
   0x4db54c7c,                                      \
   0xd159,                                          \
@@ -251,21 +251,91 @@ public:
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
   virtual int32_t TabIndexDefault() MOZ_OVERRIDE;
 
   // nsIDOMHTMLSelectElement
   NS_DECL_NSIDOMHTMLSELECTELEMENT
 
+  // WebIdl HTMLSelectElement
+  bool Autofocus() const
+  {
+    return GetBoolAttr(nsGkAtoms::autofocus);
+  }
+  void SetAutofocus(bool aVal, mozilla::ErrorResult& aRv)
+  {
+    SetHTMLBoolAttr(nsGkAtoms::autofocus, aVal, aRv);
+  }
+  bool Disabled() const
+  {
+    return GetBoolAttr(nsGkAtoms::disabled);
+  }
+  void SetDisabled(bool aVal, mozilla::ErrorResult& aRv)
+  {
+    SetHTMLBoolAttr(nsGkAtoms::disabled, aVal, aRv);
+  }
+  nsHTMLFormElement* GetForm() const
+  {
+    return nsGenericHTMLFormElement::GetForm();
+  }
+  bool Multiple() const
+  {
+    return GetBoolAttr(nsGkAtoms::multiple);
+  }
+  void SetMultiple(bool aVal, mozilla::ErrorResult& aRv)
+  {
+    SetHTMLBoolAttr(nsGkAtoms::multiple, aVal, aRv);
+  }
+  void GetName(nsString& aName, mozilla::ErrorResult& aRv) const
+  {
+    GetHTMLAttr(nsGkAtoms::name, aName);
+  }
+  void SetName(const nsAString& aName, mozilla::ErrorResult& aRv)
+  {
+    SetHTMLAttr(nsGkAtoms::name, aName, aRv);
+  }
+  bool Required() const
+  {
+    return GetBoolAttr(nsGkAtoms::required);
+  }
+  void SetRequired(bool aVal, mozilla::ErrorResult& aRv)
+  {
+    SetHTMLBoolAttr(nsGkAtoms::required, aVal, aRv);
+  }
+  nsHTMLOptionCollection* Options() const
+  {
+    return mOptions;
+  }
+  void Remove(int32_t aIdx, mozilla::ErrorResult& aRv)
+  {
+    aRv = Remove(aIdx);
+  }
+  int32_t SelectedIndex() const
+  {
+    return mSelectedIndex;
+  }
+  void SetSelectedIndex(int32_t aIdx, mozilla::ErrorResult& aRv)
+  {
+    aRv = SetSelectedIndexInternal(aIdx, true);
+  }
+  mozilla::dom::Element* IndexedGetter(uint32_t aIdx, bool& aFound) const
+  {
+    return mOptions->IndexedGetter(aIdx, aFound);
+  }
+  uint32_t Length() const
+  {
+    return mOptions->Length();
+  }
+
   // nsIContent
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
   virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
 
-  virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex);
+  virtual bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, int32_t* aTabIndex);
   virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
                                  bool aNotify);
   virtual void RemoveChildAt(uint32_t aIndex, bool aNotify);
 
   // Overriden nsIFormControl methods
   NS_IMETHOD_(uint32_t) GetType() const { return NS_FORM_SELECT; }
   NS_IMETHOD Reset();
   NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission);
@@ -306,17 +376,17 @@ public:
 
   /**
    * Checks whether an option is disabled (even if it's part of an optgroup)
    *
    * @param aIndex the index of the option to check
    * @return whether the option is disabled
    */
   NS_IMETHOD IsOptionDisabled(int32_t aIndex,
-                              bool *aIsDisabled);
+                              bool* aIsDisabled);
 
   /**
    * Sets multiple options (or just sets startIndex if select is single)
    * and handles notifications and cleanup and everything under the sun.
    * When this method exits, the select will be in a consistent state.  i.e.
    * if you set the last option to false, it will select an option anyway.
    *
    * @param aStartIndex the first index to set
@@ -375,27 +445,27 @@ public:
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               int32_t aModType) const;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
-  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+  virtual nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const;
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLSelectElement,
                                            nsGenericHTMLFormElement)
 
-  nsHTMLOptionCollection *GetOptions()
+  nsHTMLOptionCollection* GetOptions()
   {
     return mOptions;
   }
 
-  static nsHTMLSelectElement *FromSupports(nsISupports *aSupports)
+  static nsHTMLSelectElement* FromSupports(nsISupports* aSupports)
   {
     return static_cast<nsHTMLSelectElement*>(static_cast<nsINode*>(aSupports));
   }
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual nsIDOMNode* AsDOMNode() { return this; }
 
@@ -447,17 +517,17 @@ protected:
   bool CheckSelectSomething(bool aNotify);
   /**
    * Called to trigger notifications of frames and fixing selected index
    *
    * @param aSelectFrame the frame for this content (could be null)
    * @param aIndex the index that was selected or deselected
    * @param aSelected whether the index was selected or deselected
    * @param aChangeOptionState if false, don't do anything to the
-   *                           nsHTMLOptionElement at aIndex.  If true, change
+   *                           HTMLOptionElement at aIndex.  If true, change
    *                           its selected state to aSelected.
    * @param aNotify whether to notify the style system and such
    */
   void OnOptionSelected(nsISelectControlFrame* aSelectFrame,
                         int32_t aIndex,
                         bool aSelected,
                         bool aChangeOptionState,
                         bool aNotify);
@@ -552,17 +622,17 @@ protected:
   int32_t GetFirstChildOptionIndex(nsIContent* aOptions,
                                    int32_t aStartIndex,
                                    int32_t aEndIndex);
 
   /**
    * Get the frame as an nsISelectControlFrame (MAY RETURN NULL)
    * @return the select frame, or null
    */
-  nsISelectControlFrame *GetSelectFrame();
+  nsISelectControlFrame* GetSelectFrame();
 
   /**
    * Is this a combobox?
    */
   bool IsCombobox() {
     if (HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)) {
       return false;
     }
@@ -660,17 +730,17 @@ protected:
 
 void
 nsHTMLOptionCollection::Add(const HTMLOptionOrOptGroupElement& aElement,
                             const Nullable<HTMLElementOrLong>& aBefore,
                             mozilla::ErrorResult& aError)
 {
   nsGenericHTMLElement& element =
     aElement.IsHTMLOptionElement() ?
-    static_cast<nsGenericHTMLElement&>(*aElement.GetAsHTMLOptionElement()) :
+    static_cast<nsGenericHTMLElement&>(aElement.GetAsHTMLOptionElement()) :
     static_cast<nsGenericHTMLElement&>(aElement.GetAsHTMLOptGroupElement());
 
   if (aBefore.IsNull()) {
     mSelect->Add(element, (nsGenericHTMLElement*)nullptr, aError);
   } else if (aBefore.Value().IsHTMLElement()) {
     mSelect->Add(element, &aBefore.Value().GetAsHTMLElement(), aError);
   } else {
     mSelect->Add(element, aBefore.Value().GetAsLong(), aError);
--- a/content/html/content/src/nsTextEditorState.cpp
+++ b/content/html/content/src/nsTextEditorState.cpp
@@ -1598,17 +1598,17 @@ nsTextEditorState::InitializeRootNode()
   if (wrapCols >= 0) {
     classValue.AppendLiteral(" wrap");
   }
   if (!IsSingleLineTextControl()) {
     // We can't just inherit the overflow because setting visible overflow will
     // crash when the number of lines exceeds the height of the textarea and
     // setting -moz-hidden-unscrollable overflow (NS_STYLE_OVERFLOW_CLIP)
     // doesn't paint the caret for some reason.
-    const nsStyleDisplay* disp = mBoundFrame->GetStyleDisplay();
+    const nsStyleDisplay* disp = mBoundFrame->StyleDisplay();
     if (disp->mOverflowX != NS_STYLE_OVERFLOW_VISIBLE &&
         disp->mOverflowX != NS_STYLE_OVERFLOW_CLIP) {
       classValue.AppendLiteral(" inherit-overflow");
     }
   }
   nsresult rv = mRootNode->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
                                    classValue, false);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -154,17 +154,16 @@ MOCHITEST_FILES = \
 		test_bug564001.html \
 		test_bug566046.html \
 		test_bug567938-1.html \
 		test_bug567938-2.html \
 		test_bug567938-3.html \
 		test_bug567938-4.html \
 		test_bug569955.html \
 		test_bug573969.html \
-		test_bug585508.html \
 		test_bug561640.html \
 		test_bug566064.html \
 		test_bug582412-1.html \
 		test_bug582412-2.html \
 		test_bug558788-1.html \
 		test_bug558788-2.html \
 		test_bug561634.html \
 		test_bug590353-1.html \
@@ -275,16 +274,17 @@ MOCHITEST_FILES = \
 		test_input_file_picker.html \
 		test_bug763626.html \
 		test_bug780993.html \
 		test_bug797113.html \
 		test_bug787134.html \
 		test_bug803677.html \
 		test_bug827126.html \
 		test_bug827426.html \
+		test_bug841466.html \
 		test_iframe_sandbox_inheritance.html \
 		file_iframe_sandbox_a_if1.html \
 		file_iframe_sandbox_a_if2.html \
 		file_iframe_sandbox_a_if3.html \
 		file_iframe_sandbox_a_if4.html \
 		file_iframe_sandbox_a_if5.html \
 		file_iframe_sandbox_a_if6.html \
 		file_iframe_sandbox_a_if7.html \
--- a/content/html/content/test/forms/test_button_attributes_reflection.html
+++ b/content/html/content/test/forms/test_button_attributes_reflection.html
@@ -35,37 +35,33 @@ reflectLimitedEnumerated({
   element: document.createElement("button"),
   attribute: "formEnctype",
   validValues: [
     "application/x-www-form-urlencoded",
     "multipart/form-data",
     "text/plain",
   ],
   invalidValues: [ "text/html", "", "tulip" ],
-// TODO (Bug 839171):
-//  defaultValue: {
-//    invalid: "application/x-www-form-urlencoded",
-//    missing: "",
-//  }
-  defaultValue: "application/x-www-form-urlencoded",
+  defaultValue: {
+    invalid: "application/x-www-form-urlencoded",
+    missing: "",
+  }
 });
 
 // .formMethod
 reflectLimitedEnumerated({
   element: document.createElement("button"),
   attribute: "formMethod",
   validValues: [ "get", "post" ],
   invalidValues: [ "put", "", "tulip" ],
   unsupportedValues: [ "dialog" ],
-// TODO (Bug 839171):
-//  defaultValue: {
-//    invalid: "get",
-//    missing: "",
-//  }
-  defaultValue: "get",
+  defaultValue: {
+    invalid: "get",
+    missing: "",
+  }
 });
 
 // .formNoValidate
 reflectBoolean({
   element: document.createElement("button"),
   attribute: "formNoValidate",
 });
 
--- a/content/html/content/test/forms/test_input_attributes_reflection.html
+++ b/content/html/content/test/forms/test_input_attributes_reflection.html
@@ -199,21 +199,21 @@ reflectString({
 });
 
 // .type
 reflectLimitedEnumerated({
   element: document.createElement("input"),
   attribute: "type",
   validValues: [ "hidden", "text", "search", "tel", "url", "email", "password",
                  "checkbox", "radio", "file", "submit", "image", "reset",
-                 "button", "date", "time", "number" ],
+                 "button", "date", "time", "number", "range" ],
   invalidValues: [ "this-is-probably-a-wrong-type", "", "tulip" ],
   defaultValue: "text",
   unsupportedValues: [ "datetime", "month", "week", "datetime-local",
-                       "range", "color" ]
+                       "color" ]
 });
 
 // .defaultValue
 reflectString({
   element: document.createElement("input"),
   attribute: { idl: "defaultValue", content: "value" },
   otherValues: [ "foo\nbar", "foo\rbar", "foo\r\nbar" ],
 });
--- a/content/html/content/test/forms/test_input_sanitization.html
+++ b/content/html/content/test/forms/test_input_sanitization.html
@@ -13,30 +13,46 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"></p>
 <pre id="test">
 <div id='content'>
   <form>
   </form>
 </div>
 <script type="application/javascript">
 
-/** Test for Bug 549475 **/
+/**
+ * This files tests the 'value sanitization algorithm' for the various input
+ * types. Note that an input's value is affected by more than just its type's
+ * value sanitization algorithm; e.g. some type=range has actions that the user
+ * agent must perform to change the element's value to avoid underflow/overflow
+ * and step mismatch (when possible). We specifically avoid triggering these
+ * other actions here so that this test only tests the value sanitization
+ * algorithm for the various input types.
+ *
+ * XXXjwatt splitting out testing of the value sanitization algorithm and 
+ * "other things" that affect .value makes it harder to know what we're testing
+ * and what we've missed, because what's included in the value sanitization
+ * algorithm and what's not is different from input type to input type. It
+ * seems to me it would be better to have a test (maybe one per type) focused
+ * on testing .value for permutations of all other inputs that can affect it.
+ * The value sanitization algorithm is just an internal spec concept after all.
+ */
 
 // We are excluding "file" because it's too different from the other types.
 // And it has no sanitizing algorithm.
 var inputTypes =
 [
   "text", "password", "search", "tel", "hidden", "checkbox", "radio",
   "submit", "image", "reset", "button", "email", "url", "number", "date",
-  "time",
+  "time", "range"
 ];
 
 var todoTypes =
 [
-  "range", "color",
+  "color",
   "month", "week", "datetime", "datetime-local",
 ];
 
 var valueModeValue =
 [
   "text", "search", "url", "tel", "email", "password", "date", "datetime",
   "month", "week", "time", "datetime-local", "number", "range", "color",
 ];
@@ -50,16 +66,30 @@ function sanitizeValue(aType, aValue)
     case "search":
     case "tel":
       return aValue.replace(/[\n\r]/g, "");
     case "url":
     case "email":
       return aValue.replace(/[\n\r]/g, "").replace(/^[\u0020\u0009\t\u000a\u000c\u000d]+|[\u0020\u0009\t\u000a\u000c\u000d]+$/g, "");
     case "number":
       return isNaN(Number(aValue)) ? "" : aValue;
+    case "range":
+      var defaultMinimum = 0;
+      var defaultMaximum = 100;
+      var value = Number(aValue);
+      if (isNaN(value)) {
+        return ((defaultMaximum - defaultMinimum)/2).toString(); // "50"
+      }
+      if (value < defaultMinimum) {
+        return defaultMinimum.toString();
+      }
+      if (value > defaultMaximum) {
+        return defaultMaximum.toString();
+      }
+      return aValue;
     case "date":
       // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#valid-date-string
       function getNumbersOfDaysInMonth(aMonth, aYear) {
         if (aMonth === 2) {
           return (aYear % 400 === 0 || (aYear % 100 != 0 && aYear % 4 === 0)) ? 29 : 28;
         }
         return (aMonth === 1 || aMonth === 3 || aMonth === 5 || aMonth === 7 ||
                 aMonth === 8 || aMonth === 10 || aMonth === 12) ? 31 : 30;
@@ -116,20 +146,16 @@ function sanitizeValue(aType, aValue)
       return aValue;
     case "month":
     case "week":
     case "datetime":
     case "datetime-local":
       // TODO: write the sanitize algorithm.
       ok(false);
       return "";
-    case "range":
-      ok(false);
-      // TODO: write the sanitize algorithm.
-      return "";
     case "color":
       ok(false);
       // TODO: write the sanitize algorithm.
       return "";
     default:
       return aValue;
   }
 }
@@ -146,17 +172,17 @@ function checkSanitizing(element)
     // For url:
     "\r\n foobar    \n\r",
     "\u000B foo \u000B",
     "\u000A foo \u000A",
     "\u000C foo \u000C",
     "\u000d foo \u000d",
     "\u0020 foo \u0020",
     " \u0009 foo \u0009 ",
-    // For number:
+    // For number and range:
     "42",
     "13.37",
     "1.234567898765432",
     "12foo",
     "1e2",
     "3E42",
     // For date:
     "1970-01-01",
--- a/content/html/content/test/forms/test_max_attribute.html
+++ b/content/html/content/test/forms/test_max_attribute.html
@@ -29,30 +29,43 @@ var data = [
   { type: 'password', apply: false },
   { type: 'datetime', apply: true, todo: true },
   { type: 'date', apply: true },
   { type: 'month', apply: true, todo: true },
   { type: 'week', apply: true, todo: true },
   { type: 'time', apply: true },
   { type: 'datetime-local', apply: true, todo: true },
   { type: 'number', apply: true },
-  { type: 'range', apply: true, todo: true },
+  { type: 'range', apply: true },
   { type: 'color', apply: false, todo: true },
   { type: 'checkbox', apply: false },
   { type: 'radio', apply: false },
   { type: 'file', apply: false },
   { type: 'submit', apply: false },
   { type: 'image', apply: false },
   { type: 'reset', apply: false },
   { type: 'button', apply: false },
 ];
 
 var input = document.createElement("input");
 document.getElementById('content').appendChild(input);
 
+/**
+ * @aValidity - boolean indicating whether the element is expected to be valid
+ *   (aElement.validity.valid is true) or not. The value passed is ignored and
+ *   overridden with true if aApply is false.
+ * @aApply - boolean indicating whether the min/max attributes apply to this
+ *   element type.
+ * @aRangeApply - A boolean that's set to true if the current input type is a
+ *   "[candidate] for constraint validation" and it "[has] range limitations"
+ *   per http://www.whatwg.org/specs/web-apps/current-work/multipage/selectors.html#selector-in-range
+ *   (in other words, one of the pseudo classes :in-range and :out-of-range
+ *   should apply (which, depends on aValidity)).
+ *   Else (neither :in-range or :out-of-range should match) set to false.
+ */
 function checkValidity(aElement, aValidity, aApply, aRangeApply)
 {
   aValidity = aApply ? aValidity : true;
 
   is(aElement.validity.valid, aValidity,
      "element validity should be " + aValidity);
   is(aElement.validity.rangeOverflow, !aValidity,
      "element overflow status should be " + !aValidity);
@@ -81,17 +94,25 @@ for (var test of data) {
   input.type = test.type;
   var apply = test.apply;
 
   if (test.todo) {
     todo_is(input.type, test.type, test.type + " isn't implemented yet");
     continue;
   }
 
-  checkValidity(input, true, apply, false);
+  // The element should be valid. Range should not apply when @min and @max are
+  // undefined, except if the input type is 'range' (since that type has a
+  // default minimum and maximum).
+  if (input.type == 'range') {
+    checkValidity(input, true, apply, true);
+  } else {
+    checkValidity(input, true, apply, false);
+  }
+  checkValidity(input, true, apply, test.type == 'range');
 
   switch (input.type) {
     case 'hidden':
     case 'text':
     case 'search':
     case 'password':
     case 'url':
     case 'tel':
@@ -107,16 +128,24 @@ for (var test of data) {
       input.max = '-1';
       break;
     case 'date':
       input.max = '2012-06-27';
       break;
     case 'time':
       input.max = '02:20';
       break;
+    case 'range':
+      // range is special, since setting max to -1 will make it invalid since
+      // it's default would then be 0, meaning it suffers from overflow.
+      input.max = '-1';
+      checkValidity(input, false, apply, apply);
+      // Now make it something that won't cause an error below:
+      input.max = '10';
+      break;
     default:
       ok(false, 'please, add a case for this new type (' + input.type + ')');
   }
 
   checkValidity(input, true, apply, apply);
 
   switch (input.type) {
     case 'text':
@@ -231,16 +260,56 @@ for (var test of data) {
         input.max = "4.333333333333333333333333333333333331";
         input.value = "5";
         is(input.validationMessage,
            "Please select a value that is lower than 4.33333333333333.",
            "validation message");
       }
 
       break;
+    case 'range':
+      input.max = '2';
+      input.value = '1';
+      checkValidity(input, true, apply, apply);
+
+      input.value = '2';
+      checkValidity(input, true, apply, apply);
+
+      input.value = 'foo';
+      checkValidity(input, true, apply, apply);
+
+      input.value = '3';
+      checkValidity(input, true, apply, apply);
+
+      is(input.value, input.max, "the value should have been set to max");
+
+      input.max = '5';
+      checkValidity(input, true, apply, apply);
+
+      input.value = '42';
+      checkValidity(input, true, apply, apply);
+
+      is(input.value, input.max, "the value should have been set to max");
+
+      input.max = '';
+      checkValidity(input, true, apply, apply);
+
+      input.max = 'foo';
+      checkValidity(input, true, apply, apply);
+
+      // Check that we correctly convert input.max to a double in validationMessage.
+      input.step = 'any';
+      input.min = 5;
+      input.max = 0.66666666666666666666666666666666666
+      input.value = 1;
+      is(input.validationMessage,
+         "Please select a value that is lower than 0.666666666666667.",
+         "validation message")
+
+      break;
     case 'time':
       // Don't worry about that.
       input.step = 'any';
 
       input.max = '10:10';
       input.value = '10:09';
       checkValidity(input, true, apply, apply);
 
--- a/content/html/content/test/forms/test_min_attribute.html
+++ b/content/html/content/test/forms/test_min_attribute.html
@@ -29,30 +29,43 @@ var data = [
   { type: 'password', apply: false },
   { type: 'datetime', apply: true, todo: true },
   { type: 'date', apply: true },
   { type: 'month', apply: true, todo: true },
   { type: 'week', apply: true, todo: true },
   { type: 'time', apply: true },
   { type: 'datetime-local', apply: true, todo: true },
   { type: 'number', apply: true },
-  { type: 'range', apply: true, todo: true },
+  { type: 'range', apply: true },
   { type: 'color', apply: false, todo: true },
   { type: 'checkbox', apply: false },
   { type: 'radio', apply: false },
   { type: 'file', apply: false },
   { type: 'submit', apply: false },
   { type: 'image', apply: false },
   { type: 'reset', apply: false },
   { type: 'button', apply: false },
 ];
 
 var input = document.createElement("input");
 document.getElementById('content').appendChild(input);
 
+/**
+ * @aValidity - boolean indicating whether the element is expected to be valid
+ *   (aElement.validity.valid is true) or not. The value passed is ignored and
+ *   overridden with true if aApply is false.
+ * @aApply - boolean indicating whether the min/max attributes apply to this
+ *   element type.
+ * @aRangeApply - A boolean that's set to true if the current input type is a
+ *   "[candidate] for constraint validation" and it "[has] range limitations"
+ *   per http://www.whatwg.org/specs/web-apps/current-work/multipage/selectors.html#selector-in-range
+ *   (in other words, one of the pseudo classes :in-range and :out-of-range
+ *   should apply (which, depends on aValidity)).
+ *   Else (neither :in-range or :out-of-range should match) set to false.
+ */
 function checkValidity(aElement, aValidity, aApply, aRangeApply)
 {
   aValidity = aApply ? aValidity : true;
 
   is(aElement.validity.valid, aValidity,
      "element validity should be " + aValidity);
   is(aElement.validity.rangeUnderflow, !aValidity,
      "element underflow status should be " + !aValidity);
@@ -81,18 +94,24 @@ for (var test of data) {
   input.type = test.type;
   var apply = test.apply;
 
   if (test.todo) {
     todo_is(input.type, test.type, test.type + " isn't implemented yet");
     continue;
   }
 
-  // The element should be valid. Range should not apply.
-  checkValidity(input, true, apply, false);
+  // The element should be valid. Range should not apply when @min and @max are
+  // undefined, except if the input type is 'range' (since that type has a
+  // default minimum and maximum).
+  if (input.type == 'range') {
+    checkValidity(input, true, apply, true);
+  } else {
+    checkValidity(input, true, apply, false);
+  }
 
   switch (input.type) {
     case 'hidden':
     case 'text':
     case 'search':
     case 'password':
     case 'url':
     case 'tel':
@@ -108,16 +127,21 @@ for (var test of data) {
       input.min = '999';
       break;
     case 'date':
       input.min = '2012-06-27';
       break;
     case 'time':
       input.min = '20:20';
       break;
+    case 'range':
+      // range is special, since setting min to 999 will make it invalid since
+      // it's default maximum is 100, its value would be 999, and it would
+      // suffer from overflow.
+      break;
     default:
       ok(false, 'please, add a case for this new type (' + input.type + ')');
   }
 
   // The element should still be valid and range should apply if it can.
   checkValidity(input, true, apply, apply);
 
   switch (input.type) {
@@ -229,16 +253,52 @@ for (var test of data) {
       // Check that we correctly convert input.min to a double in
       // validationMessage.
       input.min = "4.333333333333333333333333333333333331";
       input.value = "2";
       is(input.validationMessage,
          "Please select a value that is higher than 4.33333333333333.",
          "validation message");
       break;
+    case 'range':
+      input.min = '0';
+      input.value = '1';
+      checkValidity(input, true, apply, apply);
+
+      input.value = '0';
+      checkValidity(input, true, apply, apply);
+
+      input.value = 'foo';
+      checkValidity(input, true, apply, apply);
+
+      input.value = '-1';
+      checkValidity(input, true, apply, apply);
+
+      is(input.value, input.min, "the value should have been set to min");
+
+      input.min = '-1';
+      checkValidity(input, true, apply, apply);
+
+      input.value = '-42';
+      checkValidity(input, true, apply, apply);
+
+      is(input.value, input.min, "the value should have been set to min");
+
+      input.min = '';
+      checkValidity(input, true, apply, true);
+
+      input.min = 'foo';
+      checkValidity(input, true, apply, true);
+
+      // We don't check the conversion of input.min to a double in
+      // validationMessage for 'range' since range will always clamp the value
+      // up to at least the minimum (so we will never see the min in a
+      // validationMessage).
+
+      break;
     case 'time':
       // Don't worry about that.
       input.step = 'any';
 
       input.min = '20:20';
       input.value = '20:20:01';
       checkValidity(input, true, apply, apply);
 
--- a/content/html/content/test/forms/test_mozistextfield.html
+++ b/content/html/content/test/forms/test_mozistextfield.html
@@ -43,27 +43,27 @@ var gInputTestData = [
   ['reset',    false],
   ['image',    false],
   ['radio',    false],
   ['submit',   false],
   ['search',   true],
   ['email',    true],
   ['url',      true],
   ['number',   false],
+  ['range',    false],
   ['date',     false],
   ['time',     false],
 ];
 
 /**
  * TODO: the next types are not yet in the tree.
  * The value is only a suggestion.
  */
 var gInputTodoData = [
 /* type        expected result */
-  ['range',    false],
   ['color',    false],
   ['datetime', false],
   ['month',    false],
   ['week',     false],
   ['datetime-local', false],
 ];
 
 function checkMozIsTextFieldDefined(aElement, aResult)
--- a/content/html/content/test/forms/test_pattern_attribute.html
+++ b/content/html/content/test/forms/test_pattern_attribute.html
@@ -256,18 +256,18 @@ function checkPatternValidity(element)
 }
 
 var input = document.getElementById('i');
 
 // |validTypes| are the types which accept @pattern
 // and |invalidTypes| are the ones which do not accept it.
 var validTypes = Array('text', 'password', 'search', 'tel', 'email', 'url');
 var barredTypes = Array('hidden', 'reset', 'button', 'submit', 'image');
-var invalidTypes = Array('checkbox', 'radio', 'file', 'number', 'date', 'time');
-// TODO: 'datetime', 'month', 'week', 'datetime-local', 'range' and 'color'
+var invalidTypes = Array('checkbox', 'radio', 'file', 'number', 'range', 'date', 'time');
+// TODO: 'datetime', 'month', 'week', 'datetime-local' and 'color'
 //       do not accept the @pattern too but are not implemented yet.
 
 for (type of validTypes) {
   input.type = type;
   completeValidityCheck(input, false);
   checkPatternValidity(input);
 }
 
--- a/content/html/content/test/forms/test_required_attribute.html
+++ b/content/html/content/test/forms/test_required_attribute.html
@@ -362,18 +362,18 @@ checkTextareaRequiredValidity();
 // First of all, checks for types that make the element barred from
 // constraint validation.
 var typeBarredFromConstraintValidation = ["hidden", "button", "reset", "submit", "image"];
 for (type of typeBarredFromConstraintValidation) {
   checkInputRequiredNotApply(type, true);
 }
 
 // Then, checks for the types which do not use the required attribute.
-// TODO: check 'color' and 'range' when they will be implemented.
-var typeRequireNotApply = [];
+// TODO: check 'color' when they will be implemented.
+var typeRequireNotApply = ['range'];
 for (type of typeRequireNotApply) {
   checkInputRequiredNotApply(type, false);
 }
 
 // Now, checking for all types which accept the required attribute.
 // TODO: check 'datetime', 'month', 'week' and 'datetime-local'
 //       when they will be implemented.
 var typeRequireApply = ["text", "password", "search", "tel", "email", "url",
--- a/content/html/content/test/forms/test_step_attribute.html
+++ b/content/html/content/test/forms/test_step_attribute.html
@@ -29,17 +29,17 @@ var data = [
   { type: 'password', apply: false },
   { type: 'datetime', apply: true, todo: true },
   { type: 'date', apply: true },
   { type: 'month', apply: true, todo: true },
   { type: 'week', apply: true, todo: true },
   { type: 'time', apply: true },
   { type: 'datetime-local', apply: true, todo: true },
   { type: 'number', apply: true },
-  { type: 'range', apply: true, todo: true },
+  { type: 'range', apply: true },
   { type: 'color', apply: false, todo: true },
   { type: 'checkbox', apply: false },
   { type: 'radio', apply: false },
   { type: 'file', apply: false },
   { type: 'submit', apply: false },
   { type: 'image', apply: false },
   { type: 'reset', apply: false },
   { type: 'button', apply: false },
@@ -412,16 +412,223 @@ for (var test of data) {
       input.min = '1';
       input.max = '10.9';
       input.value = '10';
 
       is(input.validationMessage, "Please select a valid value. " +
                                   "The nearest valid value is 9.",
          "The validation message should not include the higher value.");
       break;
+    case 'range':
+      // Range is special in that it clamps to valid values, so it is much
+      // rarer for it to be invalid.
+
+      // When step=0, the allowed value step is 1.
+      input.step = '0';
+      input.value = '1.2';
+      is(input.value, 1, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+      checkValidity(input, true, apply);
+
+      input.value = '1';
+      is(input.value, 1, "check that the value coincides with a step");
+      checkValidity(input, true, apply);
+
+      input.value = '0';
+      is(input.value, 0, "check that the value coincides with a step");
+      checkValidity(input, true, apply);
+
+      // When step is NaN, the allowed step value is 1.
+      input.step = 'foo';
+      input.value = '1';
+      is(input.value, 1, "check that the value coincides with a step");
+      checkValidity(input, true, apply);
+
+      input.value = '1.5';
+      is(input.value, 2, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+      checkValidity(input, true, apply);
+
+      // When step is negative, the allowed step value is 1.
+      input.step = '-0.1';
+      is(input.value, 2, "check that the value still coincides with a step");
+      checkValidity(input, true, apply);
+
+      input.value = '1';
+      is(input.value, 1, "check that the value coincides with a step");
+      checkValidity(input, true, apply);
+
+      // When step is missing, the allowed step value is 1.
+      input.removeAttribute('step');
+      input.value = '1.5';
+      is(input.value, 2, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+      checkValidity(input, true, apply);
+
+      input.value = '1';
+      is(input.value, 1, "check that the value coincides with a step");
+      checkValidity(input, true, apply);
+
+      // When step is 'any', all values are fine wrt to step.
+      input.step = 'any';
+      checkValidity(input, true, apply);
+
+      input.step = 'aNy';
+      input.value = '97';
+      is(input.value, 97, "check that the value for step=aNy is unchanged");
+      checkValidity(input, true, apply);
+
+      input.step = 'AnY';
+      input.value = '0.1';
+      is(input.value, 0.1, "check that a positive fractional value with step=AnY is unchanged");
+      checkValidity(input, true, apply);
+
+      input.step = 'ANY';
+      input.min = -100;
+      input.value = '-13.37';
+      is(input.value, -13.37, "check that a negative fractional value with step=ANY is unchanged");
+      checkValidity(input, true, apply);
+
+      // When min is set to a valid float, there is a step base.
+      input.min = '1'; // the step base
+      input.step = '2';
+      input.value = '3';
+      is(input.value, 3, "check that the value coincides with a step");
+      checkValidity(input, true, apply);
+
+      input.value = '2';
+      is(input.value, 3, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+      checkValidity(input, true, apply);
+
+      input.value = '1.99';
+      is(input.value, 1, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+      checkValidity(input, true, apply);
+
+      input.removeAttribute('step'); // step = 1
+      input.min = '0.5'; // step base
+      input.value = '5.5';
+      is(input.value, 5.5, "check that the value coincides with a step");
+      checkValidity(input, true, apply);
+
+      input.value = '1';
+      is(input.value, 1.5, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+      checkValidity(input, true, apply);
+
+      input.min = '-0.1'; // step base
+      input.step = '1';
+      input.value = '0.9';
+      is(input.value, 0.9, "the value should be a valid step");
+      checkValidity(input, true, apply);
+
+      input.value = '0.1';
+      is(input.value, -0.1, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+      checkValidity(input, true, apply);
+
+      // When min is set to NaN, the step base is the value.
+      input.min = 'foo';
+      input.step = '1';
+      input.value = '1';
+      is(input.value, 1, "check that the value coincides with a step");
+      checkValidity(input, true, apply);
+
+      input.value = '0.5';
+      is(input.value, 1, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+      checkValidity(input, true, apply);
+
+      input.min = '';
+      input.value = '1';
+      is(input.value, 1, "check that the value coincides with a step");
+      checkValidity(input, true, apply);
+
+      input.value = '0.5';
+      is(input.value, 1, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+      checkValidity(input, true, apply);
+
+      input.removeAttribute('min');
+
+      // Test when the value isn't a number
+      input.value = '';
+      is(input.value, 50, "value be should default to the value midway between the minimum (0) and the maximum (100)");
+      checkValidity(input, true, apply);
+
+      // Regular situations.
+      input.step = '2';
+      input.value = '1.5';
+      is(input.value, 2, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+      checkValidity(input, true, apply);
+
+      input.value = '42.0';
+      is(input.value, 42, "check that the value coincides with a step");
+      checkValidity(input, true, apply);
+
+      input.step = '0.1';
+      input.value = '-0.1';
+      is(input.value, 0, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+      checkValidity(input, true, apply);
+
+      input.step = '2';
+      input.removeAttribute('min');
+      input.max = '10';
+      input.value = '-9';
+      is(input.value, 0, "check the value is clamped to the minimum's default of zero");
+      checkValidity(input, true, apply);
+
+      // If @value is defined but not @min, the step base is @value.
+      input = getFreshElement(test.type);
+      input.setAttribute('value', '1');
+      input.step = 2;
+      is(input.value, 1, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+      checkValidity(input, true, apply);
+
+      input.value = 3;
+      is(input.value, 3, "check that the value coincides with a step");
+      checkValidity(input, true, apply);
+
+      input.value = 2;
+      is(input.value, 3, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+      checkValidity(input, true, apply);
+
+      // Should also work with defaultValue.
+      input = getFreshElement(test.type);
+      input.defaultValue = 1;
+      input.step = 2;
+      is(input.value, 1, "check that the value coincides with a step");
+      checkValidity(input, true, apply);
+
+      input.value = 3;
+      is(input.value, 3, "check that the value coincides with a step");
+      checkValidity(input, true, apply);
+
+      input.value = 2;
+      is(input.value, 3, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+      checkValidity(input, true, apply);
+
+      // Check contrived error case where there are no valid steps in range:
+      // No @min, so the step base is the default minimum, zero, the valid
+      // range is 0-1, -1 gets clamped to zero.
+      input = getFreshElement(test.type);
+      input.step = '3';
+      input.max = '1';
+      input.defaultValue = '-1';
+      is(input.value, 0, "the value should have been clamped to the default minimum, zero");
+      checkValidity(input, false, apply, {low: -1, high: -1});
+
+      // Check that when the closest of the two steps that the value is between
+      // is greater than the maximum we sanitize to the lower step.
+      input = getFreshElement(test.type);
+      input.step = '2';
+      input.min = '1';
+      input.max = '10.9';
+      input.value = '10.8'; // closest step in 11, but 11 > maximum
+      is(input.value, 9, "check that the value coincides with a step");
+
+      // The way that step base is defined, the converse (the value not being
+      // on a step, and the nearest step being a value that would be underflow)
+      // is not possible, so nothing to test there.
+
+      is(input.validationMessage, "",
+         "The validation message should be empty.");
+      break;
     case 'time':
       // Tests invalid step values. That defaults to step = 1 minute (60).
       var values = [ '0', '-1', 'foo', 'any', 'ANY', 'aNy' ];
       for (var value of values) {
         input.step = value;
         input.value = '19:06:00';
         checkValidity(input, true, apply);
         input.value = '19:06:51';
--- a/content/html/content/test/forms/test_stepup_stepdown.html
+++ b/content/html/content/test/forms/test_stepup_stepdown.html
@@ -42,30 +42,30 @@ function checkAvailability()
     ["checkbox", false],
     ["radio", false],
     ["file", false],
     ["submit", false],
     ["image", false],
     ["reset", false],
     ["button", false],
     ["number", true],
+    ["range", true],
     ["date", true],
     ["time", true],
     // The next types have not been implemented but will fallback to "text"
     // which has the same value.
     ["color", false],
   ];
 
   var todoList =
   [
     ["datetime", true],
     ["month", true],
     ["week", true],
     ["datetime-local", true],
-    ["range", true],
   ];
 
   var element = document.createElement("input");
   element.setAttribute('value', '0');
 
   for (data of testData) {
     var exceptionCaught = false;
     element.type = data[0];
@@ -175,16 +175,83 @@ function checkStepDown()
     // With step = 'any'.
     [ '0',  'any',  null,  null,  1,    null,   true ],
     [ '0',  'ANY',  null,  null,  1,    null,   true ],
     [ '0',  'AnY',  null,  null,  1,    null,   true ],
     [ '0',  'aNy',  null,  null,  1,    null,   true ],
     // With @value = step base.
     [ '1',  '2',    null,  null,  null, '-1',   false ],
   ]},
+  { type: 'range', data: [
+    // Regular case.
+    [ '1',   null,  null,  null,  null, '0',    false ],
+    // Argument testing.
+    [ '1',   null,  null,  null,  1,    '0',    false ],
+    [ '9',   null,  null,  null,  9,    '0',    false ],
+    [ '1',   null,  null,  null,  -1,   '2',    false ],
+    [ '1',   null,  null,  null,  0,    '1',    false ],
+    // Float values are rounded to integer (1.1 -> 1).
+    [ '1',   null,  null,  null,  1.1,  '0',    false ],
+    // With step values.
+    [ '1',  '0.5',  null,  null,  null, '0.5',  false ],
+    [ '1',  '0.25', null,  null,  4,    '0',    false ],
+    // step = 0 isn't allowed (-> step = 1).
+    [ '1',  '0',    null,  null,  null, '0',    false ],
+    // step < 0 isn't allowed (-> step = 1).
+    [ '1',  '-1',   null,  null,  null, '0',    false ],
+    // step = NaN isn't allowed (-> step = 1).
+    [ '1',  'foo',  null,  null,  null, '0',    false ],
+    // Min values testing.
+    [ '1',  '1',    'foo', null,  null, '0',    false ],
+    [ '1',  null,   '-10', null,  null, '0',    false ],
+    [ '1',  null,   '0',   null,  null, '0',    false ],
+    [ '1',  null,   '10',  null,  null, '10',   false ],
+    [ '1',  null,   '2',   null,  null, '2',    false ],
+    [ '1',  null,   '1',   null,  null, '1',    false ],
+    // Max values testing.
+    [ '1',  '1',    null,  'foo', null, '0',    false ],
+    [ '1',  null,   null,  '10',  null, '0',    false ],
+    [ '1',  null,   null,  '0',   null, '0',    false ],
+    [ '1',  null,   null,  '-10', null, '0',    false ],
+    [ '1',  null,   null,  '1',   null, '0',    false ],
+    [ '5',  null,   null,  '3',   '3',  '0',    false ],
+    [ '5',  '2',    '-6',  '3',   '2',  '-2',   false ],
+    [ '-3', '5',    '-10', '-3',  null, '-10',  false ],
+    // Step mismatch.
+    [ '1',  '2',    '-2',  null,  null, '0',    false ],
+    [ '3',  '2',    '-2',  null,  null, '2',    false ],
+    [ '3',  '2',    '-2',  null,  '2',  '0',    false ],
+    [ '3',  '2',    '-2',  null,  '-2', '8',    false ],
+    [ '1',  '2',    '-6',  null,  null, '0',    false ],
+    [ '1',  '2',    '-2',  null,  null, '0',    false ],
+    [ '1',  '3',    '-6',  null,  null, '-3',   false ],
+    [ '2',  '3',    '-6',  null,  null, '0',    false ],
+    [ '2',  '3',    '1',   null,  null, '1',    false ],
+    [ '5',  '3',    '1',   null,  null, '1',    false ],
+    [ '3',  '2',    '-6',  null,  null, '2',    false ],
+    [ '5',  '2',    '-6',  null,  null, '4',    false ],
+    [ '6',  '2',   '1',    null,  null, '5',    false ],
+    [ '8',  '3',   '1',    null,  null, '4',    false ],
+    [ '9',  '2',   '-10',  null,  null, '8',    false ],
+    [ '7',  '3',   '-10',  null,  null, '5',    false ],
<