Bug 567872 - Layout part of the progress element. r=roc,dbaron
authorMounir Lamouri <mounir.lamouri@gmail.com>
Sat, 07 May 2011 10:15:14 +0200
changeset 69385 a8b8078beea289410e8e2ec26b7622f88861c55a
parent 69384 6d42dd8b3d0d1eef20669dc8be77622add2166b4
child 69386 2139b047dbb7f2820da0b5eacc31220aaa245688
push id76
push userbzbarsky@mozilla.com
push dateTue, 05 Jul 2011 17:00:57 +0000
treeherdermozilla-beta@d3a2732c35f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, dbaron
bugs567872
milestone6.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
Bug 567872 - Layout part of the progress element. r=roc,dbaron
layout/base/nsCSSFrameConstructor.cpp
layout/forms/Makefile.in
layout/forms/nsProgressFrame.cpp
layout/forms/nsProgressFrame.h
layout/generic/nsHTMLParts.h
layout/generic/nsQueryFrame.h
layout/reftests/forms/progress/margin-padding-ref.html
layout/reftests/forms/progress/margin-padding.html
layout/reftests/forms/progress/reftest.list
layout/reftests/forms/progress/style.css
layout/reftests/forms/progress/transformations-ref.html
layout/reftests/forms/progress/transformations.html
layout/reftests/forms/progress/values-ref.html
layout/reftests/forms/progress/values-rtl-ref.html
layout/reftests/forms/progress/values-rtl.html
layout/reftests/forms/progress/values.html
layout/reftests/forms/reftest.list
layout/style/forms.css
layout/style/html.css
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -3543,17 +3543,18 @@ nsCSSFrameConstructor::FindHTMLData(Elem
     SIMPLE_TAG_CREATE(frameset, NS_NewHTMLFramesetFrame),
     SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame),
     COMPLEX_TAG_CREATE(button, &nsCSSFrameConstructor::ConstructButtonFrame),
     SIMPLE_TAG_CREATE(canvas, NS_NewHTMLCanvasFrame),
 #if defined(MOZ_MEDIA)
     SIMPLE_TAG_CREATE(video, NS_NewHTMLVideoFrame),
     SIMPLE_TAG_CREATE(audio, NS_NewHTMLVideoFrame),
 #endif
-    SIMPLE_TAG_CREATE(isindex, NS_NewIsIndexFrame)
+    SIMPLE_TAG_CREATE(isindex, NS_NewIsIndexFrame),
+    SIMPLE_TAG_CREATE(progress, NS_NewProgressFrame)
   };
 
   return FindDataByTag(aTag, aElement, aStyleContext, sHTMLData,
                        NS_ARRAY_LENGTH(sHTMLData));
 }
 
 /* static */
 const nsCSSFrameConstructor::FrameConstructionData*
--- a/layout/forms/Makefile.in
+++ b/layout/forms/Makefile.in
@@ -67,16 +67,17 @@ CPPSRCS		= \
 		nsButtonFrameRenderer.cpp \
 		nsComboboxControlFrame.cpp \
 		nsFieldSetFrame.cpp \
 		nsFileControlFrame.cpp \
 		nsFormControlFrame.cpp \
 		nsGfxButtonControlFrame.cpp \
 		nsGfxCheckboxControlFrame.cpp \
 		nsGfxRadioControlFrame.cpp \
+		nsProgressFrame.cpp \
 		nsTextControlFrame.cpp \
 		nsHTMLButtonControlFrame.cpp \
 		nsImageControlFrame.cpp \
 		nsLegendFrame.cpp \
 		nsListControlFrame.cpp \
 		nsIsIndexFrame.cpp \
 		nsSelectsAreaFrame.cpp \
 		$(NULL)
new file mode 100644
--- /dev/null
+++ b/layout/forms/nsProgressFrame.cpp
@@ -0,0 +1,241 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mounir Lamouri <mounir.lamouri@mozilla.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsProgressFrame.h"
+
+#include "nsIDOMHTMLProgressElement.h"
+#include "nsIContent.h"
+#include "prtypes.h"
+#include "nsPresContext.h"
+#include "nsGkAtoms.h"
+#include "nsINameSpaceManager.h"
+#include "nsIDocument.h"
+#include "nsIPresShell.h"
+#include "nsNodeInfoManager.h"
+#include "nsINodeInfo.h"
+#include "nsContentCreatorFunctions.h"
+#include "nsContentUtils.h"
+#include "nsFormControlFrame.h"
+#include "nsFontMetrics.h"
+
+
+nsIFrame*
+NS_NewProgressFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
+{
+  return new (aPresShell) nsProgressFrame(aContext);
+}
+
+NS_IMPL_FRAMEARENA_HELPERS(nsProgressFrame)
+
+nsProgressFrame::nsProgressFrame(nsStyleContext* aContext)
+  : nsHTMLContainerFrame(aContext)
+  , mBarDiv(nsnull)
+{
+}
+
+nsProgressFrame::~nsProgressFrame()
+{
+}
+
+void
+nsProgressFrame::DestroyFrom(nsIFrame* aDestructRoot)
+{
+  NS_ASSERTION(!GetPrevContinuation(),
+               "nsProgressFrame should not have continuations; if it does we "
+               "need to call RegUnregAccessKey only for the first.");
+  nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), PR_FALSE);
+  nsContentUtils::DestroyAnonymousContent(&mBarDiv);
+  nsHTMLContainerFrame::DestroyFrom(aDestructRoot);
+}
+
+nsresult
+nsProgressFrame::CreateAnonymousContent(nsTArray<nsIContent*>& aElements)
+{
+  // Get the NodeInfoManager and tag necessary to create the progress bar div.
+  nsCOMPtr<nsIDocument> doc = mContent->GetDocument();
+
+  nsCOMPtr<nsINodeInfo> nodeInfo;
+  nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::div, nsnull,
+                                                 kNameSpaceID_XHTML);
+  NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
+
+  // Create the div.
+  nsresult rv = NS_NewHTMLElement(getter_AddRefs(mBarDiv), nodeInfo.forget(),
+                                  mozilla::dom::NOT_FROM_PARSER);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (!aElements.AppendElement(mBarDiv)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  return NS_OK;
+}
+
+void
+nsProgressFrame::AppendAnonymousContentTo(nsBaseContentList& aElements,
+                                          PRUint32 aFilter)
+{
+  aElements.MaybeAppendElement(mBarDiv);
+}
+
+NS_QUERYFRAME_HEAD(nsProgressFrame)
+  NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
+NS_QUERYFRAME_TAIL_INHERITING(nsHTMLContainerFrame)
+
+
+NS_IMETHODIMP nsProgressFrame::Reflow(nsPresContext*           aPresContext,
+                                      nsHTMLReflowMetrics&     aDesiredSize,
+                                      const nsHTMLReflowState& aReflowState,
+                                      nsReflowStatus&          aStatus)
+{
+  DO_GLOBAL_REFLOW_COUNT("nsProgressFrame");
+  DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
+
+  NS_ASSERTION(mBarDiv, "Progress bar div must exist!");
+  NS_ASSERTION(!GetPrevContinuation(),
+               "nsProgressFrame should not have continuations; if it does we "
+               "need to call RegUnregAccessKey only for the first.");
+
+  if (mState & NS_FRAME_FIRST_REFLOW) {
+    nsFormControlFrame::RegUnRegAccessKey(this, PR_TRUE);
+  }
+
+  nsIFrame* barFrame = mBarDiv->GetPrimaryFrame();
+  NS_ASSERTION(barFrame, "The progress frame should have a child with a frame!");
+
+  ReflowBarFrame(barFrame, aPresContext, aReflowState, aStatus);
+
+  aDesiredSize.width = aReflowState.ComputedWidth() +
+                       aReflowState.mComputedBorderPadding.LeftRight();
+  aDesiredSize.height = aReflowState.ComputedHeight() +
+                        aReflowState.mComputedBorderPadding.TopBottom();
+  aDesiredSize.height = NS_CSS_MINMAX(aDesiredSize.height,
+                                      aReflowState.mComputedMinHeight,
+                                      aReflowState.mComputedMaxHeight);
+
+  aDesiredSize.SetOverflowAreasToDesiredBounds();
+  ConsiderChildOverflow(aDesiredSize.mOverflowAreas, barFrame);
+  FinishAndStoreOverflow(&aDesiredSize);
+
+  aStatus = NS_FRAME_COMPLETE;
+
+  NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
+
+  return NS_OK;
+}
+
+void
+nsProgressFrame::ReflowBarFrame(nsIFrame*                aBarFrame,
+                                nsPresContext*           aPresContext,
+                                const nsHTMLReflowState& aReflowState,
+                                nsReflowStatus&          aStatus)
+{
+  nsHTMLReflowState reflowState(aPresContext, aReflowState, aBarFrame,
+                                nsSize(aReflowState.ComputedWidth(),
+                                       NS_UNCONSTRAINEDSIZE));
+  nscoord width = aReflowState.ComputedWidth();
+  nscoord xoffset = aReflowState.mComputedBorderPadding.left;
+  nscoord yoffset = aReflowState.mComputedBorderPadding.top;
+
+  double position;
+  nsCOMPtr<nsIDOMHTMLProgressElement> progressElement =
+    do_QueryInterface(mContent);
+  progressElement->GetPosition(&position);
+
+  // Force the bar's width to match the current progress.
+  // When indeterminate, the progress' width will be 100%.
+  if (position >= 0.0) {
+    width *= position;
+  }
+
+  if (GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
+    xoffset += aReflowState.ComputedWidth() - width;
+  }
+
+  // We want the frame to take all the available size.
+  width -= reflowState.mComputedMargin.LeftRight() +
+           reflowState.mComputedBorderPadding.LeftRight();
+  width = NS_MAX(width, 0);
+  reflowState.SetComputedWidth(width);
+
+  xoffset += reflowState.mComputedMargin.left;
+  yoffset += reflowState.mComputedMargin.top;
+
+  nsHTMLReflowMetrics barDesiredSize;
+  ReflowChild(aBarFrame, aPresContext, barDesiredSize, reflowState, xoffset,
+              yoffset, 0, aStatus);
+  FinishReflowChild(aBarFrame, aPresContext, &reflowState, barDesiredSize,
+                    xoffset, yoffset, 0);
+}
+
+NS_IMETHODIMP
+nsProgressFrame::AttributeChanged(PRInt32  aNameSpaceID,
+                                  nsIAtom* aAttribute,
+                                  PRInt32  aModType)
+{
+  NS_ASSERTION(mBarDiv, "Progress bar div must exist!");
+
+  if (aNameSpaceID == kNameSpaceID_None &&
+      (aAttribute == nsGkAtoms::value || aAttribute == nsGkAtoms::max)) {
+    nsIFrame* barFrame = mBarDiv->GetPrimaryFrame();
+    NS_ASSERTION(barFrame, "The progress frame should have a child with a frame!");
+    PresContext()->PresShell()->FrameNeedsReflow(barFrame, nsIPresShell::eResize,
+                                                 NS_FRAME_IS_DIRTY);
+  }
+
+  return nsHTMLContainerFrame::AttributeChanged(aNameSpaceID, aAttribute,
+                                                aModType);
+}
+
+nsSize
+nsProgressFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
+                                 nsSize aCBSize, nscoord aAvailableWidth,
+                                 nsSize aMargin, nsSize aBorder,
+                                 nsSize aPadding, PRBool aShrinkWrap)
+{
+  nsRefPtr<nsFontMetrics> fontMet;
+  NS_ENSURE_SUCCESS(nsLayoutUtils::GetFontMetricsForFrame(this,
+                                                          getter_AddRefs(fontMet)),
+                    nsSize(0, 0));
+
+  nsSize autoSize;
+  autoSize.height = autoSize.width = fontMet->Font().size; // 1em
+  autoSize.width *= 10; // 10em
+
+  return autoSize;
+}
+
new file mode 100644
--- /dev/null
+++ b/layout/forms/nsProgressFrame.h
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mounir Lamouri <mounir.lamouri@mozilla.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsProgressFrame_h___
+#define nsProgressFrame_h___
+
+#include "nsHTMLContainerFrame.h"
+#include "nsIAnonymousContentCreator.h"
+#include "nsCOMPtr.h"
+
+
+class nsProgressFrame : public nsHTMLContainerFrame,
+                        public nsIAnonymousContentCreator
+{
+public:
+  NS_DECL_QUERYFRAME_TARGET(nsProgressFrame)
+  NS_DECL_QUERYFRAME
+  NS_DECL_FRAMEARENA_HELPERS
+
+  nsProgressFrame(nsStyleContext* aContext);
+  virtual ~nsProgressFrame();
+
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
+
+  NS_IMETHOD Reflow(nsPresContext*           aCX,
+                    nsHTMLReflowMetrics&     aDesiredSize,
+                    const nsHTMLReflowState& aReflowState,
+                    nsReflowStatus&          aStatus);
+
+#ifdef NS_DEBUG
+  NS_IMETHOD GetFrameName(nsAString& aResult) const {
+    return MakeFrameName(NS_LITERAL_STRING("Progress"), aResult);
+  }
+#endif
+
+  virtual PRBool IsLeaf() const { return PR_TRUE; }
+
+  // nsIAnonymousContentCreator
+  virtual nsresult CreateAnonymousContent(nsTArray<nsIContent*>& aElements);
+  virtual void AppendAnonymousContentTo(nsBaseContentList& aElements,
+                                        PRUint32 aFilter);
+
+  NS_IMETHOD AttributeChanged(PRInt32  aNameSpaceID,
+                              nsIAtom* aAttribute,
+                              PRInt32  aModType);
+
+  virtual nsSize ComputeAutoSize(nsRenderingContext *aRenderingContext,
+                                 nsSize aCBSize, nscoord aAvailableWidth,
+                                 nsSize aMargin, nsSize aBorder,
+                                 nsSize aPadding, PRBool aShrinkWrap);
+
+  virtual PRBool IsFrameOfType(PRUint32 aFlags) const
+  {
+    return nsHTMLContainerFrame::IsFrameOfType(aFlags &
+      ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
+  }
+
+protected:
+  // Helper function which reflow the anonymous div frame.
+  void ReflowBarFrame(nsIFrame*                aBarFrame,
+                      nsPresContext*           aPresContext,
+                      const nsHTMLReflowState& aReflowState,
+                      nsReflowStatus&          aStatus);
+
+  /**
+   * The div used to show the progress bar.
+   * @see nsProgressFrame::CreateAnonymousContent
+   */
+  nsCOMPtr<nsIContent> mBarDiv;
+};
+
+#endif
+
--- a/layout/generic/nsHTMLParts.h
+++ b/layout/generic/nsHTMLParts.h
@@ -199,16 +199,18 @@ NS_NewNativeRadioControlFrame(nsIPresShe
 nsIFrame*
 NS_NewNativeSelectControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
 NS_NewListControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
 NS_NewComboboxControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, PRUint32 aFlags);
 nsIFrame*
 NS_NewIsIndexFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
+nsIFrame*
+NS_NewProgressFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
 // Table frame factories
 nsIFrame*
 NS_NewTableOuterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
 NS_NewTableFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
 NS_NewTableCaptionFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
--- a/layout/generic/nsQueryFrame.h
+++ b/layout/generic/nsQueryFrame.h
@@ -180,16 +180,17 @@ public:
     nsMenuFrame_id,
     nsMenuPopupFrame_id,
     nsObjectFrame_id,
     nsPageBreakFrame_id,
     nsPageContentFrame_id,
     nsPageFrame_id,
     nsPlaceholderFrame_id,
     nsPopupSetFrame_id,
+    nsProgressFrame_id,
     nsProgressMeterFrame_id,
     nsResizerFrame_id,
     nsRootBoxFrame_id,
     nsScrollbarButtonFrame_id,
     nsScrollbarFrame_id,
     nsSelectsAreaFrame_id,
     nsSimplePageSequenceFrame_id,
     nsSliderFrame_id,
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/progress/margin-padding-ref.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+  <link rel='stylesheet' type='text/css' href='style.css'>
+  <style>
+    body > div:nth-child(1) { margin: 10px; padding: 0px; }
+    body > div:nth-child(2) { margin: 0px; padding: 10px; }
+    body > div:nth-child(3) { margin: 10px; padding: 10px; }
+    body > div:nth-child(4) { margin: 5px; padding: 5px; }
+    body > div:nth-child(5) { margin: 50px; padding: 50px; }
+    body > div:nth-child(6) { margin: 100px; padding: 100px; }
+    body > div:nth-child(7) { margin: 10px 0px 0px 0px; padding: 0px; }
+    body > div:nth-child(8) { margin: 0px 10px 0px 0px; padding: 0px; }
+    body > div:nth-child(9) { margin: 0px 0px 10px 0px; padding: 0px; }
+    body > div:nth-child(10) { margin: 0px 0px 0px 10px; padding: 0px; }
+    body > div:nth-child(11) { margin: 0px; padding: 10px 0px 0px 0px; }
+    body > div:nth-child(12) { margin: 0px; padding: 0px 10px 0px 0px; }
+    body > div:nth-child(13) { margin: 0px; padding: 0px 0px 10px 0px; }
+    body > div:nth-child(14) { margin: 0px; padding: 0px 0px 0px 10px; }
+    body > div:nth-child(15) { margin: 0px; padding: 2px 4px 6px 8px; }
+    body > div:nth-child(16) { margin: 2px 4px 6px 8px; padding: 0px; }
+  </style>
+  <body>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/progress/margin-padding.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+  <style>
+    progress:nth-child(1) { margin: 10px; padding: 0px; }
+    progress:nth-child(2) { margin: 0px; padding: 10px; }
+    progress:nth-child(3) { margin: 10px; padding: 10px; }
+    progress:nth-child(4) { margin: 5px; padding: 5px; }
+    progress:nth-child(5) { margin: 50px; padding: 50px; }
+    progress:nth-child(6) { margin: 100px; padding: 100px; }
+    progress:nth-child(7) { margin: 10px 0px 0px 0px; padding: 0px; }
+    progress:nth-child(8) { margin: 0px 10px 0px 0px; padding: 0px; }
+    progress:nth-child(9) { margin: 0px 0px 10px 0px; padding: 0px; }
+    progress:nth-child(10) { margin: 0px 0px 0px 10px; padding: 0px; }
+    progress:nth-child(11) { margin: 0px; padding: 10px 0px 0px 0px; }
+    progress:nth-child(12) { margin: 0px; padding: 0px 10px 0px 0px; }
+    progress:nth-child(13) { margin: 0px; padding: 0px 0px 10px 0px; }
+    progress:nth-child(14) { margin: 0px; padding: 0px 0px 0px 10px; }
+    progress:nth-child(15) { margin: 0px; padding: 2px 4px 6px 8px; }
+    progress:nth-child(16) { margin: 2px 4px 6px 8px; padding: 0px; }
+  </style>
+  <body>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/progress/reftest.list
@@ -0,0 +1,9 @@
+# For the moment, none of these tests will work on MacOS X.
+skip-if(cocoaWidget) == values.html values-ref.html
+skip-if(cocoaWidget) == values-rtl.html values-rtl-ref.html
+skip-if(cocoaWidget) == margin-padding.html margin-padding-ref.html
+
+# The following test is disabled but kept in the repository because the
+# transformations will not behave exactly the same for <progress> and two divs.
+# However, it would be possible to manually check those.
+# == transformations.html transformations-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/progress/style.css
@@ -0,0 +1,26 @@
+div.progress-element {
+  -moz-appearance: progressbar;
+  display: inline-block;
+  height: 1em;
+  width: 10em;
+  vertical-align: -0.2em;
+
+  /* TODO: this is a workaround for bug 568825 */
+  overflow: hidden;
+
+  /* Default style in case of there is -moz-appearance: none; */
+  border: 2px solid;
+  -moz-border-top-colors: ThreeDShadow -moz-Dialog;
+  -moz-border-right-colors: ThreeDHighlight -moz-Dialog;
+  -moz-border-bottom-colors: ThreeDHighlight -moz-Dialog;
+  -moz-border-left-colors: ThreeDShadow -moz-Dialog;
+  background-color: -moz-Dialog;
+}
+
+div.progress-bar {
+  -moz-appearance: progresschunk;
+  height: 100%;
+
+  /* Default style in case of there is -moz-appearance: none; */
+  background-color: ThreeDShadow;
+}
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/progress/transformations-ref.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<html>
+  <link rel='stylesheet' type='text/css' href='style.css'>
+  <style>
+    body > div:nth-child(1) { -moz-transform: matrix(1, -0.2, 0, 1, 0, 0); }
+    body > div:nth-child(2) { -moz-transform: matrix(1, 0, 0.6, 1, 15em, 0); }
+    body > div:nth-child(3) { -moz-transform: rotate(30deg); }
+    body > div:nth-child(4) { -moz-transform: scale(2, 4); }
+    body > div:nth-child(5) { -moz-transform: scale(0.1, 0.4); }
+    body > div:nth-child(6) { -moz-transform: scale(1, 0.4); }
+    body > div:nth-child(7) { -moz-transform: scale(0.1, 1); }
+    body > div:nth-child(8) { -moz-transform: skew(30deg, -10deg); }
+    body > div:nth-child(9) { -moz-transform: skew(-30deg, 10deg); }
+    body > div:nth-child(10) { -moz-transform: translate(10px, 30px); }
+    body > div:nth-child(11) { -moz-transform: translate(30px, 10px); }
+    body > div:nth-child(12) { -moz-transform: translate(-10px, 30px); }
+    body > div:nth-child(13) { -moz-transform: translate(30px, -10px); }
+    body > div:nth-child(14) { -moz-transform: scale(0, 0); }
+  </style>
+  <body>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/progress/transformations.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+  <style>
+    progress:nth-child(1) { -moz-transform: matrix(1, -0.2, 0, 1, 0, 0); }
+    progress:nth-child(2) { -moz-transform: matrix(1, 0, 0.6, 1, 15em, 0); }
+    progress:nth-child(3) { -moz-transform: rotate(30deg); }
+    progress:nth-child(4) { -moz-transform: scale(2, 4); }
+    progress:nth-child(5) { -moz-transform: scale(0.1, 0.4); }
+    progress:nth-child(6) { -moz-transform: scale(1, 0.4); }
+    progress:nth-child(7) { -moz-transform: scale(0.1, 1); }
+    progress:nth-child(8) { -moz-transform: skew(30deg, -10deg); }
+    progress:nth-child(9) { -moz-transform: skew(-30deg, 10deg); }
+    progress:nth-child(10) { -moz-transform: translate(10px, 30px); }
+    progress:nth-child(11) { -moz-transform: translate(30px, 10px); }
+    progress:nth-child(12) { -moz-transform: translate(-10px, 30px); }
+    progress:nth-child(13) { -moz-transform: translate(30px, -10px); }
+    progress:nth-child(14) { -moz-transform: scale(0, 0); }
+  </style>
+  <body>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+    <progress value='1'></progress>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/progress/values-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+  <link rel='stylesheet' type='text/css' href='style.css'>
+  <style>
+    div:nth-child(1) > .progress-bar { width: 100%; }
+    div:nth-child(2) > .progress-bar { width: 0%; }
+    div:nth-child(3) > .progress-bar { width: 10%; }
+    div:nth-child(4) > .progress-bar { width: 50%; }
+    div:nth-child(5) > .progress-bar { width: 0%; }
+    div:nth-child(6) > .progress-bar { width: 100%; }
+    div:nth-child(7) > .progress-bar { width: 42%; }
+    div:nth-child(8) > .progress-bar { width: 100%; }
+    div:nth-child(9) > .progress-bar { width: 100%; }
+    div:nth-child(10) > .progress-bar { width: 10%; }
+  </style>
+  <body>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/progress/values-rtl-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+  <link rel='stylesheet' type='text/css' href='style.css'>
+  <style>
+    div:nth-child(1) > .progress-bar { width: 100%; }
+    div:nth-child(2) > .progress-bar { width: 0%; }
+    div:nth-child(3) > .progress-bar { width: 10%; }
+    div:nth-child(4) > .progress-bar { width: 50%; }
+    div:nth-child(5) > .progress-bar { width: 0%; }
+    div:nth-child(6) > .progress-bar { width: 100%; }
+    div:nth-child(7) > .progress-bar { width: 42%; }
+    div:nth-child(8) > .progress-bar { width: 100%; }
+    div:nth-child(9) > .progress-bar { width: 100%; }
+    div:nth-child(10) > .progress-bar { width: 10%; }
+  </style>
+  <body dir='rtl'>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar">
+      </div>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/progress/values-rtl.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+  <body dir='rtl'>
+    <progress value="1.0"></progress>
+    <progress value="0.0"></progress>
+    <progress value="0.1"></progress>
+    <progress value="0.5"></progress>
+    <progress value="-1"></progress>
+    <progress value="42"></progress>
+    <progress value="42" max="100"></progress>
+    <progress value="42" max="1"></progress>
+    <progress value="42" max="-1"></progress>
+    <progress value="0.1" max="-1"></progress>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/progress/values.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <progress value="1.0"></progress>
+    <progress value="0.0"></progress>
+    <progress value="0.1"></progress>
+    <progress value="0.5"></progress>
+    <progress value="-1"></progress>
+    <progress value="42"></progress>
+    <progress value="42" max="100"></progress>
+    <progress value="42" max="1"></progress>
+    <progress value="42" max="-1"></progress>
+    <progress value="0.1" max="-1"></progress>
+  </body>
+</html>
--- a/layout/reftests/forms/reftest.list
+++ b/layout/reftests/forms/reftest.list
@@ -54,8 +54,11 @@ fails-if(Android) != textarea-rtl.html t
 # placeholder
 include placeholder/reftest.list
 
 # input
 include input/reftest.list
 
 # output element
 include output/reftest.list
+
+# progress element
+include progress/reftest.list
--- a/layout/style/forms.css
+++ b/layout/style/forms.css
@@ -663,16 +663,41 @@ output:-moz-ui-invalid {
 @media print {
   input, textarea, select, button {
     -moz-user-input: none !important;
   }
 
   input[type="file"] { height: 2em; }
 }
 
+progress {
+  -moz-appearance: progressbar;
+  display: inline-block;
+  vertical-align: -0.2em;
+
+  /* TODO: this is a workaround for bug 568825 */
+  overflow: hidden;
+
+  /* Default style in case of there is -moz-appearance: none; */
+  border: 2px solid;
+  -moz-border-top-colors: ThreeDShadow -moz-Dialog;
+  -moz-border-right-colors: ThreeDHighlight -moz-Dialog;
+  -moz-border-bottom-colors: ThreeDHighlight -moz-Dialog;
+  -moz-border-left-colors: ThreeDShadow -moz-Dialog;
+  background-color: -moz-Dialog;
+}
+
+progress > div {
+  -moz-appearance: progresschunk;
+  height: 100%;
+
+  /* Default style in case of there is -moz-appearance: none; */
+  background-color: ThreeDShadow;
+}
+
 %if OSARCH==OS2
 input {
   font: medium serif; font-family: inherit
 }
 
 select {
   font: medium serif; font-family: inherit
 }
--- a/layout/style/html.css
+++ b/layout/style/html.css
@@ -690,42 +690,85 @@ spacer {
   float: none ! important;
 }
 
 canvas {
   -moz-user-select: none;
 }
 
 /* focusable content: anything w/ tabindex >=0 is focusable */
-abbr:-moz-focusring, acronym:-moz-focusring, address:-moz-focusring,
+abbr:-moz-focusring,
+acronym:-moz-focusring,
+address:-moz-focusring,
 applet:-moz-focusring,
-b:-moz-focusring, base:-moz-focusring, big:-moz-focusring,
-blockquote:-moz-focusring, br:-moz-focusring, canvas:-moz-focusring,
-caption:-moz-focusring, center:-moz-focusring, cite:-moz-focusring,
-code:-moz-focusring, col:-moz-focusring, colgroup:-moz-focusring,
-dd:-moz-focusring, del:-moz-focusring, dfn:-moz-focusring, dir:-moz-focusring,
-div:-moz-focusring, dl:-moz-focusring, dt:-moz-focusring, em:-moz-focusring,
+b:-moz-focusring,
+base:-moz-focusring,
+big:-moz-focusring,
+blockquote:-moz-focusring,
+br:-moz-focusring,
+canvas:-moz-focusring,
+caption:-moz-focusring,
+center:-moz-focusring,
+cite:-moz-focusring,
+code:-moz-focusring,
+col:-moz-focusring,
+colgroup:-moz-focusring,
+dd:-moz-focusring,
+del:-moz-focusring,
+dfn:-moz-focusring,
+dir:-moz-focusring,
+div:-moz-focusring,
+dl:-moz-focusring,
+dt:-moz-focusring,
+em:-moz-focusring,
 embed:-moz-focusring,
-fieldset:-moz-focusring, font:-moz-focusring, form:-moz-focusring,
-h1:-moz-focusring, h2:-moz-focusring, h3:-moz-focusring, h4:-moz-focusring,
-h5:-moz-focusring, h6:-moz-focusring, hr:-moz-focusring, i:-moz-focusring,
-img:-moz-focusring, ins:-moz-focusring, kbd:-moz-focusring,
-label:-moz-focusring, legend:-moz-focusring, li:-moz-focusring,
+fieldset:-moz-focusring,
+font:-moz-focusring,
+form:-moz-focusring,
+h1:-moz-focusring,
+h2:-moz-focusring,
+h3:-moz-focusring,
+h4:-moz-focusring,
+h5:-moz-focusring,
+h6:-moz-focusring,
+hr:-moz-focusring,
+i:-moz-focusring,
+img:-moz-focusring,
+ins:-moz-focusring,
+kbd:-moz-focusring,
+label:-moz-focusring,
+legend:-moz-focusring,
+li:-moz-focusring,
 link:-moz-focusring,
 menu:-moz-focusring,
 object:-moz-focusring,
 ol:-moz-focusring,
 p:-moz-focusring,
-pre:-moz-focusring, q:-moz-focusring, s:-moz-focusring, samp:-moz-focusring,
-small:-moz-focusring, span:-moz-focusring, strike:-moz-focusring,
-strong:-moz-focusring, sub:-moz-focusring, sup:-moz-focusring,
-table:-moz-focusring, tbody:-moz-focusring, td:-moz-focusring,
-tfoot:-moz-focusring, th:-moz-focusring, thead:-moz-focusring, 
-tr:-moz-focusring, tt:-moz-focusring, u:-moz-focusring,
-ul:-moz-focusring, var:-moz-focusring {
+pre:-moz-focusring,
+progress:-moz-focusring,
+q:-moz-focusring,
+s:-moz-focusring,
+samp:-moz-focusring,
+small:-moz-focusring,
+span:-moz-focusring,
+strike:-moz-focusring,
+strong:-moz-focusring,
+sub:-moz-focusring,
+sup:-moz-focusring,
+table:-moz-focusring,
+tbody:-moz-focusring,
+td:-moz-focusring,
+tfoot:-moz-focusring,
+th:-moz-focusring,
+thead:-moz-focusring,
+tr:-moz-focusring,
+tt:-moz-focusring,
+u:-moz-focusring,
+ul:-moz-focusring,
+var:-moz-focusring {
   /* Don't specify the outline-color, we should always use initial value. */
    outline: 1px dotted;
 }
 
 /* hidden elements */
 base, basefont, datalist, head, meta, script, style, title,
 noembed, param {
    display: none;