Merge backout
authorChris Jones <jones.chris.g@gmail.com>
Thu, 19 Aug 2010 19:02:24 -0500
changeset 50959 3ceaf53d80dfbb6f17013bcf9b4c52deca5e9a8e
parent 50957 3496939165ad1e978ee6bdb50fd36abf6b75e94a (diff)
parent 50958 344aa86787f71f1e701f3c282af24fb10387df34 (current diff)
child 50961 28070f8d44b57484024a709e54bd18fcf4078c02
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone2.0b5pre
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 backout
view/src/nsView.cpp
view/src/nsView.h
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -645,16 +645,19 @@ xpicleanup@BIN_SUFFIX@
   modules/CertUtils.jsm
   modules/CrashSubmit.jsm
   modules/CSPUtils.jsm
   modules/ctypes.jsm
   modules/debug.js
   modules/distribution.js
   modules/DownloadLastDir.jsm
   modules/DownloadPaths.jsm
+  #ifdef XP_WIN
+    modules/DownloadTaskbarProgress.jsm
+  #endif
   modules/DownloadUtils.jsm
   modules/FileUtils.jsm
   modules/Geometry.jsm
   modules/HUDService.jsm
   modules/InlineSpellChecker.jsm
   modules/ISO8601DateUtils.jsm
   modules/LightweightThemeConsumer.jsm
   modules/LightweightThemeManager.jsm
--- a/configure.in
+++ b/configure.in
@@ -113,17 +113,17 @@ MOZZLIB=0x1230
 NSPR_VERSION=4
 NSS_VERSION=3
 
 dnl Set the minimum version of toolkit libs used by mozilla
 dnl ========================================================
 GLIB_VERSION=1.2.0
 LIBIDL_VERSION=0.6.3
 PERL_VERSION=5.006
-PYTHON_VERSION=2.4
+PYTHON_VERSION=2.5
 CAIRO_VERSION=1.8.8
 PANGO_VERSION=1.14.0
 GTK2_VERSION=2.10.0
 WINDRES_VERSION=2.14.90
 W32API_VERSION=3.8
 GNOMEVFS_VERSION=2.0
 GNOMEUI_VERSION=2.2.0
 GCONF_VERSION=1.2.1
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -1807,17 +1807,16 @@ nsIAtom** const kDefaultAllowedAttribute
   &nsGkAtoms::accept,
   &nsGkAtoms::acceptcharset,
   &nsGkAtoms::accesskey,
   &nsGkAtoms::action,
   &nsGkAtoms::align,
   &nsGkAtoms::alt,
   &nsGkAtoms::autocomplete,
 #ifdef MOZ_MEDIA
-  &nsGkAtoms::autobuffer,
   &nsGkAtoms::autoplay,
 #endif
   &nsGkAtoms::axis,
   &nsGkAtoms::background,
   &nsGkAtoms::bgcolor,
   &nsGkAtoms::border,
   &nsGkAtoms::cellpadding,
   &nsGkAtoms::cellspacing,
@@ -1867,16 +1866,17 @@ nsIAtom** const kDefaultAllowedAttribute
 #ifdef MOZ_MEDIA
   &nsGkAtoms::pixelratio,
   &nsGkAtoms::playbackrate,
   &nsGkAtoms::playcount,
 #endif
   &nsGkAtoms::pointSize,
 #ifdef MOZ_MEDIA
   &nsGkAtoms::poster,
+  &nsGkAtoms::preload,
 #endif
   &nsGkAtoms::prompt,
   &nsGkAtoms::readonly,
   &nsGkAtoms::rel,
   &nsGkAtoms::rev,
   &nsGkAtoms::role,
   &nsGkAtoms::rows,
   &nsGkAtoms::rowspan,
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -115,19 +115,16 @@ GK_ATOM(ascending, "ascending")
 GK_ATOM(aside, "aside")
 GK_ATOM(aspectRatio, "aspect-ratio")
 GK_ATOM(assign, "assign")
 GK_ATOM(async, "async")
 GK_ATOM(attribute, "attribute")
 GK_ATOM(attributeSet, "attribute-set")
 GK_ATOM(aural, "aural")
 GK_ATOM(_auto, "auto")
-#ifdef MOZ_MEDIA
-GK_ATOM(autobuffer, "autobuffer")
-#endif
 GK_ATOM(autocheck, "autocheck")
 GK_ATOM(autocomplete, "autocomplete")
 GK_ATOM(autofocus, "autofocus")
 #ifdef MOZ_MEDIA
 GK_ATOM(autoplay, "autoplay")
 #endif
 GK_ATOM(autorepeatbutton, "autorepeatbutton")
 GK_ATOM(axis, "axis")
@@ -760,16 +757,19 @@ GK_ATOM(position, "position")
 #ifdef MOZ_MEDIA
 GK_ATOM(poster, "poster")
 #endif
 GK_ATOM(pre, "pre")
 GK_ATOM(preceding, "preceding")
 GK_ATOM(precedingSibling, "preceding-sibling")
 GK_ATOM(predicate, "predicate")
 GK_ATOM(prefix, "prefix")
+#ifdef MOZ_MEDIA
+GK_ATOM(preload, "preload")
+#endif
 GK_ATOM(preserve, "preserve")
 GK_ATOM(preserveSpace, "preserve-space")
 GK_ATOM(preventdefault, "preventdefault")
 GK_ATOM(primary, "primary")
 GK_ATOM(print, "print")
 GK_ATOM(priority, "priority")
 GK_ATOM(processingInstruction, "processing-instruction")
 GK_ATOM(profile, "profile")
--- a/content/base/test/test_bug564863.xhtml
+++ b/content/base/test/test_bug564863.xhtml
@@ -11,16 +11,19 @@
 https://bugzilla.mozilla.org/show_bug.cgi?id=564863
 -->
 <head>
   <title>Test for Bug 564863</title>
   <script type="text/javascript" src="/MochiKit/packed.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 <style>
+* {
+  color: rgb(0, 0, 0);
+}
 #div_id {
   color: rgb(10, 10, 10);
 }
 #a_id {
   color: rgb(20, 20, 20);
 }
 #xul_id {
   color: rgb(30, 30, 30);
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -2322,18 +2322,17 @@ nsCanvasRenderingContext2D::SetFont(cons
     css::Declaration *declaration = rule->GetDeclaration();
     // The easiest way to see whether we got a syntax error or whether
     // we got 'inherit' or 'initial' is to look at font-size-adjust,
     // which the shorthand resets to either 'none' or
     // '-moz-system-font'.
     // We know the declaration is not !important, so we can use
     // GetNormalBlock().
     const nsCSSValue *fsaVal =
-      declaration->GetNormalBlock()->
-        ValueStorageFor(eCSSProperty_font_size_adjust);
+      declaration->GetNormalBlock()->ValueFor(eCSSProperty_font_size_adjust);
     if (!fsaVal || (fsaVal->GetUnit() != eCSSUnit_None &&
                     fsaVal->GetUnit() != eCSSUnit_System_Font)) {
         // We got an all-property value or a syntax error.  The spec says
         // this value must be ignored.
         return NS_OK;
     }
 
     rules.AppendObject(rule);
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -3289,17 +3289,16 @@ nsEventStateManager::PostHandleEvent(nsP
     }
     break;
 #endif // ANDROID
 #endif // MOZ_IPC
   }
 
   //Reset target frame to null to avoid mistargeting after reentrant event
   mCurrentTarget = nsnull;
-  mCurrentTargetContent = nsnull;
 
   return ret;
 }
 
 #ifdef MOZ_IPC
 #ifdef ANDROID
 mozilla::dom::PBrowserParent*
 nsEventStateManager::GetCrossProcessTarget()
@@ -3609,34 +3608,32 @@ nsEventStateManager::DispatchMouseEvent(
   event.isControl = ((nsMouseEvent*)aEvent)->isControl;
   event.isAlt = ((nsMouseEvent*)aEvent)->isAlt;
   event.isMeta = ((nsMouseEvent*)aEvent)->isMeta;
   event.pluginEvent = ((nsMouseEvent*)aEvent)->pluginEvent;
   event.relatedTarget = aRelatedContent;
   event.inputSource = static_cast<nsMouseEvent*>(aEvent)->inputSource;
 
   mCurrentTargetContent = aTargetContent;
-  mCurrentTarget = nsnull;
 
   nsIFrame* targetFrame = nsnull;
   if (aTargetContent) {
     nsESMEventCB callback(aTargetContent);
     nsEventDispatcher::Dispatch(aTargetContent, mPresContext, &event, nsnull,
                                 &status, &callback);
 
     // Although the primary frame was checked in event callback, 
     // it may not be the same object after event dispatching and handling.
     // So we need to refetch it.
     if (mPresContext) {
       targetFrame = mPresContext->GetPrimaryFrameFor(aTargetContent);
     }
   }
 
   mCurrentTargetContent = nsnull;
-  mCurrentTarget = nsnull;
 
   return targetFrame;
 }
 
 void
 nsEventStateManager::NotifyMouseOut(nsGUIEvent* aEvent, nsIContent* aMovingInto)
 {
   if (!mLastMouseOverElement)
@@ -3791,17 +3788,16 @@ nsEventStateManager::GenerateMouseEnterE
 
       NotifyMouseOut(aEvent, nsnull);
     }
     break;
   }
 
   // reset mCurretTargetContent to what it was
   mCurrentTargetContent = targetBeforeEvent;
-  mCurrentTarget = nsnull;
 }
 
 void
 nsEventStateManager::GenerateDragDropEnterExit(nsPresContext* aPresContext,
                                                nsGUIEvent* aEvent)
 {
   //Hold onto old target content through the event and reset after.
   nsCOMPtr<nsIContent> targetBeforeEvent = mCurrentTargetContent;
--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -425,16 +425,61 @@ protected:
    * Call this to reevaluate whether we should be holding a self-reference.
    */
   void AddRemoveSelfReference();
 
   /**
    * Called asynchronously to release a self-reference to this element.
    */
   void DoRemoveSelfReference();
+  
+  /**
+   * Possible values of the 'preload' attribute.
+   */
+  enum PreloadAttrValue {
+    PRELOAD_ATTR_EMPTY,    // set to ""
+    PRELOAD_ATTR_NONE,     // set to "none"
+    PRELOAD_ATTR_METADATA, // set to "metadata"
+    PRELOAD_ATTR_AUTO      // set to "auto"
+  };
+
+  /**
+   * The preloading action to perform. These dictate how we react to the 
+   * preload attribute. See mPreloadAction.
+   */
+  enum PreloadAction {
+    PRELOAD_UNDEFINED = 0, // not determined - used only for initialization
+    PRELOAD_NONE = 1,      // do not preload
+    PRELOAD_METADATA = 2,  // preload only the metadata (and first frame)
+    PRELOAD_ENOUGH = 3     // preload enough data to allow uninterrupted
+                           // playback
+  };
+
+  /**
+   * Suspends the load of resource at aURI, so that it can be resumed later
+   * by ResumeLoad(). This is called when we have a media with a 'preload'
+   * attribute value of 'none', during the resource selection algorithm.
+   */
+  void SuspendLoad(nsIURI* aURI);
+
+  /**
+   * Resumes a previously suspended load (suspended by SuspendLoad(uri)).
+   * Will continue running the resource selection algorithm.
+   * Sets mPreloadAction to aAction.
+   */
+  void ResumeLoad(PreloadAction aAction);
+
+  /**
+   * Handle a change to the preload attribute. Should be called whenever the
+   * value (or presence) of the preload attribute changes. The change in 
+   * attribute value may cause a change in the mPreloadAction of this
+   * element. If there is a change then this method will initiate any
+   * behaviour that is necessary to implement the action.
+   */
+  void UpdatePreloadAction();
 
   nsRefPtr<nsMediaDecoder> mDecoder;
 
   // A reference to the ImageContainer which contains the current frame
   // of video to display.
   nsRefPtr<ImageContainer> mImageContainer;
 
   // Holds a reference to the first channel we open to the media resource.
@@ -477,20 +522,33 @@ protected:
 
   // When the load algorithm is waiting for more src/<source>, this denotes
   // what type of waiting we're doing.
   LoadAlgorithmState mLoadWaitStatus;
 
   // Current audio volume
   float mVolume;
 
+  // If we're loading a preload:none media, we'll record the URI we're
+  // attempting to load in mPreloadURI, and delay loading the resource until
+  // the user initiates a load by either playing the resource, or explicitly
+  // loading it.
+  nsCOMPtr<nsIURI> mPreloadURI;
+  
+  // Stores the current preload action for this element. Initially set to
+  // PRELOAD_UNDEFINED, its value is changed by calling
+  // UpdatePreloadAction().
+  PreloadAction mPreloadAction;
+
   // Size of the media. Updated by the decoder on the main thread if
   // it changes. Defaults to a width and height of -1 if not set.
   nsIntSize mMediaSize;
 
+  nsRefPtr<gfxASurface> mPrintSurface;
+
   // If true then we have begun downloading the media content.
   // Set to false when completed, or not yet started.
   PRPackedBool mBegun;
 
   // True when the decoder has loaded enough data to display the
   // first frame of the content.
   PRPackedBool mLoadedFirstFrame;
 
@@ -546,32 +604,38 @@ protected:
   // an error occurs, or the first frame is loaded.
   PRPackedBool mDelayingLoadEvent;
 
   // PR_TRUE when we've got a task queued to call SelectResource(),
   // or while we're running SelectResource().
   PRPackedBool mIsRunningSelectResource;
 
   // PR_TRUE if we suspended the decoder because we were paused,
-  // autobuffer and autoplay were not set, and we loaded the first frame.
+  // preloading metadata is enabled, autoplay was not enabled, and we loaded
+  // the first frame.
   PRPackedBool mSuspendedAfterFirstFrame;
 
   // PR_TRUE if we are allowed to suspend the decoder because we were paused,
-  // autobuffer and autoplay were not set, and we loaded the first frame.
+  // preloading metdata was enabled, autoplay was not enabled, and we loaded
+  // the first frame.
   PRPackedBool mAllowSuspendAfterFirstFrame;
 
   // PR_TRUE if we've played or completed a seek. We use this to determine
   // when the poster frame should be shown.
   PRPackedBool mHasPlayedOrSeeked;
 
   // PR_TRUE if we've added a reference to ourselves to keep the element
   // alive while no-one is referencing it but the element may still fire
   // events of its own accord.
   PRPackedBool mHasSelfReference;
 
   // PR_TRUE if we've received a notification that the engine is shutting
   // down.
   PRPackedBool mShuttingDown;
 
-  nsRefPtr<gfxASurface> mPrintSurface;
+  // PR_TRUE if we've suspended a load in the resource selection algorithm
+  // due to loading a preload:none media. When PR_TRUE, the resource we'll
+  // load when the user initiates either playback or an explicit load is
+  // stored in mPreloadURI.
+  PRPackedBool mLoadIsSuspended;
 };
 
 #endif
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -1911,17 +1911,18 @@ nsGenericHTMLElement::MapImageBorderAttr
 void
 nsGenericHTMLElement::MapBackgroundInto(const nsMappedAttributes* aAttributes,
                                         nsRuleData* aData)
 {
   if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Background)))
     return;
 
   nsPresContext* presContext = aData->mPresContext;
-  if (!aData->mColorData->mBackImage && presContext->UseDocumentColors()) {
+  if (aData->mColorData->mBackImage.GetUnit() == eCSSUnit_Null &&
+      presContext->UseDocumentColors()) {
     // background
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::background);
     if (value && value->Type() == nsAttrValue::eString) {
       const nsString& spec = value->GetStringValue();
       if (!spec.IsEmpty()) {
         // Resolve url to an absolute url
         // XXX this breaks if the HTML element has an xml:base
         // attribute (the xml:base will not be taken into account)
@@ -1941,32 +1942,28 @@ nsGenericHTMLElement::MapBackgroundInto(
             // XXXbz it would be nice to assert that doc->NodePrincipal() is
             // the same as the principal of the node (which we'd need to store
             // in the mapped attrs or something?)
             nsCSSValue::Image *img =
               new nsCSSValue::Image(uri, buffer, doc->GetDocumentURI(),
                                     doc->NodePrincipal(), doc);
             buffer->Release();
             if (NS_LIKELY(img != 0)) {
-              // Use nsRuleDataColor's temporary mTempBackImage to
-              // make a value list.
-              aData->mColorData->mTempBackImage.mValue.SetImageValue(img);
-              aData->mColorData->mBackImage =
-                &aData->mColorData->mTempBackImage;
+              nsCSSValueList* list =
+                aData->mColorData->mBackImage.SetListValue();
+              list->mValue.SetImageValue(img);
             }
           }
         }
       }
       else if (presContext->CompatibilityMode() == eCompatibility_NavQuirks) {
         // in NavQuirks mode, allow the empty string to set the
         // background to empty
-        // Use nsRuleDataColor's temporary mTempBackImage to make a value list.
-        aData->mColorData->mBackImage = nsnull;
-        aData->mColorData->mTempBackImage.mValue.SetNoneValue();
-        aData->mColorData->mBackImage = &aData->mColorData->mTempBackImage;
+        nsCSSValueList* list = aData->mColorData->mBackImage.SetListValue();
+        list->mValue.SetNoneValue();
       }
     }
   }
 }
 
 void
 nsGenericHTMLElement::MapBGColorInto(const nsMappedAttributes* aAttributes,
                                      nsRuleData* aData)
--- a/content/html/content/src/nsHTMLAudioElement.cpp
+++ b/content/html/content/src/nsHTMLAudioElement.cpp
@@ -115,19 +115,20 @@ nsHTMLAudioElement::~nsHTMLAudioElement(
 {
 }
 
 NS_IMETHODIMP
 nsHTMLAudioElement::Initialize(nsISupports* aOwner, JSContext* aContext,
                                JSObject *aObj, PRUint32 argc, jsval *argv)
 {
   // Audio elements created using "new Audio(...)" should have
-  // 'autobuffer' set (since the script must intend to play the audio)
-  nsresult rv = SetAttr(kNameSpaceID_None, nsGkAtoms::autobuffer,
-                        NS_LITERAL_STRING("autobuffer"), PR_TRUE);
+  // 'preload' set to 'auto' (since the script must intend to
+  // play the audio)
+  nsresult rv = SetAttr(kNameSpaceID_None, nsGkAtoms::preload,
+                        NS_LITERAL_STRING("auto"), PR_TRUE);
   if (NS_FAILED(rv))
     return rv;
 
   if (argc <= 0) {
     // Nothing more to do here if we don't get any arguments.
     return NS_OK;
   }
 
--- a/content/html/content/src/nsHTMLHRElement.cpp
+++ b/content/html/content/src/nsHTMLHRElement.cpp
@@ -278,18 +278,18 @@ MapAttributesIntoRule(const nsMappedAttr
         borderStyle.mLeft.SetIntValue(NS_STYLE_BORDER_STYLE_SOLID,
                                       eCSSUnit_Enumerated);
       }
 
       // If it would be noticeable, set the border radius to
       // 100% on all corners
       nsCSSCornerSizes& corners = aData->mMarginData->mBorderRadius;
 
-      NS_FOR_CSS_HALF_CORNERS(hc) {
-        nsCSSValue& dimen = corners.GetHalfCorner(hc);
+      NS_FOR_CSS_FULL_CORNERS(c) {
+        nsCSSValue& dimen = corners.GetCorner(c);
         if (dimen.GetUnit() == eCSSUnit_Null) {
           dimen.SetPercentValue(1.0f);
         }
       }
     }
   }
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Color)) {
     // color: a color
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -393,17 +393,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsHTMLMediaElement)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
 NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
 
 // nsIDOMHTMLMediaElement
 NS_IMPL_URI_ATTR(nsHTMLMediaElement, Src, src)
 NS_IMPL_BOOL_ATTR(nsHTMLMediaElement, Controls, controls)
 NS_IMPL_BOOL_ATTR(nsHTMLMediaElement, Autoplay, autoplay)
-NS_IMPL_BOOL_ATTR(nsHTMLMediaElement, Autobuffer, autobuffer)
+NS_IMPL_STRING_ATTR(nsHTMLMediaElement, Preload, preload)
 
 /* readonly attribute nsIDOMHTMLMediaElement mozAutoplayEnabled; */
 NS_IMETHODIMP nsHTMLMediaElement::GetMozAutoplayEnabled(PRBool *aAutoplayEnabled)
 {
   *aAutoplayEnabled = mAutoplayEnabled;
 
   return NS_OK;
 }
@@ -605,16 +605,23 @@ void nsHTMLMediaElement::SelectResource(
   nsCOMPtr<nsIURI> uri;
 
   // If we have a 'src' attribute, use that exclusively.
   if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
     nsresult rv = NewURIFromString(src, getter_AddRefs(uri));
     if (NS_SUCCEEDED(rv)) {
       LOG(PR_LOG_DEBUG, ("%p Trying load from src=%s", this, NS_ConvertUTF16toUTF8(src).get()));
       mIsLoadingFromSrcAttribute = PR_TRUE;
+      if (mPreloadAction == nsHTMLMediaElement::PRELOAD_NONE) {
+        // preload:none media, suspend the load here before we make any
+        // network requests.
+        SuspendLoad(uri);
+        return;
+      }
+
       rv = LoadResource(uri);
       if (NS_SUCCEEDED(rv))
         return;
     }
     NoSupportedMediaSourceError();
   } else {
     // Otherwise, the source elements will be used.
     LoadFromSourceChildren();
@@ -642,25 +649,137 @@ void nsHTMLMediaElement::LoadFromSourceC
       // the media element.
       mLoadWaitStatus = WAITING_FOR_SOURCE;
       NoSupportedMediaSourceError();
       return;
     }
 
     mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
 
+    if (mPreloadAction == nsHTMLMediaElement::PRELOAD_NONE) {
+      // preload:none media, suspend the load here before we make any
+      // network requests.
+      SuspendLoad(uri);
+      return;
+    }
+
     rv = LoadResource(uri);
     if (NS_SUCCEEDED(rv))
       return;
 
     // If we fail to load, loop back and try loading the next resource.
   }
   NS_NOTREACHED("Execution should not reach here!");
 }
 
+void nsHTMLMediaElement::SuspendLoad(nsIURI* aURI)
+{
+  mLoadIsSuspended = PR_TRUE;
+  mPreloadURI = aURI;
+  mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE;
+  DispatchAsyncProgressEvent(NS_LITERAL_STRING("suspend"));
+  ChangeDelayLoadStatus(PR_FALSE);
+}
+
+void nsHTMLMediaElement::ResumeLoad(PreloadAction aAction)
+{
+  NS_ASSERTION(mLoadIsSuspended, "Can only resume preload if halted for one");
+  nsCOMPtr<nsIURI> uri = mPreloadURI;
+  mLoadIsSuspended = PR_FALSE;
+  mPreloadURI = nsnull;
+  mPreloadAction = aAction;
+  ChangeDelayLoadStatus(PR_TRUE);
+  mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
+  if (mIsLoadingFromSrcAttribute) {
+    // We were loading from the element's src attribute.
+    if (NS_FAILED(LoadResource(uri))) {
+      NoSupportedMediaSourceError();
+    }
+  } else {
+    // We were loading from a child <source> element. Try to resume the
+    // load of that child, and if that fails, try the next child.
+    if (NS_FAILED(LoadResource(uri))) {
+      LoadFromSourceChildren();
+    }
+  }
+}
+
+static PRBool IsAutoplayEnabled()
+{
+  return nsContentUtils::GetBoolPref("media.autoplay.enabled");
+}
+
+void nsHTMLMediaElement::UpdatePreloadAction()
+{
+  PreloadAction nextAction = PRELOAD_UNDEFINED;
+  // If autoplay is set, we should always preload data, as we'll need it
+  // to play.
+  if (IsAutoplayEnabled() && HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay)) {
+    nextAction = nsHTMLMediaElement::PRELOAD_ENOUGH;
+  } else {
+    // Find the appropriate preload action by looking at the attribute.
+    const nsAttrValue* val = mAttrsAndChildren.GetAttr(nsGkAtoms::preload,
+                                                       kNameSpaceID_None);
+    if (!val) {
+      // Attribute is not set. The default is to load metadata.
+      nextAction = nsHTMLMediaElement::PRELOAD_METADATA;
+    } else if (val->Type() == nsAttrValue::eEnum) {
+      PreloadAttrValue attr = static_cast<PreloadAttrValue>(val->GetEnumValue());
+      if (attr == nsHTMLMediaElement::PRELOAD_ATTR_EMPTY ||
+          attr == nsHTMLMediaElement::PRELOAD_ATTR_AUTO)
+      {
+        nextAction = nsHTMLMediaElement::PRELOAD_ENOUGH;
+      } else if (attr == nsHTMLMediaElement::PRELOAD_ATTR_METADATA) {
+        nextAction = nsHTMLMediaElement::PRELOAD_METADATA;
+      } else if (attr == nsHTMLMediaElement::PRELOAD_ATTR_NONE) {
+        nextAction = nsHTMLMediaElement::PRELOAD_NONE;
+      }
+    } else {
+      // There was a value, but it wasn't an enumerated value.
+      // Use the suggested "missing value default" of "metadata".
+      nextAction = nsHTMLMediaElement::PRELOAD_METADATA;
+    }
+  }
+
+  if ((mBegun || mIsRunningSelectResource) && nextAction < mPreloadAction) {
+    // We've started a load or are already downloading, and the preload was
+    // changed to a state where we buffer less. We don't support this case,
+    // so don't change the preload behaviour.
+    return;
+  }
+
+  PRBool wasPreloadNone = mPreloadAction == PRELOAD_NONE;
+  mPreloadAction = nextAction;
+  if (nextAction == nsHTMLMediaElement::PRELOAD_ENOUGH) {
+    if (mLoadIsSuspended) {
+      // Our load was previouly suspended due to the media having preload
+      // value "none". The preload value has changed to preload:auto, so
+      // resume the load.
+      ResumeLoad(PRELOAD_ENOUGH);
+    } else {
+      // Preload as much of the video as we can, i.e. don't suspend after
+      // the first frame.
+      StopSuspendingAfterFirstFrame();
+    }
+
+  } else if (nextAction == nsHTMLMediaElement::PRELOAD_METADATA) {
+    // Ensure that the video can be suspended after first frame.
+    mAllowSuspendAfterFirstFrame = PR_TRUE;
+    if (mLoadIsSuspended) {
+      // Our load was previouly suspended due to the media having preload
+      // value "none". The preload value has changed to preload:metadata, so
+      // resume the load. We'll pause the load again after we've read the
+      // metadata.
+      ResumeLoad(PRELOAD_METADATA);
+    }
+  }
+
+  return;
+}
+
 nsresult nsHTMLMediaElement::LoadResource(nsIURI* aURI)
 {
   NS_ASSERTION(mDelayingLoadEvent,
                "Should delay load event (if in document) during load");
   nsresult rv;
 
   if (mChannel) {
     mChannel->Cancel(NS_BINDING_ABORTED);
@@ -989,17 +1108,19 @@ nsHTMLMediaElement::nsHTMLMediaElement(a
     mIsRunningLoadMethod(PR_FALSE),
     mIsLoadingFromSrcAttribute(PR_FALSE),
     mDelayingLoadEvent(PR_FALSE),
     mIsRunningSelectResource(PR_FALSE),
     mSuspendedAfterFirstFrame(PR_FALSE),
     mAllowSuspendAfterFirstFrame(PR_TRUE),
     mHasPlayedOrSeeked(PR_FALSE),
     mHasSelfReference(PR_FALSE),
-    mShuttingDown(PR_FALSE)
+    mShuttingDown(PR_FALSE),
+    mPreloadAction(PRELOAD_UNDEFINED),
+    mLoadIsSuspended(PR_FALSE)
 {
 #ifdef PR_LOGGING
   if (!gMediaElementLog) {
     gMediaElementLog = PR_NewLogModule("nsMediaElement");
   }
   if (!gMediaElementEventsLog) {
     gMediaElementEventsLog = PR_NewLogModule("nsMediaElementEvents");
   }
@@ -1054,16 +1175,18 @@ void nsHTMLMediaElement::SetPlayedOrSeek
 NS_IMETHODIMP nsHTMLMediaElement::Play()
 {
   StopSuspendingAfterFirstFrame();
   SetPlayedOrSeeked(PR_TRUE);
 
   if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
     nsresult rv = Load();
     NS_ENSURE_SUCCESS(rv, rv);
+  }  else if (mLoadIsSuspended) {
+    ResumeLoad(PRELOAD_ENOUGH);
   } else if (mDecoder) {
     if (mDecoder->IsEnded()) {
       SetCurrentTime(0);
     }
     if (!mPausedForInactiveDocument) {
       nsresult rv = mDecoder->Play();
       NS_ENSURE_SUCCESS(rv, rv);
     }
@@ -1094,97 +1217,113 @@ NS_IMETHODIMP nsHTMLMediaElement::Play()
   return NS_OK;
 }
 
 PRBool nsHTMLMediaElement::ParseAttribute(PRInt32 aNamespaceID,
                                           nsIAtom* aAttribute,
                                           const nsAString& aValue,
                                           nsAttrValue& aResult)
 {
+  // Mappings from 'preload' attribute strings to an enumeration.
+  static const nsAttrValue::EnumTable kPreloadTable[] = {
+    { "",         nsHTMLMediaElement::PRELOAD_ATTR_EMPTY },
+    { "none",     nsHTMLMediaElement::PRELOAD_ATTR_NONE },
+    { "metadata", nsHTMLMediaElement::PRELOAD_ATTR_METADATA },
+    { "auto",     nsHTMLMediaElement::PRELOAD_ATTR_AUTO },
+    { 0 }
+  };
+
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::src) {
       static const char* kWhitespace = " \n\r\t\b";
       aResult.SetTo(nsContentUtils::TrimCharsInSet(kWhitespace, aValue));
       return PR_TRUE;
     }
     else if (aAttribute == nsGkAtoms::loopstart
             || aAttribute == nsGkAtoms::loopend
             || aAttribute == nsGkAtoms::start
             || aAttribute == nsGkAtoms::end) {
       return aResult.ParseFloatValue(aValue);
     }
     else if (ParseImageAttribute(aAttribute, aValue, aResult)) {
       return PR_TRUE;
     }
+    else if (aAttribute == nsGkAtoms::preload) {
+      return aResult.ParseEnumValue(aValue, kPreloadTable, PR_FALSE);
+    }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 nsresult nsHTMLMediaElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                                      nsIAtom* aPrefix, const nsAString& aValue,
                                      PRBool aNotify)
 {
   nsresult rv =
     nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
                                     aNotify);
+  if (NS_FAILED(rv))
+    return rv;
   if (aNotify && aNameSpaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::src) {
       if (mLoadWaitStatus == WAITING_FOR_SRC_OR_SOURCE) {
         // A previous load algorithm instance is waiting on a src
         // addition, resume the load. It is waiting at "step 1 of the load
         // algorithm".
         mLoadWaitStatus = NOT_WAITING;
         QueueSelectResourceTask();
       }
     } else if (aName == nsGkAtoms::autoplay) {
       StopSuspendingAfterFirstFrame();
       if (mReadyState == nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) {
         NotifyAutoplayDataReady();
       }
       // This attribute can affect AddRemoveSelfReference
       AddRemoveSelfReference();
-    } else if (aName == nsGkAtoms::autobuffer) {
-      StopSuspendingAfterFirstFrame();
+      UpdatePreloadAction();
+    } else if (aName == nsGkAtoms::preload) {
+      UpdatePreloadAction();
     }
   }
 
   return rv;
 }
 
 nsresult nsHTMLMediaElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttr,
                                        PRBool aNotify)
 {
   nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttr, aNotify);
+  if (NS_FAILED(rv))
+    return rv;
   if (aNotify && aNameSpaceID == kNameSpaceID_None) {
     if (aAttr == nsGkAtoms::autoplay) {
       // This attribute can affect AddRemoveSelfReference
       AddRemoveSelfReference();
+      UpdatePreloadAction();
+    } else if (aAttr == nsGkAtoms::preload) {
+      UpdatePreloadAction();
     }
-    // We perhaps should stop loading if 'autobuffer' is being removed,
-    // and we're buffering only because of 'autobuffer', but why bother?
   }
 
   return rv;
 }
 
-static PRBool IsAutoplayEnabled()
-{
-  return nsContentUtils::GetBoolPref("media.autoplay.enabled");
-}
-
 nsresult nsHTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                                         nsIContent* aBindingParent,
                                         PRBool aCompileEventHandlers)
 {
   if (aDocument) {
     mIsBindingToTree = PR_TRUE;
     mAutoplayEnabled =
       IsAutoplayEnabled() && (!aDocument || !aDocument->IsStaticDocument());
+    // The preload action depends on the value of the autoplay attribute.
+    // It's value may have changed, so update it.
+    UpdatePreloadAction();
   }
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument,
                                                  aParent,
                                                  aBindingParent,
                                                  aCompileEventHandlers);
   if (aDocument) {
     if (NS_SUCCEEDED(rv) &&
         mIsDoneAddingChildren &&
@@ -1636,17 +1775,17 @@ void nsHTMLMediaElement::FirstFrameLoade
   ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA);
   ChangeDelayLoadStatus(PR_FALSE);
 
   NS_ASSERTION(!mSuspendedAfterFirstFrame, "Should not have already suspended");
 
   if (mDecoder && mAllowSuspendAfterFirstFrame && mPaused &&
       !aResourceFullyLoaded &&
       !HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay) &&
-      !HasAttr(kNameSpaceID_None, nsGkAtoms::autobuffer)) {
+      mPreloadAction == nsHTMLMediaElement::PRELOAD_METADATA) {
     mSuspendedAfterFirstFrame = PR_TRUE;
     mDecoder->Suspend();
   }
 }
 
 void nsHTMLMediaElement::ResourceLoaded()
 {
   mBegun = PR_FALSE;
@@ -1939,16 +2078,17 @@ nsresult nsHTMLMediaElement::DispatchPro
   return target->DispatchEvent(event, &dummy);
 }
 
 nsresult nsHTMLMediaElement::DoneAddingChildren(PRBool aHaveNotified)
 {
   if (!mIsDoneAddingChildren) {
     mIsDoneAddingChildren = PR_TRUE;
 
+    UpdatePreloadAction();
     if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
       QueueSelectResourceTask();
     }
   }
 
   return NS_OK;
 }
 
--- a/content/html/content/src/nsHTMLTableElement.cpp
+++ b/content/html/content/src/nsHTMLTableElement.cpp
@@ -1056,33 +1056,32 @@ MapAttributesIntoRule(const nsMappedAttr
   // when the display type is changed).
 
   nsPresContext* presContext = aData->mPresContext;
   nsCompatibility mode = presContext->CompatibilityMode();
 
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(TableBorder)) {
     const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
     if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL) {
-      // cellspacing 
+      // cellspacing
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::cellspacing);
       if (value && value->Type() == nsAttrValue::eInteger) {
-        if (aData->mTableData->mBorderSpacing.mXValue.GetUnit() == eCSSUnit_Null)
-          aData->mTableData->mBorderSpacing.mXValue.SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
-        if (aData->mTableData->mBorderSpacing.mYValue.GetUnit() == eCSSUnit_Null)
-          aData->mTableData->mBorderSpacing.mYValue.SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
+        if (aData->mTableData->mBorderSpacing.GetUnit() == eCSSUnit_Null)
+          aData->mTableData->mBorderSpacing.
+            SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
       }
-      else if (value && value->Type() == nsAttrValue::ePercent && eCompatibility_NavQuirks == mode) {
+      else if (value && value->Type() == nsAttrValue::ePercent &&
+               eCompatibility_NavQuirks == mode) {
         // in quirks mode, treat a % cellspacing value a pixel value.
-        if (aData->mTableData->mBorderSpacing.mXValue.GetUnit() == eCSSUnit_Null)
-          aData->mTableData->mBorderSpacing.mXValue.SetFloatValue(100.0f * value->GetPercentValue(), eCSSUnit_Pixel);
-        if (aData->mTableData->mBorderSpacing.mYValue.GetUnit() == eCSSUnit_Null)
-          aData->mTableData->mBorderSpacing.mYValue.SetFloatValue(100.0f * value->GetPercentValue(), eCSSUnit_Pixel);
+        if (aData->mTableData->mBorderSpacing.GetUnit() == eCSSUnit_Null)
+          aData->mTableData->mBorderSpacing.
+            SetFloatValue(100.0f * value->GetPercentValue(), eCSSUnit_Pixel);
       }
     }
-  } 
+  }
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Table)) {
     const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
     if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL) {
       const nsAttrValue* value;
       // layout
       if (aData->mTableData->mLayout.GetUnit() == eCSSUnit_Null) {
         value = aAttributes->GetAttr(nsGkAtoms::layout);
         if (value && value->Type() == nsAttrValue::eEnum)
--- a/content/media/nsBuiltinDecoderReader.h
+++ b/content/media/nsBuiltinDecoderReader.h
@@ -371,17 +371,17 @@ public:
             PRInt64 aTimeStart,
             PRInt64 aTimeEnd)
     : mOffsetStart(aOffsetStart),
       mOffsetEnd(aOffsetEnd),
       mTimeStart(aTimeStart),
       mTimeEnd(aTimeEnd)
   {}
 
-  PRBool IsNull() {
+  PRBool IsNull() const {
     return mOffsetStart == 0 &&
            mOffsetEnd == 0 &&
            mTimeStart == 0 &&
            mTimeEnd == 0;
   }
 
   PRInt64 mOffsetStart, mOffsetEnd; // in bytes.
   PRInt64 mTimeStart, mTimeEnd; // in ms.
@@ -433,18 +433,22 @@ public:
   virtual VideoData* FindStartTime(PRInt64 aOffset,
                                    PRInt64& aOutStartTime);
 
   // Returns the end time of the last page which occurs before aEndOffset.
   // This will not read past aEndOffset. Returns -1 on failure. 
   virtual PRInt64 FindEndTime(PRInt64 aEndOffset);
 
   // Moves the decode head to aTime milliseconds. aStartTime and aEndTime
-  // denote the start and end times of the media.
-  virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime) = 0;
+  // denote the start and end times of the media in ms, and aCurrentTime
+  // is the current playback position in ms.
+  virtual nsresult Seek(PRInt64 aTime,
+                        PRInt64 aStartTime,
+                        PRInt64 aEndTime,
+                        PRInt64 aCurrentTime) = 0;
 
   // Gets presentation info required for playback.
   const nsVideoInfo& GetInfo() {
     return mInfo;
   }
 
   // Queue of audio samples. This queue is threadsafe.
   MediaQueue<SoundData> mAudioQueue;
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -934,17 +934,20 @@ nsresult nsBuiltinDecoderStateMachine::R
           StopPlayback(AUDIO_SHUTDOWN);
           StopDecodeThreads();
           ResetPlayback();
           nsresult res;
           {
             MonitorAutoExit exitMon(mDecoder->GetMonitor());
             // Now perform the seek. We must not hold the state machine monitor
             // while we seek, since the seek decodes.
-            res = mReader->Seek(seekTime, mStartTime, mEndTime);
+            res = mReader->Seek(seekTime,
+                                mStartTime,
+                                mEndTime,
+                                mCurrentFrameTime + mStartTime);
           }
           if (NS_SUCCEEDED(res)){
             PRInt64 audioTime = seekTime;
             SoundData* audio = HasAudio() ? mReader->mAudioQueue.PeekFront() : nsnull;
             if (audio) {
               audioTime = audio->mTime;
               mPlayDuration = TimeDuration::FromMilliseconds(mAudioStartTime);
             }
--- a/content/media/ogg/nsOggCodecState.cpp
+++ b/content/media/ogg/nsOggCodecState.cpp
@@ -38,16 +38,23 @@
  * ***** END LICENSE BLOCK ***** */
 #include "nsDebug.h"
 #include "nsOggCodecState.h"
 #include "nsOggDecoder.h"
 #include <string.h>
 #include "nsTraceRefcnt.h"
 #include "VideoUtils.h"
 
+#ifdef PR_LOGGING
+extern PRLogModuleInfo* gBuiltinDecoderLog;
+#define LOG(type, msg) PR_LOG(gBuiltinDecoderLog, type, msg)
+#else
+#define LOG(type, msg)
+#endif
+
 /*
    The maximum height and width of the video. Used for
    sanitizing the memory allocation of the RGB buffer.
    The maximum resolution we anticipate encountering in the
    wild is 2160p - 3840x2160 pixels.
 */
 #define MAX_VIDEO_WIDTH  4000
 #define MAX_VIDEO_HEIGHT 3000
@@ -359,36 +366,361 @@ PRBool nsVorbisState::Init()
     if (mActive) {
       vorbis_dsp_clear(&mDsp);
     }
     return mActive = PR_FALSE;
   }
   return PR_TRUE;
 }
 
-PRInt64 nsVorbisState::Time(PRInt64 granulepos) {
+PRInt64 nsVorbisState::Time(PRInt64 granulepos)
+{
   if (granulepos == -1 || !mActive || mDsp.vi->rate == 0) {
     return -1;
   }
   PRInt64 t = 0;
   MulOverflow(1000, granulepos, t);
   return t / mDsp.vi->rate;
 }
 
 nsSkeletonState::nsSkeletonState(ogg_page* aBosPage)
-  : nsOggCodecState(aBosPage)
+  : nsOggCodecState(aBosPage),
+    mVersion(0),
+    mLength(0)
 {
   MOZ_COUNT_CTOR(nsSkeletonState);
 }
-
+ 
 nsSkeletonState::~nsSkeletonState()
 {
   MOZ_COUNT_DTOR(nsSkeletonState);
 }
 
+// Support for Ogg Skeleton 4.0, as per specification at:
+// http://wiki.xiph.org/Ogg_Skeleton_4
+
+// Minimum length in bytes of a Skeleton 4.0 header packet.
+#define SKELETON_4_0_MIN_HEADER_LEN 80
+
+// Minimum length in bytes of a Skeleton 4.0 index packet.
+#define SKELETON_4_0_MIN_INDEX_LEN 42
+
+// Minimum possible size of a compressed index keypoint.
+#define MIN_KEY_POINT_SIZE 2
+
+// Byte offset of the major and minor version numbers in the
+// Ogg Skeleton 4.0 header packet.
+#define SKELETON_VERSION_MAJOR_OFFSET 8
+#define SKELETON_VERSION_MINOR_OFFSET 10
+
+// Byte-offsets of the length of file field in the Skeleton 4.0 header packet.
+#define SKELETON_FILE_LENGTH_OFFSET 64
+
+// Byte-offsets of the fields in the Skeleton index packet.
+#define INDEX_SERIALNO_OFFSET 6
+#define INDEX_NUM_KEYPOINTS_OFFSET 10
+#define INDEX_TIME_DENOM_OFFSET 18
+#define INDEX_FIRST_NUMER_OFFSET 26
+#define INDEX_LAST_NUMER_OFFSET 34
+#define INDEX_KEYPOINT_OFFSET 42
+
+static PRBool IsSkeletonBOS(ogg_packet* aPacket)
+{
+  return aPacket->bytes >= SKELETON_4_0_MIN_HEADER_LEN && 
+         memcmp(reinterpret_cast<char*>(aPacket->packet), "fishead", 8) == 0;
+}
+
+static PRBool IsSkeletonIndex(ogg_packet* aPacket)
+{
+  return aPacket->bytes >= SKELETON_4_0_MIN_INDEX_LEN &&
+         memcmp(reinterpret_cast<char*>(aPacket->packet), "index", 5) == 0;
+}
+
+// Reads a little-endian encoded unsigned 32bit integer at p.
+static PRUint32 LEUint32(const unsigned char* p)
+{
+  return p[0] +
+        (p[1] << 8) + 
+        (p[2] << 16) +
+        (p[3] << 24);
+}
+
+// Reads a little-endian encoded 64bit integer at p.
+static PRInt64 LEInt64(const unsigned char* p)
+{
+  PRUint32 lo = LEUint32(p);
+  PRUint32 hi = LEUint32(p + 4);
+  return static_cast<PRInt64>(lo) | (static_cast<PRInt64>(hi) << 32);
+}
+
+// Reads a little-endian encoded unsigned 16bit integer at p.
+static PRUint16 LEUint16(const unsigned char* p)
+{
+  return p[0] + (p[1] << 8);  
+}
+
+// Reads a variable length encoded integer at p. Will not read
+// past aLimit. Returns pointer to character after end of integer.
+static const unsigned char* ReadVariableLengthInt(const unsigned char* p,
+                                                  const unsigned char* aLimit,
+                                                  PRInt64& n)
+{
+  int shift = 0;
+  PRInt64 byte = 0;
+  n = 0;
+  while (p < aLimit &&
+         (byte & 0x80) != 0x80 &&
+         shift < 57)
+  {
+    byte = static_cast<PRInt64>(*p);
+    n |= ((byte & 0x7f) << shift);
+    shift += 7;
+    p++;
+  }
+  return p;
+}
+
+PRBool nsSkeletonState::DecodeIndex(ogg_packet* aPacket)
+{
+  NS_ASSERTION(aPacket->bytes >= SKELETON_4_0_MIN_INDEX_LEN,
+               "Index must be at least minimum size");
+  if (!mActive) {
+    return PR_FALSE;
+  }
+
+  PRUint32 serialno = LEUint32(aPacket->packet + INDEX_SERIALNO_OFFSET);
+  PRInt64 numKeyPoints = LEInt64(aPacket->packet + INDEX_NUM_KEYPOINTS_OFFSET);
+
+  PRInt64 n = 0;
+  PRInt64 endTime = 0, startTime = 0;
+  const unsigned char* p = aPacket->packet;
+
+  PRInt64 timeDenom = LEInt64(aPacket->packet + INDEX_TIME_DENOM_OFFSET);
+  if (timeDenom == 0) {
+    LOG(PR_LOG_DEBUG, ("Ogg Skeleton Index packet for stream %u has 0 "
+                       "timestamp denominator.", serialno));
+    return (mActive = PR_FALSE);
+  }
+
+  // Extract the start time.
+  n = LEInt64(p + INDEX_FIRST_NUMER_OFFSET);
+  PRInt64 t;
+  if (!MulOverflow(n, 1000, t)) {
+    return (mActive = PR_FALSE);
+  } else {
+    startTime = t / timeDenom;
+  }
+
+  // Extract the end time.
+  n = LEInt64(p + INDEX_LAST_NUMER_OFFSET);
+  if (!MulOverflow(n, 1000, t)) {
+    return (mActive = PR_FALSE);
+  } else {
+    endTime = t / timeDenom;
+  }
+
+  // Check the numKeyPoints value read, ensure we're not going to run out of
+  // memory while trying to decode the index packet.
+  PRInt64 minPacketSize;
+  if (!MulOverflow(numKeyPoints, MIN_KEY_POINT_SIZE, minPacketSize) ||
+      !AddOverflow(INDEX_KEYPOINT_OFFSET, minPacketSize, minPacketSize))
+  {
+    return (mActive = PR_FALSE);
+  }
+  
+  PRInt64 sizeofIndex = aPacket->bytes - INDEX_KEYPOINT_OFFSET;
+  PRInt64 maxNumKeyPoints = sizeofIndex / MIN_KEY_POINT_SIZE;
+  if (aPacket->bytes < minPacketSize ||
+      numKeyPoints > maxNumKeyPoints || 
+      numKeyPoints < 0)
+  {
+    // Packet size is less than the theoretical minimum size, or the packet is
+    // claiming to store more keypoints than it's capable of storing. This means
+    // that the numKeyPoints field is too large or small for the packet to
+    // possibly contain as many packets as it claims to, so the numKeyPoints
+    // field is possibly malicious. Don't try decoding this index, we may run
+    // out of memory.
+    LOG(PR_LOG_DEBUG, ("Possibly malicious number of key points reported "
+                       "(%lld) in index packet for stream %u.",
+                       numKeyPoints,
+                       serialno));
+    return (mActive = PR_FALSE);
+  }
+
+  nsAutoPtr<nsKeyFrameIndex> keyPoints(new nsKeyFrameIndex(startTime, endTime));
+  
+  p = aPacket->packet + INDEX_KEYPOINT_OFFSET;
+  const unsigned char* limit = aPacket->packet + aPacket->bytes;
+  PRInt64 numKeyPointsRead = 0;
+  PRInt64 offset = 0;
+  PRInt64 time = 0;
+  while (p < limit &&
+         numKeyPointsRead < numKeyPoints)
+  {
+    PRInt64 delta = 0;
+    p = ReadVariableLengthInt(p, limit, delta);
+    if (p == limit ||
+        !AddOverflow(offset, delta, offset) ||
+        offset > mLength ||
+        offset < 0)
+    {
+      return (mActive = PR_FALSE);
+    }
+    p = ReadVariableLengthInt(p, limit, delta);
+    if (!AddOverflow(time, delta, time) ||
+        time > endTime ||
+        time < startTime)
+    {
+      return (mActive = PR_FALSE);
+    }
+    PRInt64 timeMs = 0;
+    if (!MulOverflow(time, 1000, timeMs))
+      return mActive = PR_FALSE;
+    timeMs /= timeDenom;
+    keyPoints->Add(offset, timeMs);
+    numKeyPointsRead++;
+  }
+
+  PRInt32 keyPointsRead = keyPoints->Length();
+  if (keyPointsRead > 0) {
+    mIndex.Put(serialno, keyPoints.forget());
+  }
+
+  LOG(PR_LOG_DEBUG, ("Loaded %d keypoints for Skeleton on stream %u",
+                     keyPointsRead, serialno));
+  return PR_TRUE;
+}
+
+nsresult nsSkeletonState::IndexedSeekTargetForTrack(PRUint32 aSerialno,
+                                                    PRInt64 aTarget,
+                                                    nsKeyPoint& aResult)
+{
+  nsKeyFrameIndex* index = nsnull;
+  mIndex.Get(aSerialno, &index);
+
+  if (!index ||
+      index->Length() == 0 ||
+      aTarget < index->mStartTime ||
+      aTarget > index->mEndTime)
+  {
+    return NS_ERROR_FAILURE;
+  }
+
+  // Binary search to find the last key point with time less than target.
+  int start = 0;
+  int end = index->Length() - 1;
+  while (end > start) {
+    int mid = start + ((end - start + 1) >> 1);
+    if (index->Get(mid).mTime == aTarget) {
+       start = mid;
+       break;
+    } else if (index->Get(mid).mTime < aTarget) {
+      start = mid;
+    } else {
+      end = mid - 1;
+    }
+  }
+
+  aResult = index->Get(start);
+  NS_ASSERTION(aResult.mTime <= aTarget, "Result should have time <= target");
+  return NS_OK;
+}
+
+nsresult nsSkeletonState::IndexedSeekTarget(PRInt64 aTarget,
+                                            nsTArray<PRUint32>& aTracks,
+                                            nsSeekTarget& aResult)
+{
+  if (!mActive || mVersion < SKELETON_VERSION(4,0)) {
+    return NS_ERROR_FAILURE;
+  }
+  // Loop over all requested tracks' indexes, and get the keypoint for that
+  // seek target. Record the keypoint with the lowest offset, this will be
+  // our seek result. User must seek to the one with lowest offset to ensure we
+  // pass "keyframes" on all tracks when we decode forwards to the seek target.
+  nsSeekTarget r;
+  for (PRUint32 i=0; i<aTracks.Length(); i++) {
+    nsKeyPoint k;
+    if (NS_SUCCEEDED(IndexedSeekTargetForTrack(aTracks[i], aTarget, k)) &&
+        k.mOffset < r.mKeyPoint.mOffset)
+    {
+      r.mKeyPoint = k;
+      r.mSerial = aTracks[i];
+    }
+  }
+  if (r.IsNull()) {
+    return NS_ERROR_FAILURE;
+  }
+  LOG(PR_LOG_DEBUG, ("Indexed seek target for time %lld is offset %lld",
+                     aTarget, r.mKeyPoint.mOffset));
+  aResult = r;
+  return NS_OK;
+}
+
+nsresult nsSkeletonState::GetDuration(const nsTArray<PRUint32>& aTracks,
+                                      PRInt64& aDuration)
+{
+  if (!mActive ||
+      mVersion < SKELETON_VERSION(4,0) ||
+      !HasIndex() ||
+      aTracks.Length() == 0)
+  {
+    return NS_ERROR_FAILURE;
+  }
+  PRInt64 endTime = PR_INT64_MIN;
+  PRInt64 startTime = PR_INT64_MAX;
+  for (PRUint32 i=0; i<aTracks.Length(); i++) {
+    nsKeyFrameIndex* index = nsnull;
+    mIndex.Get(aTracks[i], &index);
+    if (!index) {
+      // Can't get the timestamps for one of the required tracks, fail.
+      return NS_ERROR_FAILURE;
+    }
+    if (index->mEndTime > endTime) {
+      endTime = index->mEndTime;
+    }
+    if (index->mStartTime < startTime) {
+      startTime = index->mStartTime;
+    }
+  }
+  NS_ASSERTION(endTime > startTime, "Duration must be positive");
+  return AddOverflow(endTime, -startTime, aDuration) ? NS_OK : NS_ERROR_FAILURE;
+}
+
 PRBool nsSkeletonState::DecodeHeader(ogg_packet* aPacket)
 {
-  if (aPacket->e_o_s) {
+  if (IsSkeletonBOS(aPacket)) {
+    PRUint16 verMajor = LEUint16(aPacket->packet + SKELETON_VERSION_MAJOR_OFFSET);
+    PRUint16 verMinor = LEUint16(aPacket->packet + SKELETON_VERSION_MINOR_OFFSET);
+    mVersion = SKELETON_VERSION(verMajor, verMinor);
+    if (mVersion < SKELETON_VERSION(4,0) ||
+        mVersion >= SKELETON_VERSION(5,0) ||
+        aPacket->bytes < SKELETON_4_0_MIN_HEADER_LEN)
+    {
+      // We can only care to parse Skeleton version 4.0+.
+      mActive = PR_FALSE;
+      return mDoneReadingHeaders = PR_TRUE;
+    }
+
+    // Extract the segment length.
+    mLength = LEInt64(aPacket->packet + SKELETON_FILE_LENGTH_OFFSET);
+
+    LOG(PR_LOG_DEBUG, ("Skeleton segment length: %lld", mLength));
+
+    // Initialize the serianlno-to-index map.
+    PRBool init = mIndex.Init();
+    if (!init) {
+      NS_WARNING("Failed to initialize Ogg skeleton serialno-to-index map");
+      mActive = PR_FALSE;
+      return mDoneReadingHeaders = PR_TRUE;
+    }
     mActive = PR_TRUE;
+  } else if (IsSkeletonIndex(aPacket) && mVersion >= SKELETON_VERSION(4,0)) {
+    if (!DecodeIndex(aPacket)) {
+      // Failed to parse index, or invalid/hostile index. DecodeIndex() will
+      // have deactivated the track.
+      return mDoneReadingHeaders = PR_TRUE;
+    }
+
+  } else if (aPacket->e_o_s) {
     mDoneReadingHeaders = PR_TRUE;
   }
   return mDoneReadingHeaders;
 }
--- a/content/media/ogg/nsOggCodecState.h
+++ b/content/media/ogg/nsOggCodecState.h
@@ -38,16 +38,19 @@
  * ***** END LICENSE BLOCK ***** */
 #if !defined(nsOggCodecState_h_)
 #define nsOggCodecState_h_
 
 #include <ogg/ogg.h>
 #include <theora/theoradec.h>
 #include <vorbis/codec.h>
 #include <nsDeque.h>
+#include <nsTArray.h>
+#include <nsClassHashtable.h>
+#include "VideoUtils.h"
 
 class OggPageDeallocator : public nsDequeFunctor {
   virtual void* operator() (void* aPage) {
     ogg_page* p = static_cast<ogg_page*>(aPage);
     delete p->header;
     delete p;
     return nsnull;
   }
@@ -121,18 +124,16 @@ class nsOggCodecState {
   // the bitstream at a later time (using PageInFromBuffer()). Memory stored in
   // cloned pages is freed when Reset() or PageInFromBuffer() are called.
   inline void AddToBuffer(ogg_page* aPage) { mBuffer.Append(aPage); }
 
   // Returns PR_TRUE if we had a buffered page and we successfully inserted it
   // into the bitstream.
   PRBool PageInFromBuffer();
 
-public:
-
   // Number of packets read.  
   PRUint64 mPacketCount;
 
   // Serial number of the bitstream.
   PRUint32 mSerial;
 
   // Ogg specific state.
   ogg_stream_state mState;
@@ -188,19 +189,136 @@ public:
   PRUint32 mFrameDuration;
 
   // Number of frames per second.
   float mFrameRate;
 
   float mPixelAspectRatio;
 };
 
+// Constructs a 32bit version number out of two 16 bit major,minor
+// version numbers.
+#define SKELETON_VERSION(major, minor) (((major)<<16)|(minor))
+
 class nsSkeletonState : public nsOggCodecState {
 public:
   nsSkeletonState(ogg_page* aBosPage);
   virtual ~nsSkeletonState();
   virtual CodecType GetType() { return TYPE_SKELETON; }
   virtual PRBool DecodeHeader(ogg_packet* aPacket);
   virtual PRInt64 Time(PRInt64 granulepos) { return -1; }
   virtual PRBool Init() { return PR_TRUE; }
+
+
+  // Stores the offset of the page on which a keyframe starts,
+  // and its presentation time.
+  class nsKeyPoint {
+  public:
+    nsKeyPoint()
+      : mOffset(PR_INT64_MAX),
+        mTime(PR_INT64_MAX) {}
+
+    nsKeyPoint(PRInt64 aOffset, PRInt64 aTime)
+      : mOffset(aOffset),
+        mTime(aTime) {}
+
+    // Offset from start of segment/link-in-the-chain in bytes.
+    PRInt64 mOffset;
+
+    // Presentation time in ms.
+    PRInt64 mTime;
+
+    PRBool IsNull() {
+      return mOffset == PR_INT64_MAX &&
+             mTime == PR_INT64_MAX;
+    }
+  };
+
+  // Stores a keyframe's byte-offset, presentation time and the serialno
+  // of the stream it belongs to.
+  class nsSeekTarget {
+  public:
+    nsSeekTarget() : mSerial(0) {}
+    nsKeyPoint mKeyPoint;
+    PRUint32 mSerial;
+    PRBool IsNull() {
+      return mKeyPoint.IsNull() &&
+             mSerial == 0;
+    }
+  };
+
+  // Determines from the seek index the keyframe which you must seek back to
+  // in order to get all keyframes required to render all streams with
+  // serialnos in aTracks, at time aTarget.
+  nsresult IndexedSeekTarget(PRInt64 aTarget,
+                             nsTArray<PRUint32>& aTracks,
+                             nsSeekTarget& aResult);
+
+  PRBool HasIndex() const {
+    return mIndex.Count() > 0;
+  }
+
+  // Returns the duration of the active tracks in the media, if we have
+  // an index. aTracks must be filled with the serialnos of the active tracks.
+  // The duration is calculated as the greatest end time of all active tracks,
+  // minus the smalled start time of all the active tracks.
+  nsresult GetDuration(const nsTArray<PRUint32>& aTracks, PRInt64& aDuration);
+
+private:
+
+  // Decodes an index packet. Returns PR_FALSE on failure.
+  PRBool DecodeIndex(ogg_packet* aPacket);
+
+  // Gets the keypoint you must seek to in order to get the keyframe required
+  // to render the stream at time aTarget on stream with serial aSerialno.
+  nsresult IndexedSeekTargetForTrack(PRUint32 aSerialno,
+                                     PRInt64 aTarget,
+                                     nsKeyPoint& aResult);
+
+  // Version of the decoded skeleton track, as per the SKELETON_VERSION macro.
+  PRUint32 mVersion;
+
+  // Length of the resource in bytes.
+  PRInt64 mLength;
+
+  // Stores the keyframe index and duration information for a particular
+  // stream.
+  class nsKeyFrameIndex {
+  public:
+
+    nsKeyFrameIndex(PRInt64 aStartTime, PRInt64 aEndTime) 
+      : mStartTime(aStartTime),
+        mEndTime(aEndTime)
+    {
+      MOZ_COUNT_CTOR(nsKeyFrameIndex);
+    }
+
+    ~nsKeyFrameIndex() {
+      MOZ_COUNT_DTOR(nsKeyFrameIndex);
+    }
+
+    void Add(PRInt64 aOffset, PRInt64 aTimeMs) {
+      mKeyPoints.AppendElement(nsKeyPoint(aOffset, aTimeMs));
+    }
+
+    const nsKeyPoint& Get(PRUint32 aIndex) const {
+      return mKeyPoints[aIndex];
+    }
+
+    PRUint32 Length() const {
+      return mKeyPoints.Length();
+    }
+
+    // Presentation time of the first sample in this stream in ms.
+    const PRInt64 mStartTime;
+
+    // End time of the last sample in this stream in ms.
+    const PRInt64 mEndTime;
+
+  private:
+    nsTArray<nsKeyPoint> mKeyPoints;
+  };
+
+  // Maps Ogg serialnos to the index-keypoint list.
+  nsClassHashtable<nsUint32HashKey, nsKeyFrameIndex> mIndex;
 };
 
 #endif
--- a/content/media/ogg/nsOggReader.cpp
+++ b/content/media/ogg/nsOggReader.cpp
@@ -57,24 +57,56 @@ extern PRLogModuleInfo* gBuiltinDecoderL
 #else
 #define SEEK_LOG(type, msg)
 #endif
 #else
 #define LOG(type, msg)
 #define SEEK_LOG(type, msg)
 #endif
 
+// If we don't have a Theora video stream, then during seeking, if a seek
+// target is less than SEEK_DECODE_MARGIN ahead of the current playback
+// position, we'll just decode forwards rather than performing a bisection
+// search. If we have Theora video we use the maximum keyframe interval as
+// this value, rather than SEEK_DECODE_MARGIN. This makes small seeks faster.
+#define SEEK_DECODE_MARGIN 2000
+
+// The number of milliseconds of "fuzz" we use in a bisection search over
+// HTTP. When we're seeking with fuzz, we'll stop the search if a bisection
+// lands between the seek target and SEEK_FUZZ_MS milliseconds before the
+// seek target.  This is becaue it's usually quicker to just keep downloading
+// from an exisiting connection than to do another bisection inside that
+// small range, which would open a new HTTP connetion.
+#define SEEK_FUZZ_MS 500
+
+enum PageSyncResult {
+  PAGE_SYNC_ERROR = 1,
+  PAGE_SYNC_END_OF_RANGE= 2,
+  PAGE_SYNC_OK = 3
+};
+
+// Reads a page from the media stream.
+static PageSyncResult
+PageSync(nsMediaStream* aStream,
+         ogg_sync_state* aState,
+         PRBool aCachedDataOnly,
+         PRInt64 aOffset,
+         PRInt64 aEndOffset,
+         ogg_page* aPage,
+         int& aSkippedBytes);
+
 // Chunk size to read when reading Ogg files. Average Ogg page length
 // is about 4300 bytes, so we read the file in chunks larger than that.
 static const int PAGE_STEP = 8192;
 
 nsOggReader::nsOggReader(nsBuiltinDecoder* aDecoder)
   : nsBuiltinDecoderReader(aDecoder),
     mTheoraState(nsnull),
     mVorbisState(nsnull),
+    mSkeletonState(nsnull),
     mPageOffset(0),
     mTheoraGranulepos(-1),
     mVorbisGranulepos(-1)
 {
   MOZ_COUNT_CTOR(nsOggReader);
 }
 
 nsOggReader::~nsOggReader()
@@ -183,16 +215,22 @@ nsresult nsOggReader::ReadMetadata()
       if (codecState &&
           codecState->GetType() == nsOggCodecState::TYPE_THEORA &&
           !mTheoraState)
       {
         // First Theora bitstream, we'll play this one. Subsequent Theora
         // bitstreams will be ignored.
         mTheoraState = static_cast<nsTheoraState*>(codecState);
       }
+      if (codecState &&
+          codecState->GetType() == nsOggCodecState::TYPE_SKELETON &&
+          !mSkeletonState)
+      {
+        mSkeletonState = static_cast<nsSkeletonState*>(codecState);
+      }
     } else {
       // We've encountered the a non Beginning Of Stream page. No more
       // BOS pages can follow in this Ogg segment, so there will be no other
       // bitstreams in the Ogg (unless it's invalid).
       readAllBOS = PR_TRUE;
     }
 
     mCodecStates.Get(serial, &codecState);
@@ -232,17 +270,17 @@ nsresult nsOggReader::ReadMetadata()
       // muxed, and includes the last header packet on a page with non-header
       // packets. We need to ensure that this is the media start page offset.
       mDataOffset = pageOffset;
     }
   }
   // Deactivate any non-primary bitstreams.
   for (PRUint32 i = 0; i < bitstreams.Length(); i++) {
     nsOggCodecState* s = bitstreams[i];
-    if (s != mVorbisState && s != mTheoraState) {
+    if (s != mVorbisState && s != mTheoraState && s != mSkeletonState) {
       s->Deactivate();
     }
   }
 
   // Initialize the first Theora and Vorbis bitstreams. According to the
   // Theora spec these can be considered the 'primary' bitstreams for playback.
   // Extract the metadata needed from these streams.
   // Set a default callback period for if we have no video data
@@ -254,16 +292,22 @@ nsresult nsOggReader::ReadMetadata()
     } else {
       mTheoraState = nsnull;
     }
   }
   if (mVorbisState) {
     mVorbisState->Init();
   }
 
+  if (!HasAudio() && !HasVideo() && mSkeletonState) {
+    // We have a skeleton track, but no audio or video, may as well disable
+    // the skeleton, we can't do anything useful with this media.
+    mSkeletonState->Deactivate();
+  }
+
   mInfo.mHasAudio = HasAudio();
   mInfo.mHasVideo = HasVideo();
   if (HasAudio()) {
     mInfo.mAudioRate = mVorbisState->mInfo.rate;
     mInfo.mAudioChannels = mVorbisState->mInfo.channels;
   }
   if (HasVideo()) {
     mInfo.mPixelAspectRatio = mTheoraState->mPixelAspectRatio;
@@ -271,16 +315,35 @@ nsresult nsOggReader::ReadMetadata()
     mInfo.mPicture.height = mTheoraState->mInfo.pic_height;
     mInfo.mPicture.x = mTheoraState->mInfo.pic_x;
     mInfo.mPicture.y = mTheoraState->mInfo.pic_y;
     mInfo.mFrame.width = mTheoraState->mInfo.frame_width;
     mInfo.mFrame.height = mTheoraState->mInfo.frame_height;
   }
   mInfo.mDataOffset = mDataOffset;
 
+  if (mSkeletonState && mSkeletonState->HasIndex()) {
+    // Extract the duration info out of the index, so we don't need to seek to
+    // the end of stream to get it.
+    nsAutoTArray<PRUint32, 2> tracks;
+    if (HasVideo()) {
+      tracks.AppendElement(mTheoraState->mSerial);
+    }
+    if (HasAudio()) {
+      tracks.AppendElement(mVorbisState->mSerial);
+    }
+    PRInt64 duration = 0;
+    if (NS_SUCCEEDED(mSkeletonState->GetDuration(tracks, duration))) {
+      MonitorAutoExit exitReaderMon(mMonitor);
+      MonitorAutoEnter decoderMon(mDecoder->GetMonitor());
+      mDecoder->GetStateMachine()->SetDuration(duration);
+      LOG(PR_LOG_DEBUG, ("Got duration from Skeleton index %lld", duration));
+    }
+  }
+
   LOG(PR_LOG_DEBUG, ("Done loading headers, data offset %lld", mDataOffset));
 
   return NS_OK;
 }
 
 nsresult nsOggReader::DecodeVorbis(nsTArray<SoundData*>& aChunks,
                                    ogg_packet* aPacket)
 {
@@ -934,139 +997,272 @@ PRInt64 nsOggReader::FindEndTime(PRInt64
     }
   }
 
   ogg_sync_reset(aState);
 
   return endTime;
 }
 
-nsresult nsOggReader::Seek(PRInt64 aTarget, PRInt64 aStartTime, PRInt64 aEndTime)
+nsOggReader::IndexedSeekResult nsOggReader::RollbackIndexedSeek(PRInt64 aOffset)
+{
+  mSkeletonState->Deactivate();
+  nsMediaStream* stream = mDecoder->GetCurrentStream();
+  NS_ENSURE_TRUE(stream != nsnull, SEEK_FATAL_ERROR);
+  nsresult res = stream->Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
+  NS_ENSURE_SUCCESS(res, SEEK_FATAL_ERROR);
+  return SEEK_INDEX_FAIL;
+}
+ 
+nsOggReader::IndexedSeekResult nsOggReader::SeekToKeyframeUsingIndex(PRInt64 aTarget)
+{
+  nsMediaStream* stream = mDecoder->GetCurrentStream();
+  NS_ENSURE_TRUE(stream != nsnull, SEEK_FATAL_ERROR);
+  if (!HasSkeleton() || !mSkeletonState->HasIndex()) {
+    return SEEK_INDEX_FAIL;
+  }
+  // We have an index from the Skeleton track, try to use it to seek.
+  nsAutoTArray<PRUint32, 2> tracks;
+  if (HasVideo()) {
+    tracks.AppendElement(mTheoraState->mSerial);
+  }
+  if (HasAudio()) {
+    tracks.AppendElement(mVorbisState->mSerial);
+  }
+  nsSkeletonState::nsSeekTarget keyframe;
+  if (NS_FAILED(mSkeletonState->IndexedSeekTarget(aTarget,
+                                                  tracks,
+                                                  keyframe)))
+  {
+    // Could not locate a keypoint for the target in the index.
+    return SEEK_INDEX_FAIL;
+  }
+
+  // Remember original stream read cursor position so we can rollback on failure.
+  PRInt64 tell = stream->Tell();
+
+  // Seek to the keypoint returned by the index.
+  if (keyframe.mKeyPoint.mOffset > stream->GetLength() ||
+      keyframe.mKeyPoint.mOffset < 0)
+  {
+    // Index must be invalid.
+    return RollbackIndexedSeek(tell);
+  }
+  LOG(PR_LOG_DEBUG, ("Seeking using index to keyframe at offset %lld\n",
+                     keyframe.mKeyPoint.mOffset));
+  nsresult res = stream->Seek(nsISeekableStream::NS_SEEK_SET,
+                              keyframe.mKeyPoint.mOffset);
+  NS_ENSURE_SUCCESS(res, SEEK_FATAL_ERROR);
+  mPageOffset = keyframe.mKeyPoint.mOffset;
+
+  // We've moved the read set, so reset decode.
+  res = ResetDecode();
+  NS_ENSURE_SUCCESS(res, SEEK_FATAL_ERROR);
+
+  // Check that the page the index thinks is exactly here is actually exactly
+  // here. If not, the index is invalid.
+  ogg_page page;
+  int skippedBytes = 0;
+  PageSyncResult syncres = PageSync(stream,
+                                    &mOggState,
+                                    PR_FALSE,
+                                    mPageOffset,
+                                    stream->GetLength(),
+                                    &page,
+                                    skippedBytes);
+  NS_ENSURE_TRUE(syncres != PAGE_SYNC_ERROR, SEEK_FATAL_ERROR);
+  if (syncres != PAGE_SYNC_OK || skippedBytes != 0) {
+    LOG(PR_LOG_DEBUG, ("Indexed-seek failure: Ogg Skeleton Index is invalid "
+                       "or sync error after seek"));
+    return RollbackIndexedSeek(tell);
+  }
+  PRUint32 serial = ogg_page_serialno(&page);
+  if (serial != keyframe.mSerial) {
+    // Serialno of page at offset isn't what the index told us to expect.
+    // Assume the index is invalid.
+    return RollbackIndexedSeek(tell);
+  }
+  nsOggCodecState* codecState = nsnull;
+  mCodecStates.Get(serial, &codecState);
+  if (codecState &&
+      codecState->mActive &&
+      ogg_stream_pagein(&codecState->mState, &page) != 0)
+  {
+    // Couldn't insert page into the ogg stream, or somehow the stream
+    // is no longer active.
+    return RollbackIndexedSeek(tell);
+  }      
+  mPageOffset = keyframe.mKeyPoint.mOffset + page.header_len + page.body_len;
+  return SEEK_OK;
+}
+
+nsresult nsOggReader::SeekInBufferedRange(PRInt64 aTarget,
+                                          PRInt64 aStartTime,
+                                          PRInt64 aEndTime,
+                                          const nsTArray<ByteRange>& aRanges,
+                                          const ByteRange& aRange)
+{
+  LOG(PR_LOG_DEBUG, ("%p Seeking in buffered data to %lldms using bisection search", mDecoder, aTarget));
+
+  // We know the exact byte range in which the target must lie. It must
+  // be buffered in the media cache. Seek there.
+  nsresult res = SeekBisection(aTarget, aRange, 0);
+  if (NS_FAILED(res) || !HasVideo()) {
+    return res;
+  }
+
+  // We have an active Theora bitstream. Decode the next Theora frame, and
+  // extract its keyframe's time.
+  PRBool eof;
+  do {
+    PRBool skip = PR_FALSE;
+    eof = !DecodeVideoFrame(skip, 0);
+    {
+      MonitorAutoExit exitReaderMon(mMonitor);
+      MonitorAutoEnter decoderMon(mDecoder->GetMonitor());
+      if (mDecoder->GetDecodeState() == nsBuiltinDecoderStateMachine::DECODER_STATE_SHUTDOWN) {
+        return NS_ERROR_FAILURE;
+      }
+    }
+  } while (!eof &&
+           mVideoQueue.GetSize() == 0);
+
+  VideoData* video = mVideoQueue.PeekFront();
+  if (video && !video->mKeyframe) {
+    // First decoded frame isn't a keyframe, seek back to previous keyframe,
+    // otherwise we'll get visual artifacts.
+    NS_ASSERTION(video->mTimecode != -1, "Must have a granulepos");
+    int shift = mTheoraState->mInfo.keyframe_granule_shift;
+    PRInt64 keyframeGranulepos = (video->mTimecode >> shift) << shift;
+    PRInt64 keyframeTime = mTheoraState->StartTime(keyframeGranulepos);
+    SEEK_LOG(PR_LOG_DEBUG, ("Keyframe for %lld is at %lld, seeking back to it",
+                            video->mTime, keyframeTime));
+    ByteRange k = GetSeekRange(aRanges,
+                               keyframeTime,
+                               aStartTime,
+                               aEndTime,
+                               PR_FALSE);
+    res = SeekBisection(keyframeTime, k, SEEK_FUZZ_MS);
+    NS_ASSERTION(mTheoraGranulepos == -1, "SeekBisection must reset Theora decode");
+    NS_ASSERTION(mVorbisGranulepos == -1, "SeekBisection must reset Vorbis decode");
+  }
+  return res;
+}
+
+PRBool nsOggReader::CanDecodeToTarget(PRInt64 aTarget,
+                                      PRInt64 aCurrentTime)
+{
+  // We can decode to the target if the target is no further than the
+  // maximum keyframe offset ahead of the current playback position, if
+  // we have video, or SEEK_DECODE_MARGIN if we don't have video.
+  PRInt64 margin = HasVideo() ? mTheoraState->MaxKeyframeOffset() : SEEK_DECODE_MARGIN;
+  return aTarget >= aCurrentTime &&
+         aTarget - aCurrentTime < margin;
+}
+
+nsresult nsOggReader::SeekInUnbuffered(PRInt64 aTarget,
+                                       PRInt64 aStartTime,
+                                       PRInt64 aEndTime,
+                                       const nsTArray<ByteRange>& aRanges)
+{
+  LOG(PR_LOG_DEBUG, ("%p Seeking in unbuffered data to %lldms using bisection search", mDecoder, aTarget));
+  
+  // If we've got an active Theora bitstream, determine the maximum possible
+  // time in ms which a keyframe could be before a given interframe. We
+  // subtract this from our seek target, seek to the new target, and then
+  // will decode forward to the original seek target. We should encounter a
+  // keyframe in that interval. This prevents us from needing to run two
+  // bisections; one for the seek target frame, and another to find its
+  // keyframe. It's usually faster to just download this extra data, rather
+  // tham perform two bisections to find the seek target's keyframe. We
+  // don't do this offsetting when seeking in a buffered range,
+  // as the extra decoding causes a noticeable speed hit when all the data
+  // is buffered (compared to just doing a bisection to exactly find the
+  // keyframe).
+  PRInt64 keyframeOffsetMs = 0;
+  if (HasVideo() && mTheoraState) {
+    keyframeOffsetMs = mTheoraState->MaxKeyframeOffset();
+  }
+  PRInt64 seekTarget = NS_MAX(aStartTime, aTarget - keyframeOffsetMs);
+  // Minimize the bisection search space using the known timestamps from the
+  // buffered ranges.
+  ByteRange k = GetSeekRange(aRanges, seekTarget, aStartTime, aEndTime, PR_FALSE);
+  nsresult res = SeekBisection(seekTarget, k, SEEK_FUZZ_MS);
+  NS_ASSERTION(mTheoraGranulepos == -1, "SeekBisection must reset Theora decode");
+  NS_ASSERTION(mVorbisGranulepos == -1, "SeekBisection must reset Vorbis decode");
+  return res;
+}
+
+nsresult nsOggReader::Seek(PRInt64 aTarget,
+                           PRInt64 aStartTime,
+                           PRInt64 aEndTime,
+                           PRInt64 aCurrentTime)
 {
   MonitorAutoEnter mon(mMonitor);
-  nsresult res;
   NS_ASSERTION(mDecoder->OnStateMachineThread(),
                "Should be on state machine thread.");
   LOG(PR_LOG_DEBUG, ("%p About to seek to %lldms", mDecoder, aTarget));
+  nsresult res;
   nsMediaStream* stream = mDecoder->GetCurrentStream();
+  NS_ENSURE_TRUE(stream != nsnull, NS_ERROR_FAILURE);
 
-  if (NS_FAILED(ResetDecode())) {
-    return NS_ERROR_FAILURE;
-  }
   if (aTarget == aStartTime) {
+    // We've seeked to the media start. Just seek to the offset of the first
+    // content page.
     res = stream->Seek(nsISeekableStream::NS_SEEK_SET, mDataOffset);
-    NS_ENSURE_SUCCESS(res, res);
+    NS_ENSURE_SUCCESS(res,res);
+
     mPageOffset = mDataOffset;
+    res = ResetDecode();
+    NS_ENSURE_SUCCESS(res,res);
+
     NS_ASSERTION(aStartTime != -1, "mStartTime should be known");
     {
       MonitorAutoExit exitReaderMon(mMonitor);
       MonitorAutoEnter decoderMon(mDecoder->GetMonitor());
       mDecoder->UpdatePlaybackPosition(aStartTime);
     }
+  } else if (CanDecodeToTarget(aTarget, aCurrentTime)) {
+    LOG(PR_LOG_DEBUG, ("%p Seek target (%lld) is close to current time (%lld), "
+        "will just decode to it", mDecoder, aCurrentTime, aTarget));
   } else {
-
-    // Determine the already downloaded data in the media cache. 
-    nsAutoTArray<ByteRange, 16> ranges;
-    stream->Pin();
-    if (NS_FAILED(GetBufferedBytes(ranges))) {
-      stream->Unpin();
-      return NS_ERROR_FAILURE;
-    }
-
-    // Try to seek in the cached data ranges first, before falling back to
-    // seeking over the network. This makes seeking in buffered ranges almost
-    // instantaneous.
-    ByteRange r = GetSeekRange(ranges, aTarget, aStartTime, aEndTime, PR_TRUE);
-    res = NS_ERROR_FAILURE;
-    if (!r.IsNull()) {
-      // The frame should be in this buffered range. Seek exactly there.
-      res = SeekBisection(aTarget, r, 0);
+    IndexedSeekResult sres = SeekToKeyframeUsingIndex(aTarget);
+    NS_ENSURE_TRUE(sres != SEEK_FATAL_ERROR, NS_ERROR_FAILURE);
+    if (sres == SEEK_INDEX_FAIL) {
+      // No index or other non-fatal index-related failure. Try to seek
+      // using a bisection search. Determine the already downloaded data
+      // in the media cache, so we can try to seek in the cached data first.
+      nsAutoTArray<ByteRange, 16> ranges;
+      res = GetBufferedBytes(ranges);
+      NS_ENSURE_SUCCESS(res,res);
 
-      if (NS_SUCCEEDED(res) && HasVideo()) {
-        // We have an active Theora bitstream. Decode the next Theora frame, and
-        // extract its keyframe's time.
-        PRBool eof;
-        do {
-          PRBool skip = PR_FALSE;
-          eof = !DecodeVideoFrame(skip, 0);
-          {
-            MonitorAutoExit exitReaderMon(mMonitor);
-            MonitorAutoEnter decoderMon(mDecoder->GetMonitor());
-            if (mDecoder->GetDecodeState() == nsBuiltinDecoderStateMachine::DECODER_STATE_SHUTDOWN) {
-              stream->Unpin();
-              return NS_ERROR_FAILURE;
-            }
-          }
-        } while (!eof &&
-                 mVideoQueue.GetSize() == 0);
-      
-        VideoData* video = mVideoQueue.PeekFront();
-        if (video && !video->mKeyframe) {
-          // First decoded frame isn't a keyframe, seek back to previous keyframe,
-          // otherwise we'll get visual artifacts.
-          NS_ASSERTION(video->mTimecode != -1, "Must have a granulepos");
-          int shift = mTheoraState->mInfo.keyframe_granule_shift;
-          PRInt64 keyframeGranulepos = (video->mTimecode >> shift) << shift;
-          PRInt64 keyframeTime = mTheoraState->StartTime(keyframeGranulepos);
-          
-          SEEK_LOG(PR_LOG_DEBUG, ("Keyframe for %lld is at %lld, seeking back to it",
-                                  video->mTime, keyframeTime));
-          ByteRange k = GetSeekRange(ranges,
-                                     keyframeTime,
-                                     aStartTime,
-                                     aEndTime,
-                                     PR_FALSE);
-          res = SeekBisection(keyframeTime, k, 500);
-          NS_ASSERTION(mTheoraGranulepos == -1, "SeekBisection must reset Theora decode");
-          NS_ASSERTION(mVorbisGranulepos == -1, "SeekBisection must reset Vorbis decode");
-        }
+      // Figure out if the seek target lies in a buffered range.
+      ByteRange r = GetSeekRange(ranges, aTarget, aStartTime, aEndTime, PR_TRUE);
+
+      if (!r.IsNull()) {
+        // We know the buffered range in which the seek target lies, do a
+        // bisection search in that buffered range.
+        res = SeekInBufferedRange(aTarget, aStartTime, aEndTime, ranges, r);
+        NS_ENSURE_SUCCESS(res,res);
+      } else {
+        // The target doesn't lie in a buffered range. Perform a bisection
+        // search over the whole media, using the known buffered ranges to
+        // reduce the search space.
+        res = SeekInUnbuffered(aTarget, aStartTime, aEndTime, ranges);
+        NS_ENSURE_SUCCESS(res,res);
       }
     }
-
-    stream->Unpin();
-
-    if (NS_FAILED(res)) {
-      // We failed to find the seek target (or perhaps its keyframe, somehow?)
-      // in a buffered range. Minimize the bisection search space using the
-      // buffered ranges, and perform a bisection search.
+  }
 
-      // If we've got an active Theora bitstream, determine the maximum possible
-      // time in ms which a keyframe could be before a given interframe. We
-      // subtract this from our seek target, seek to the new target, and then
-      // decode forwards to the original seek target. We should encounter a
-      // keyframe in that interval. This prevents us from needing to run two
-      // bisections; one for the seek target frame, and another to find its
-      // keyframe. It's usually faster to just download this extra data, rather
-      // tham perform two bisections to find the seek target's keyframe. We
-      // don't do this offsetting when seeking in a buffered ranges (above),
-      // as the extra decoding causes a noticeable speed hit when all the data
-      // is buffered.
-      PRInt64 keyframeOffsetMs = 0;
-      if (HasVideo() && mTheoraState) {
-        keyframeOffsetMs = mTheoraState->MaxKeyframeOffset();
-      }
-      PRInt64 seekTarget = NS_MAX(aStartTime, aTarget - keyframeOffsetMs);
-
-      ByteRange k = GetSeekRange(ranges, seekTarget, aStartTime, aEndTime, PR_FALSE);
-      res = SeekBisection(seekTarget, k, 500);
-
-      NS_ENSURE_SUCCESS(res, res);
-      NS_ASSERTION(mTheoraGranulepos == -1, "SeekBisection must reset Theora decode");
-      NS_ASSERTION(mVorbisGranulepos == -1, "SeekBisection must reset Vorbis decode");
-    }
-  }
+  // The decode position must now be either close to the seek target, or
+  // we've seeked to before the keyframe before the seek target. Decode
+  // forward to the seek target frame.
   return DecodeToTarget(aTarget);
 }
 
-enum PageSyncResult {
-  PAGE_SYNC_ERROR = 1,
-  PAGE_SYNC_END_OF_RANGE= 2,
-  PAGE_SYNC_OK = 3
-};
-
 // Reads a page from the media stream.
 static PageSyncResult
 PageSync(nsMediaStream* aStream,
          ogg_sync_state* aState,
          PRBool aCachedDataOnly,
          PRInt64 aOffset,
          PRInt64 aEndOffset,
          ogg_page* aPage,
@@ -1135,17 +1331,17 @@ nsresult nsOggReader::SeekBisection(PRIn
   nsresult res;
   nsMediaStream* stream = mDecoder->GetCurrentStream();
 
   if (aTarget == aRange.mTimeStart) {
     if (NS_FAILED(ResetDecode())) {
       return NS_ERROR_FAILURE;
     }
     res = stream->Seek(nsISeekableStream::NS_SEEK_SET, mDataOffset);
-    NS_ENSURE_SUCCESS(res, res);
+    NS_ENSURE_SUCCESS(res,res);
     mPageOffset = mDataOffset;
     return NS_OK;
   }
 
   // Bisection search, find start offset of last page with end time less than
   // the seek target.
   ogg_int64_t startOffset = aRange.mOffsetStart;
   ogg_int64_t startTime = aRange.mTimeStart;
@@ -1217,19 +1413,17 @@ nsresult nsOggReader::SeekBisection(PRIn
       // make a bisection decision based on our location in the media.
       PageSyncResult res = PageSync(stream,
                                     &mOggState,
                                     PR_FALSE,
                                     guess,
                                     endOffset,
                                     &page,
                                     skippedBytes);
-      if (res == PAGE_SYNC_ERROR) {
-        return NS_ERROR_FAILURE;
-      }
+      NS_ENSURE_TRUE(res != PAGE_SYNC_ERROR, NS_ERROR_FAILURE);
 
       // We've located a page of length |ret| at |guess + skippedBytes|.
       // Remember where the page is located.
       pageOffset = guess + skippedBytes;
       pageLength = page.header_len + page.body_len;
       mPageOffset = pageOffset + pageLength;
 
       if (mPageOffset == endOffset || res == PAGE_SYNC_END_OF_RANGE) {
@@ -1299,17 +1493,17 @@ nsresult nsOggReader::SeekBisection(PRIn
     }
 
     if (interval == 0) {
       // Seek termination condition; we've found the page boundary of the
       // last page before the target, and the first page after the target.
       SEEK_LOG(PR_LOG_DEBUG, ("Seek loop (interval == 0) break"));
       NS_ASSERTION(startTime < aTarget, "Start time must always be less than target");
       res = stream->Seek(nsISeekableStream::NS_SEEK_SET, startOffset);
-      NS_ENSURE_SUCCESS(res, res);
+      NS_ENSURE_SUCCESS(res,res);
       mPageOffset = startOffset;
       if (NS_FAILED(ResetDecode())) {
         return NS_ERROR_FAILURE;
       }
       break;
     }
 
     SEEK_LOG(PR_LOG_DEBUG, ("Time at offset %lld is %lldms", guess, granuleTime));
--- a/content/media/ogg/nsOggReader.h
+++ b/content/media/ogg/nsOggReader.h
@@ -39,16 +39,19 @@
 #if !defined(nsOggReader_h_)
 #define nsOggReader_h_
 
 #include <ogg/ogg.h>
 #include <theora/theoradec.h>
 #include <vorbis/codec.h>
 #include "nsBuiltinDecoderReader.h"
 #include "nsOggCodecState.h"
+#include "VideoUtils.h"
+
+using namespace mozilla;
 
 class nsMediaDecoder;
 class nsHTMLTimeRanges;
 
 class nsOggReader : public nsBuiltinDecoderReader
 {
 public:
   nsOggReader(nsBuiltinDecoder* aDecoder);
@@ -79,21 +82,68 @@ public:
 
   virtual PRBool HasVideo()
   {
     mozilla::MonitorAutoEnter mon(mMonitor);
     return mTheoraState != 0 && mTheoraState->mActive;
   }
 
   virtual nsresult ReadMetadata();
-  virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime);
+  virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime);
   virtual nsresult GetBuffered(nsHTMLTimeRanges* aBuffered, PRInt64 aStartTime);
 
 private:
 
+  PRBool HasSkeleton()
+  {
+    MonitorAutoEnter mon(mMonitor);
+    return mSkeletonState != 0 && mSkeletonState->mActive;
+  }
+
+  // Returns PR_TRUE if we should decode up to the seek target rather than
+  // seeking to the target using a bisection search or index-assisted seek.
+  // We should do this if the seek target (aTarget, in ms), lies not too far
+  // ahead of the current playback position (aCurrentTime, in ms).
+  PRBool CanDecodeToTarget(PRInt64 aTarget,
+                           PRInt64 aCurrentTime);
+
+  // Seeks to the keyframe preceeding the target time using available
+  // keyframe indexes.
+  enum IndexedSeekResult {
+    SEEK_OK,          // Success.
+    SEEK_INDEX_FAIL,  // Failure due to no index, or invalid index.
+    SEEK_FATAL_ERROR  // Error returned by a stream operation.
+  };
+  IndexedSeekResult SeekToKeyframeUsingIndex(PRInt64 aTarget);
+
+  // Rolls back a seek-using-index attempt, returning a failure error code.
+  IndexedSeekResult RollbackIndexedSeek(PRInt64 aOffset);
+
+  // Seeks to aTarget ms in the buffered range aRange using bisection search,
+  // or to the keyframe prior to aTarget if we have video. aStartTime must be
+  // the presentation time at the start of media, and aEndTime the time at
+  // end of media. aRanges must be the time/byte ranges buffered in the media
+  // cache as per GetBufferedBytes().
+  nsresult SeekInBufferedRange(PRInt64 aTarget,
+                               PRInt64 aStartTime,
+                               PRInt64 aEndTime,
+                               const nsTArray<ByteRange>& aRanges,
+                               const ByteRange& aRange);
+
+  // Seeks to before aTarget ms in media using bisection search. If the media
+  // has video, this will seek to before the keyframe required to render the
+  // media at aTarget. Will use aRanges in order to narrow the bisection
+  // search space. aStartTime must be the presentation time at the start of
+  // media, and aEndTime the time at end of media. aRanges must be the time/byte
+  // ranges buffered in the media cache as per GetBufferedBytes().
+  nsresult SeekInUnbuffered(PRInt64 aTarget,
+                            PRInt64 aStartTime,
+                            PRInt64 aEndTime,
+                            const nsTArray<ByteRange>& aRanges);
+
   // Get the end time of aEndOffset. This is the playback position we'd reach
   // after playback finished at aEndOffset. If PRBool aCachedDataOnly is
   // PR_TRUE, then we'll only read from data which is cached in the media cached,
   // otherwise we'll do regular blocking reads from the media stream.
   // If PRBool aCachedDataOnly is PR_TRUE, and aState is not mOggState, this can
   // safely be called on the main thread, otherwise it must be called on the
   // state machine thread.
   PRInt64 FindEndTime(PRInt64 aEndOffset,
@@ -132,16 +182,19 @@ private:
   nsClassHashtable<nsUint32HashKey, nsOggCodecState> mCodecStates;
 
   // Decode state of the Theora bitstream we're decoding, if we have video.
   nsTheoraState* mTheoraState;
 
   // Decode state of the Vorbis bitstream we're decoding, if we have audio.
   nsVorbisState* mVorbisState;
 
+  // Decode state of the Skeleton bitstream.
+  nsSkeletonState* mSkeletonState;
+
   // Ogg decoding state.
   ogg_sync_state mOggState;
 
   // The offset of the end of the last page we've read, or the start of
   // the page we're about to read.
   PRInt64 mPageOffset;
 
   // The granulepos of the last decoded Theora frame.
--- a/content/media/raw/nsRawReader.cpp
+++ b/content/media/raw/nsRawReader.cpp
@@ -237,17 +237,17 @@ PRBool nsRawReader::DecodeVideoFrame(PRB
 
   mVideoQueue.Push(v);
   mCurrentFrame++;
   currentFrameTime += 1000 / mFrameRate;
 
   return PR_TRUE;
 }
 
-nsresult nsRawReader::Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime)
+nsresult nsRawReader::Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime)
 {
   mozilla::MonitorAutoEnter autoEnter(mMonitor);
   NS_ASSERTION(mDecoder->OnStateMachineThread(),
                "Should be on state machine thread.");
 
   nsMediaStream *stream = mDecoder->GetCurrentStream();
   NS_ASSERTION(stream, "Decoder has no media stream");
 
--- a/content/media/raw/nsRawReader.h
+++ b/content/media/raw/nsRawReader.h
@@ -106,17 +106,17 @@ public:
   }
 
   virtual PRBool HasVideo()
   {
     return PR_TRUE;
   }
 
   virtual nsresult ReadMetadata();
-  virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime);
+  virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime);
   virtual PRInt64 FindEndTime(PRInt64 aEndOffset);
   virtual nsresult GetBuffered(nsHTMLTimeRanges* aBuffered, PRInt64 aStartTime);
 
 private:
   PRBool ReadFromStream(nsMediaStream *aStream, PRUint8 *aBuf,
                         PRUint32 aLength);
 
   nsRawVideoHeader mMetadata;
--- a/content/media/test/Makefile.in
+++ b/content/media/test/Makefile.in
@@ -86,17 +86,16 @@ include $(topsrcdir)/config/rules.mk
 		seek7.js \
 		seek8.js \
 		seek9.js \
 		seek10.js \
 		seek11.js \
 		test_access_control.html \
 		test_audio1.html \
 		test_audio2.html \
-		test_autobuffer.html \
 		test_autoplay.html \
 		test_buffered.html \
 		test_bug448534.html \
 		test_bug463162.xhtml \
 		test_bug465498.html \
 		test_bug493187.html \
 		test_bug495145.html \
 		test_bug495300.html \
@@ -142,17 +141,17 @@ include $(topsrcdir)/config/rules.mk
 		$(NULL)
 
 # These tests are disabled until we figure out random failures.
 # When these tests are fixed, we should also make them backend-independent.
 #		test_resume.html \
 # Bug 492821:
 #   test_videoDocumentTitle.html
 # Bug 493692:
-#   test_autobuffer2.html
+#   test_preload_suspend.html
 # Disabled since we don't play Wave files standalone, for now
 #		test_audioDocumentTitle.html
 
 ifdef MOZ_OGG
 ifneq ($(OS_ARCH),WINNT)
 # Disabled on windows until we figure out the random failures.
 # When this is fixed, make it backend-independent please.
 # See bug 475369 and bug 526323
@@ -182,16 +181,17 @@ endif
 		bug500311.ogv \
 		bug500311.ogv^headers^ \
 		bug501279.ogg \
 		bug504613.ogv \
 		bug504644.ogv \
 		bug504843.ogv \
 		bug506094.ogv \
 		bug516323.ogv \
+		bug516323.indexed.ogv \
 		bug520493.ogg \
 		bug520500.ogg \
 		bug520908.ogv \
 		bug520908.ogv^headers^ \
 		bug523816.ogv \
 		bug533822.ogg \
 		bug557094.ogv \
 		bug580982.webm \
new file mode 100644
index 0000000000000000000000000000000000000000..da620fffcd35256ec4f08c42174823db2cce33fa
GIT binary patch
literal 162028
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%0DLSU<_w@qsGz0Gb(
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
R;Pv><?U3dluwYm2{{dS7NK60#
--- a/content/media/test/manifest.js
+++ b/content/media/test/manifest.js
@@ -198,16 +198,17 @@ var gErrorTests = [
 ];
 
 // These are files that have nontrivial duration and are useful for seeking within.
 var gSeekTests = [
   { name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
   { name:"seek.ogv", type:"video/ogg", duration:3.966 },
   { name:"320x240.ogv", type:"video/ogg", duration:0.233 },
   { name:"seek.webm", type:"video/webm", duration:3.966 },
+  { name:"bug516323.indexed.ogv", type:"video/ogg", duration:4.208 },
   { name:"bogus.duh", type:"bogus/duh", duration:123 }
 ];
 
 // These are files suitable for using with a "new Audio" constructor.
 var gAudioTests = [
   { name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
   { name:"sound.ogg", type:"audio/ogg" },
   { name:"bogus.duh", type:"bogus/duh", duration:123 }
--- a/content/media/test/test_audio1.html
+++ b/content/media/test/test_audio1.html
@@ -11,15 +11,15 @@
 <pre id="test">
 <script class="testbody" type="text/javascript">
 for (var i = 0; i < gAudioTests.length; ++i) {
   var test = gAudioTests[i];
   var a1 = new Audio();
   if (!a1.canPlayType(test.type))
     continue;
 
-  is(a1.getAttribute("autobuffer"), "autobuffer", "Autobuffer automatically set");
+  is(a1.getAttribute("preload"), "auto", "preload:auto automatically set");
   is(a1.src, "", "Src set?");
 }
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/test/test_audio2.html
+++ b/content/media/test/test_audio2.html
@@ -12,15 +12,15 @@
 <script class="testbody" type="text/javascript">
 var tmpAudio = new Audio();
 for (var i = 0; i < gAudioTests.length; ++i) {
   var test = gAudioTests[i];
   if (!tmpAudio.canPlayType(test.type))
     continue;
 
   var a1 = new Audio(test.name);
-  is(a1.getAttribute("autobuffer"), "autobuffer", "Autobuffer automatically set");
+  is(a1.getAttribute("preload"), "auto", "Preload automatically set to auto");
   is(a1.src.match("/[^/]+$"), "/" + test.name, "src OK");
 }
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/test/test_bug493187.html
+++ b/content/media/test/test_bug493187.html
@@ -49,17 +49,17 @@ for (var i=0; i<gSeekTests.length; ++i) 
 
   var v = document.createElement('video');
   if (!v.canPlayType(test.type))
     continue;
   v.src = test.name;
   v._name = test.name;
   v._seeked = false;
   v._finished = false;
-  v.autobuffer = true;
+  v.preload = "auto";
   v.addEventListener("loadedmetadata", start, false);
   v.addEventListener("canplaythrough", canPlayThrough, false);
   v.addEventListener("seeking", startSeeking, false);
   document.body.appendChild(v);
   videos.push(v);
 }
 
 if (videos.length == 0) {
--- a/content/media/test/test_load.html
+++ b/content/media/test/test_load.html
@@ -47,17 +47,17 @@ function listener(evt) {
     setTimeout(nextTest, 0); 
   }
 }
 
 var gMedia = null;
 
 function createMedia(tag) {
   gMedia = document.createElement(tag);
-  gMedia.setAttribute("autobuffer", "true");
+  gMedia.setAttribute("preload", "auto");
   for (var i=0; i<gEventTypes.length; i++) {
     gMedia.addEventListener(gEventTypes[i], listener, false);
   }
 }
 
 function addSource(src, type) {
   var s = document.createElement("source");
   s.src = src;
new file mode 100644
--- /dev/null
+++ b/content/media/test/test_preload_actions.html
@@ -0,0 +1,550 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=548523
+-->
+<head>
+  <title>Test for Bug 548523</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="text/javascript" src="manifest.js"></script>
+  <script type="text/javascript" src="use_large_cache.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=548523">Mozilla Bug 548523</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<!-- <button onClick="SimpleTest.finish();">Finish</button> -->
+<div>Tests complete: <span id="log" style="font-size: small;"></span></div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 548523 **/
+
+var videos = [];
+
+var test = getPlayableVideo(gSeekTests);
+var bogusSrc = "bogus.duh";
+var bogusType = "video/bogus";
+var gotLoadEvent = false;
+var finished = false;
+
+addLoadEvent(function() {gotLoadEvent=true;});
+
+function log(m) {
+  var l = document.getElementById("log");
+  l.innerHTML += m;
+}
+
+function maybeFinish(n) {
+  log(n + ",");
+  setTimeout(
+  function() {
+    if (!finished && AllFinished(videos)) {
+      finished = true;
+      is(gotLoadEvent, true, "Should not have delayed the load event indefinitely");
+      SimpleTest.finish();
+    }
+  }, 0);
+}
+
+function filename(uri) {
+  return uri.substr(uri.lastIndexOf("/")+1);
+}
+
+// Every test must have a setup(v) function, and must set _finished field on target v to
+// true when test is complete.
+var tests = [
+  {
+    // 1. Add preload:none video with src to document. Load should halt at NETWORK_IDLE and HAVE_NOTHING,
+    // after receiving a suspend event. Should not receive loaded events until after we call load().
+    // Note the suspend event is explictly sent by our "stop the load" code, but other tests can't rely
+    // on it for the preload:metadata case, as there can be multiple suspend events when loading metadata.
+    suspend:
+    function(e) {
+      var v = e.target;
+      is(v._gotLoadStart, true, "(1) Must get loadstart.");
+      is(v._gotLoadedMetaData, false, "(1) Must not get loadedmetadata.");
+      is(v.readyState, v.HAVE_NOTHING, "(1) ReadyState must be HAVE_NOTHING");
+      is(v.networkState, v.NETWORK_IDLE, "(1) NetworkState must be NETWORK_IDLE");
+      v._finished = true;
+      maybeFinish(1);
+    },
+    
+    setup:
+    function(v) {
+      v._gotLoadStart = false;
+      v._gotLoadedMetaData = false;
+      v._finished = false;
+      v.preload = "none";
+      v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
+      v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
+      v.addEventListener("suspend", this.suspend, false);
+      v.src = test.name;
+      document.body.appendChild(v); // Causes implicit load, which will be halted due to preload:none.
+    },
+  },
+  {
+    // 2. Add preload:metadata video with src to document. Should halt with NETWORK_IDLE, HAVE_CURRENT_DATA
+    // after suspend event and after loadedmetadata.
+    loadeddata:
+    function(e) {
+      var v = e.target;
+      is(v._gotLoadStart, true, "(2) Must get loadstart.");
+      is(v._gotLoadedMetaData, true, "(2) Must get loadedmetadata.");
+      ok(v.readyState >= v.HAVE_CURRENT_DATA, "(2) ReadyState must be >= HAVE_CURRENT_DATA");
+      is(v.networkState, v.NETWORK_IDLE, "(2) NetworkState must be NETWORK_IDLE");
+      v._finished = true;
+      maybeFinish(2);
+    },
+    
+    setup:
+    function(v) {
+      v._gotLoadStart = false;
+      v._gotLoadedMetaData = false;
+      v._finished = false;
+      v.preload = "metadata";
+      v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
+      v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
+      v.addEventListener("loadeddata", this.loadeddata, false);
+      v.src = test.name;
+      document.body.appendChild(v); // Causes implicit load, which will be halted after
+                                     // metadata due to preload:metadata.
+    },
+  },
+  {
+    // 3. Add preload:auto to document. Should receive canplaythrough eventually.
+    canplaythrough:
+    function(e) {
+      var v = e.target;
+      is(v._gotLoadStart, true, "(3) Must get loadstart.");
+      is(v._gotLoadedMetaData, true, "(3) Must get loadedmetadata.");
+      v._finished = true;
+      maybeFinish(3);
+    },
+    
+    setup:
+    function(v) {
+      v._gotLoadStart = false;
+      v._gotLoadedMetaData = false;
+      v._finished = false;
+      v.preload = "auto";
+      v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
+      v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
+      v.addEventListener("canplaythrough", this.canplaythrough, false);
+      v.src = test.name;
+      document.body.appendChild(v); // Causes implicit load.
+    },
+  },
+  {
+    // 4. Add preload:none video to document. Call play(), should load then play through.
+    suspend:
+    function(e) {
+      var v = e.target;
+      if (v._gotSuspend) 
+        return; // We can receive multiple suspend events, like the one after download completes.
+      v._gotSuspend = true;
+      is(v._gotLoadStart, true, "(4) Must get loadstart.");
+      is(v._gotLoadedMetaData, false, "(4) Must not get loadedmetadata.");
+      is(v.readyState, v.HAVE_NOTHING, "(4) ReadyState must be HAVE_NOTHING");
+      is(v.networkState, v.NETWORK_IDLE, "(4) NetworkState must be NETWORK_IDLE");
+      v.play(); // Should load and play through.
+    },
+    
+    ended:
+    function(e) {
+      ok(true, "(4) Got playback ended");
+      e.target._finished = true;
+      maybeFinish(4);
+    },
+      
+    setup:
+    function(v) {
+      v._gotLoadStart = false;
+      v._gotLoadedMetaData = false;
+      v._gotSuspend = false;
+      v._finished = false;
+      v.preload = "none";
+      v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
+      v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
+      v.addEventListener("suspend", this.suspend, false);
+      v.addEventListener("ended", this.ended, false);
+      v.src = test.name;
+      document.body.appendChild(v);
+    },
+  },
+  {
+    // 5. preload:none video without resource, add to document, will implicitly start a
+    // preload:none load. Add a src, it shouldn't load.
+    suspend:
+    function(e) {
+      var v = e.target;
+      is(v._gotLoadStart, true, "(5) Must get loadstart.");
+      is(v._gotLoadedMetaData, false, "(5) Must not get loadedmetadata.");
+      is(v.readyState, v.HAVE_NOTHING, "(5) ReadyState must be HAVE_NOTHING");
+      is(v.networkState, v.NETWORK_IDLE, "(5) NetworkState must be NETWORK_IDLE");
+      v._finished = true;
+      maybeFinish(5);
+    },
+      
+    setup:
+    function(v) {
+      v._gotLoadStart = false;
+      v._gotLoadedMetaData = false;
+      v._finished = false;
+      v.preload = "none";
+      v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
+      v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
+      v.addEventListener("suspend", this.suspend, false);
+      document.body.appendChild(v); // Causes implicit load, which will be halted due to no resource.
+      v.src = test.name; // Load should start, and halt at preload:none.
+    },
+  },
+  {
+    // 6. preload:none video without resource, add to document, will implicitly start a
+    // preload:none load. Add a source, it shouldn't load.
+    suspend:
+    function(e) {
+      var v = e.target;
+      is(v._gotLoadStart, true, "(6) Must get loadstart.");
+      is(v._gotLoadedMetaData, false, "(6) Must not get loadedmetadata.");
+      is(v.readyState, v.HAVE_NOTHING, "(6) ReadyState must be HAVE_NOTHING");
+      is(v.networkState, v.NETWORK_IDLE, "(6) NetworkState must be NETWORK_IDLE");
+      v._finished = true;
+      maybeFinish(6);
+    },
+      
+    setup:
+    function(v) {
+      v._gotLoadStart = false;
+      v._gotLoadedMetaData = false;
+      v._finished = false;
+      v.preload = "none";
+      v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
+      v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
+      v.addEventListener("suspend", this.suspend, false);
+      document.body.appendChild(v); // Causes implicit load, which will be halted due to no resource.
+      var s = document.createElement("source");
+      s.src = test.name;
+      s.type = test.type;
+      v.appendChild(s); // Load should start, and halt at preload:none.
+    },
+  },
+  {
+    // 7. create a preload:none document with multiple sources, the first of which is invalid.
+    // Add to document, then play. It should load and play through the second source.
+    suspend:
+    function(e) {
+      var v = e.target;
+      if (v._gotSuspend) 
+        return; // We can receive multiple suspend events, like the one after download completes.
+      v._gotSuspend = true;
+      is(v._gotLoadStart, true, "(7) Must get loadstart.");
+      is(v._gotLoadedMetaData, false, "(7) Must not get loadedmetadata.");
+      is(v.readyState, v.HAVE_NOTHING, "(7) ReadyState must be HAVE_NOTHING");
+      is(v.networkState, v.NETWORK_IDLE, "(7) NetworkState must be NETWORK_IDLE");
+      v.play(); // Should load and play through.
+    },
+
+    ended:
+    function(e) {
+      ok(true, "(7) Got playback ended");
+      e.target._finished = true;
+      maybeFinish(7);
+    },
+      
+    setup:
+    function(v) {
+      v._gotLoadStart = false;
+      v._gotLoadedMetaData = false;
+      v._finished = false;
+      v.preload = "none";
+      v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
+      v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
+      v.addEventListener("suspend", this.suspend, false);
+      v.addEventListener("ended", this.ended, false);
+      var s1 = document.createElement("source");
+      s1.src = "not-a-real-file.404"
+      s1.type = test.type;
+      v.appendChild(s1);
+      var s2 = document.createElement("source");
+      s2.src = test.name;
+      s2.type = test.type;
+      v.appendChild(s2);
+      document.body.appendChild(v); // Causes implicit load, which will be halt at preload:none on the second resource.
+    },
+  },
+  {
+    // 8. Change preload value from none to metadata should cause metadata to be loaded.
+    loadeddata:
+    function(e) {
+      var v = e.target;
+      is(v._gotLoadedMetaData, true, "(8) Must get loadedmetadata.");
+      ok(v.readyState >= v.HAVE_CURRENT_DATA, "(8) ReadyState must be >= HAVE_CURRENT_DATA on suspend.");
+      is(v.networkState, v.NETWORK_IDLE, "(8) NetworkState must be NETWORK_IDLE when load is halted");
+      v._finished = true;
+      maybeFinish(8);
+    },
+    
+    setup:
+    function(v) {
+      v._gotLoadedMetaData = false;
+      v._finished = false;
+      v.preload = "none";
+      v.addEventListener("loadstart", function(e){v.preload = "metadata";}, false);
+      v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
+      v.addEventListener("loadeddata", this.loadeddata, false);
+      v.src = test.name;
+      document.body.appendChild(v); // Causes implicit load.
+    },
+  },
+  /*{
+    // 9. Change preload value from metadata to auto should cause entire media to be loaded.
+    // For some reason we don't always receive the canplaythrough event, particuarly on this test.
+    // We've disabled this test until bug 568402 is fixed.
+    canplaythrough:
+    function(e) {
+      var v = e.target;
+      if (v._finished)
+        return;
+      is(v._gotLoadStart, true, "(9) Must get loadstart.");
+      is(v._gotLoadedMetaData, true, "(9) Must get loadedmetadata.");
+      v._finished = true;
+      maybeFinish(9);
+    },
+    
+    setup:
+    function(v) {
+      v._gotLoadStart = false;
+      v._gotLoadedMetaData = false;
+      v._finished = false;
+      v.preload = "metadata";
+      v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
+      v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
+      v.addEventListener("loadeddata", function(){v.preload = "auto"}, false);
+      v.addEventListener("canplaythrough", this.canplaythrough, false);
+      v.src = test.name;
+      document.body.appendChild(v); // Causes implicit load.
+    },
+  },*/
+  {
+    // 10. Change preload value from none to auto should cause entire media to be loaded.
+    canplaythrough:
+    function(e) {
+      var v = e.target;
+      is(v._gotLoadedMetaData, true, "(10) Must get loadedmetadata.");
+      v._finished = true;
+      maybeFinish(10);
+    },
+    
+    setup:
+    function(v) {
+      v._gotLoadedMetaData = false;
+      v._finished = false;
+      v.preload = "none";
+      v.addEventListener("loadstart", function(e){v.preload = "auto";}, false);
+      v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
+      v.addEventListener("canplaythrough", this.canplaythrough, false);
+      v.src = test.name;
+      document.body.appendChild(v); // Causes implicit load.
+    },
+  },
+  {
+    // 11. Change preload value from none to metadata should cause metadata to load.
+    loadeddata:
+    function(e) {
+      var v = e.target;
+      is(v._gotLoadedMetaData, true, "(11) Must get loadedmetadata.");
+      ok(v.readyState >= v.HAVE_CURRENT_DATA, "(11) ReadyState must be >= HAVE_CURRENT_DATA.");
+      is(v.networkState, v.NETWORK_IDLE, "(11) NetworkState must be NETWORK_IDLE.");
+      v._finished = true;
+      maybeFinish(11);
+    },
+
+    setup:
+    function(v) {
+      v._gotLoadedMetaData = false;
+      v._finished = false;
+      v.preload = "none";
+      v.addEventListener("loadstart", function(e){v.preload = "metadata";}, false);
+      v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
+      v.addEventListener("loadeddata", this.loadeddata, false);
+      v.src = test.name;
+      document.body.appendChild(v); // Causes implicit load.
+    },
+  },
+  {
+    // 12. Change preload value from auto to metadata after load started,
+    // should still do full load, should not halt after metadata only.
+    canplaythrough:
+    function(e) {
+      var v = e.target;
+      is(v._gotLoadedMetaData, true, "(12) Must get loadedmetadata.");
+      is(v._gotLoadStart, true, "(12) Must get loadstart.");
+      v._finished = true;
+      maybeFinish(12);
+    },
+
+    setup:
+    function(v) {
+      v._gotLoadStart = false;
+      v._gotLoadedMetaData = false;
+      v._finished = false;
+      v.preload = "auto";
+      v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
+      v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
+      v.addEventListener("canplaythrough", this.canplaythrough, false);
+      v.src = test.name;
+      document.body.appendChild(v); // Causes implicit load.
+      v.preload = "metadata";
+    },
+  },
+  
+  {
+    // 13. Change preload value from metadata to none after load started,
+    // should still load up to metadata, should not halt immediately.
+    loadeddata:
+    function(e) {
+      var v = e.target;
+      is(v._gotLoadStart, true, "(13) Must get loadstart.");
+      is(v._gotLoadedMetaData, true, "(13) Must get loadedmetadata.");
+      ok(v.readyState >= v.HAVE_CURRENT_DATA, "(13) ReadyState must be >= HAVE_CURRENT_DATA.");
+      is(v.networkState, v.NETWORK_IDLE, "(13) NetworkState must be NETWORK_IDLE.");
+      v._finished = true;
+      maybeFinish(13);
+    },
+
+    setup:
+    function(v) {
+      v._gotLoadStart = false;
+      v._gotLoadedMetaData = false;
+      v._finished = false;
+      v.preload = "metadata";
+      v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
+      v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
+      v.addEventListener("loadeddata", this.loadeddata, false);
+      v.src = test.name;
+      document.body.appendChild(v); // Causes implicit load.
+      v.preload = "none";
+    },
+  },
+  {
+    // 14. Add preload:metadata video with src to document. Play(), should play through.
+    loadeddata:
+    function(e) {
+      var v = e.target;
+      is(v._gotLoadStart, true, "(14) Must get loadstart.");
+      is(v._gotLoadedMetaData, true, "(14) Must get loadedmetadata.");
+      ok(v.readyState >= v.HAVE_CURRENT_DATA, "(14) ReadyState must be >= HAVE_CURRENT_DATA");
+      is(v.networkState, v.NETWORK_IDLE, "(14) NetworkState must be NETWORK_IDLE");
+      v.play();
+    },
+    
+    ended:
+    function(e) {
+      ok(true, "(14) Got playback ended");
+      e.target._finished = true;
+      maybeFinish(14);
+    },
+
+    setup:
+    function(v) {
+      v._gotLoadStart = false;
+      v._gotLoadedMetaData = false;
+      v._finished = false;
+      v.preload = "metadata";
+      v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
+      v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
+      v.addEventListener("ended", this.ended, false);
+      v.addEventListener("loadeddata", this.loadeddata, false);
+      v.src = test.name;
+      document.body.appendChild(v); // Causes implicit load, which will be halted after
+                                     // metadata due to preload:metadata.
+    },
+  },
+  {
+    // 15. Autoplay should override preload:none.
+    ended:
+    function(e) {
+      ok(true, "(15) Got playback ended.");
+      e.target._finished = true;
+      maybeFinish(15);
+    },
+    
+    setup:
+    function(v) {
+      v._gotLoadStart = false;
+      v._gotLoadedMetaData = false;
+      v._finished = false;
+      v.preload = "none";
+      v.autoplay = true;
+      v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
+      v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
+      v.addEventListener("ended", this.ended, false);
+      v.src = test.name;
+      document.body.appendChild(v); // Causes implicit load.
+    },
+  },
+  {
+    // 16. Autoplay should override preload:metadata.
+    ended:
+    function(e) {
+      ok(true, "(16) Got playback ended.");
+      e.target._finished = true;
+      maybeFinish(16);
+    },
+    
+    setup:
+    function(v) {
+      v._finished = false;
+      v.preload = "metadata";
+      v.autoplay = true;
+      v.addEventListener("ended", this.ended, false);
+      v.src = test.name;
+      document.body.appendChild(v); // Causes implicit load.
+    },
+  },
+  {
+    // 17. On a preload:none video, adding autoplay should disable preload none, i.e. don't break autoplay!
+    ended:
+    function(e) {
+      ok(true, "(17) Got playback ended.");
+      e.target._finished = true;
+      maybeFinish(17);
+    },
+    
+    setup:
+    function(v) {
+      v.addEventListener("ended", this.ended, false);
+      v._finished = false;
+      v.preload = "none";
+      document.body.appendChild(v); // Causes implicit load, which will be halted due to preload:none.
+      v.autoplay = true;
+      v.src = test.name;
+    },    
+  },
+];
+
+if (test) {
+  for (var i=0; i<tests.length; i++) {
+    var t = tests[i];
+    var v = document.createElement("video");
+    videos.push(v);
+    t.setup(v);
+  }
+}
+
+if (test && videos.length == 0) {
+  todo(false, "No types or tests supported");
+} else {
+  SimpleTest.waitForExplicitFinish();
+}
+
+
+</script>
+</pre>
+</body>
+</html>
rename from content/media/test/test_autobuffer.html
rename to content/media/test/test_preload_attribute.html
--- a/content/media/test/test_autobuffer.html
+++ b/content/media/test/test_preload_attribute.html
@@ -13,33 +13,35 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=479863">Mozilla Bug 479863</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 
 <video id='v1' onerror="event.stopPropagation();"></video><audio id='a1' onerror="ev
 ent.stopPropagation();"></audio>
-<video id='v2' onerror="event.stopPropagation();" autobuffer></video><audio id='a2' on
-error="event.stopPropagation();" autobuffer></audio>
+<video id='v2' onerror="event.stopPropagation();" preload="auto"></video><audio id='a2' on
+error="event.stopPropagation();" preload="auto"></audio>
 
 <pre id="test">
 <script type="application/javascript">
 var v1 = document.getElementById('v1');
 var a1 = document.getElementById('a1');
 var v2 = document.getElementById('v2');
 var a2 = document.getElementById('a2');
-ok(!v1.autobuffer, "v1.autobuffer should be false by default");
-ok(!a1.autobuffer, "v1.autobuffer should be false by default");
-ok(v2.autobuffer, "v2.autobuffer should be true");
-ok(a2.autobuffer, "v2.autobuffer should be true");
+is(v1.getAttribute("preload"), undefined, "video preload via getAttribute should be undefined by default");
+is(a1.getAttribute("preload"), undefined, "video preload via getAttribute should be undefined by default");
+is(v1.preload, "", "v1.preload should be undefined by default");
+is(a1.preload, "", "a1.preload should be undefined by default");
+is(v2.preload, "auto", "v2.preload should be auto");
+is(a2.preload, "auto", "a2.preload should be auto");
 
-v1.autobuffer = true;
-a1.autobuffer = true;
-ok(v1.autobuffer, "video.autobuffer not true");
-ok(a1.autobuffer, "audio.autobuffer not true");
-is(v1.getAttribute("autobuffer"), "", "video autobuffer attribute not set");
-is(a1.getAttribute("autobuffer"), "", "video autobuffer attribute not set");
+v1.preload = "auto";
+a1.preload = "auto";
+is(v1.preload, "auto", "video.preload should be auto");
+is(a1.preload, "auto", "audio.preload should be auto");
+is(v1.getAttribute("preload"), "auto", "video preload attribute should be auto");
+is(a1.getAttribute("preload"), "auto", "video preload attribute should be auto");
 
 </script>
 </pre>
 </body>
 </html>
rename from content/media/test/test_autobuffer2.html
rename to content/media/test/test_preload_suspend.html
--- a/content/media/test/test_autobuffer2.html
+++ b/content/media/test/test_preload_suspend.html
@@ -13,24 +13,26 @@ https://bugzilla.mozilla.org/show_bug.cg
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=479863">Mozilla Bug 479863</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 
 <video id='v1' onerror="event.stopPropagation()"></video>
-<video id='v2' onerror="event.stopPropagation()" autobuffer></video>
+<video id='v2' onerror="event.stopPropagation()" preload="auto"></video>
 <video id='v3' onerror="event.stopPropagation()" autoplay></video>
 <video id='v4' onerror="event.stopPropagation()"></video>
 <video id='v5' onerror="event.stopPropagation()"></video>
 <video id='v6' onerror="event.stopPropagation()"></video>
 
 <pre id="test">
 <script type="application/javascript">
+function is() {}
+
 var suspendCount = {};
 var expectedSuspendCount = {v1:2, v2:1, v3:1, v4:2, v5:2, v6:2};
 var totalSuspendCount = 0;
 for (var i = 0; i < expectedSuspendCount.length; ++i) {
   totalSuspendCount += expectedSuspendCount[i];
 }
 
 function suspended(event) {
@@ -53,17 +55,17 @@ function suspended(event) {
     }
     SimpleTest.finish();
   }
 
   if (suspendCount[event.target.id] > 1)
     return;
 
   if (event.target.id == "v1") {
-    event.target.autobuffer = true;
+    event.target.preload = "auto";
   } else if (event.target.id == "v4") {
     event.target.play();
   } else if (event.target.id == "v5") {
     event.target.currentTime = 0.1;
   } else if (event.target.id == "v6") {
     event.target.autoplay = true;
   }
 }
--- a/content/media/test/test_resume.html
+++ b/content/media/test/test_resume.html
@@ -2,17 +2,17 @@
 <html>
 <head>
   <title>Media test: Test resume of server-dropped connections</title>
   <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
-<audio autobuffer id="a"></audio>
+<audio preload="auto" id="a"></audio>
 <iframe id="f"></iframe>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 var key = Math.round(Math.random()*1000000000);
 var a = document.getElementById("a");
 var f = document.getElementById("f");
 
 function didEnd() {
--- a/content/media/webm/nsWebMReader.cpp
+++ b/content/media/webm/nsWebMReader.cpp
@@ -670,17 +670,17 @@ PRBool nsWebMReader::DecodeVideoFrame(PR
       mVideoQueue.Push(v);
     }
   }
  
   nestegg_free_packet(packet);
   return PR_TRUE;
 }
 
-nsresult nsWebMReader::Seek(PRInt64 aTarget, PRInt64 aStartTime, PRInt64 aEndTime)
+nsresult nsWebMReader::Seek(PRInt64 aTarget, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime)
 {
   MonitorAutoEnter mon(mMonitor);
   NS_ASSERTION(mDecoder->OnStateMachineThread(),
                "Should be on state machine thread.");
   LOG(PR_LOG_DEBUG, ("%p About to seek to %lldms", mDecoder, aTarget));
   if (NS_FAILED(ResetDecode())) {
     return NS_ERROR_FAILURE;
   }
--- a/content/media/webm/nsWebMReader.h
+++ b/content/media/webm/nsWebMReader.h
@@ -119,17 +119,17 @@ public:
 
   virtual PRBool HasVideo()
   {
     mozilla::MonitorAutoEnter mon(mMonitor);
     return mHasVideo;
   }
 
   virtual nsresult ReadMetadata();
-  virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime);
+  virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime);
   virtual nsresult GetBuffered(nsHTMLTimeRanges* aBuffered, PRInt64 aStartTime);
 
 private:
   // Value passed to NextPacket to determine if we are reading a video or an
   // audio packet.
   enum TrackType {
     VIDEO = 0,
     AUDIO = 1
--- a/dom/interfaces/html/nsIDOMHTMLMediaElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLMediaElement.idl
@@ -52,31 +52,32 @@
 
 // undef the GetCurrentTime macro defined in WinBase.h from the MS Platform SDK
 %{C++
 #ifdef GetCurrentTime
 #undef GetCurrentTime
 #endif
 %}
 
-[scriptable, uuid(b6c9f51d-237c-44d1-842d-996f4d62c843)]
+[scriptable, uuid(925c46e0-3795-11df-9879-0800200c9a66)]
 interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement
 {
   // error state
   readonly attribute nsIDOMHTMLMediaError error;
 
   // network state
            attribute DOMString src;
   readonly attribute DOMString currentSrc;
   const unsigned short NETWORK_EMPTY = 0;
   const unsigned short NETWORK_IDLE = 1;
   const unsigned short NETWORK_LOADING = 2;
   const unsigned short NETWORK_LOADED = 3;
   const unsigned short NETWORK_NO_SOURCE = 4;
   readonly attribute unsigned short networkState;
+           attribute DomString preload;  
   readonly attribute nsIDOMHTMLTimeRanges buffered;
   void load();
   DOMString canPlayType(in DOMString type);
 
   // ready state
   const unsigned short HAVE_NOTHING = 0;
   const unsigned short HAVE_METADATA = 1;
   const unsigned short HAVE_CURRENT_DATA = 2;
@@ -87,17 +88,16 @@ interface nsIDOMHTMLMediaElement : nsIDO
 
   // playback state
            attribute float currentTime;
   readonly attribute float duration;
   readonly attribute boolean paused;
   readonly attribute boolean ended;
   readonly attribute boolean mozAutoplayEnabled;
            attribute boolean autoplay;
-           attribute boolean autobuffer;
   void play();
   void pause();
 
   // controls
            attribute boolean controls;
            attribute float volume;
            attribute boolean muted;
 
--- a/dom/src/threads/test/json_worker.js
+++ b/dom/src/threads/test/json_worker.js
@@ -280,16 +280,21 @@ var messages = [
     exception: true
   },
   {
     type: "object",
     value: self,
     exception: true
   },
   {
+    type: "object",
+    value: { p: ArrayBuffer.prototype },
+    exception: true
+  },
+  {
     type: "string",
     shouldEqual: true,
     value: "testFinished"
   }
 ];
 
 for (var index = 0; index < messages.length; index++) {
   var message = messages[index];
--- a/ipc/chromium/src/base/message_loop.cc
+++ b/ipc/chromium/src/base/message_loop.cc
@@ -310,17 +310,21 @@ void MessageLoop::PostTask_Helper(
 }
 
 void MessageLoop::SetNestableTasksAllowed(bool allowed) {
   if (nestable_tasks_allowed_ != allowed) {
     nestable_tasks_allowed_ = allowed;
     if (!nestable_tasks_allowed_)
       return;
     // Start the native pump if we are not already pumping.
+#ifndef CHROMIUM_MOZILLA_BUILD
     pump_->ScheduleWork();
+#else
+    pump_->ScheduleWorkForNestedLoop();
+#endif
   }
 }
 
 void MessageLoop::ScheduleWork() {
   // Start the native pump if we are not already pumping.
   pump_->ScheduleWork();
 }
 
--- a/ipc/chromium/src/base/message_pump.h
+++ b/ipc/chromium/src/base/message_pump.h
@@ -106,16 +106,26 @@ class MessagePump : public RefCountedThr
   virtual void Quit() = 0;
 
   // Schedule a DoWork callback to happen reasonably soon.  Does nothing if a
   // DoWork callback is already scheduled.  This method may be called from any
   // thread.  Once this call is made, DoWork should not be "starved" at least
   // until it returns a value of false.
   virtual void ScheduleWork() = 0;
 
+#if defined(CHROMIUM_MOZILLA_BUILD)
+  // This method may only called from the thread that called Run.
+  //
+  // Ensure that DoWork will be called if a nested loop is entered.
+  // If a MessagePump can already guarantee that DoWork will be called
+  // "reasonably soon", this method can be a no-op to avoid expensive
+  // atomic tests and/or syscalls required for ScheduleWork().
+  virtual void ScheduleWorkForNestedLoop() { ScheduleWork(); };
+#endif  // defined(CHROMIUM_MOZILLA_BUILD)
+
   // Schedule a DoDelayedWork callback to happen at the specified time,
   // cancelling any pending DoDelayedWork callback.  This method may only be
   // used on the thread that called Run.
   virtual void ScheduleDelayedWork(const Time& delayed_work_time) = 0;
 };
 
 }  // namespace base
 
--- a/ipc/glue/MessagePump.cpp
+++ b/ipc/glue/MessagePump.cpp
@@ -47,41 +47,33 @@
 #include "base/logging.h"
 #include "base/scoped_nsautorelease_pool.h"
 
 using mozilla::ipc::DoWorkRunnable;
 using mozilla::ipc::MessagePump;
 using mozilla::ipc::MessagePumpForChildProcess;
 using base::Time;
 
-namespace {
-
-bool gRunningSetNestableTasksAllowed = false;
-
-} /* anonymous namespace */
-
 NS_IMPL_THREADSAFE_ISUPPORTS2(DoWorkRunnable, nsIRunnable, nsITimerCallback)
 
 NS_IMETHODIMP
 DoWorkRunnable::Run()
 {
   MessageLoop* loop = MessageLoop::current();
   NS_ASSERTION(loop, "Shouldn't be null!");
   if (loop) {
     bool nestableTasksAllowed = loop->NestableTasksAllowed();
 
-    gRunningSetNestableTasksAllowed = true;
+    // MessageLoop::RunTask() disallows nesting, but our Frankenvent
+    // will always dispatch DoWork() below from what looks to
+    // MessageLoop like a nested context.  So we unconditionally allow
+    // nesting here.
     loop->SetNestableTasksAllowed(true);
-    gRunningSetNestableTasksAllowed = false;
-
     loop->DoWork();
-
-    gRunningSetNestableTasksAllowed = true;
     loop->SetNestableTasksAllowed(nestableTasksAllowed);
-    gRunningSetNestableTasksAllowed = false;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 DoWorkRunnable::Notify(nsITimer* aTimer)
 {
   MessageLoop* loop = MessageLoop::current();
@@ -145,33 +137,38 @@ MessagePump::Run(MessagePump::Delegate* 
   mDelayedWorkTimer->Cancel();
 
   keep_running_ = true;
 }
 
 void
 MessagePump::ScheduleWork()
 {
-  if (gRunningSetNestableTasksAllowed) {
-    return;
-  }
-
   // Make sure the event loop wakes up.
   if (mThread) {
     mThread->Dispatch(mDoWorkEvent, NS_DISPATCH_NORMAL);
   }
   else {
     // Some things (like xpcshell) don't use the app shell and so Run hasn't
     // been called. We still need to wake up the main thread.
     NS_DispatchToMainThread(mDoWorkEvent, NS_DISPATCH_NORMAL);
   }
   event_.Signal();
 }
 
 void
+MessagePump::ScheduleWorkForNestedLoop()
+{
+  // This method is called when our MessageLoop has just allowed
+  // nested tasks.  In our setup, whenever that happens we know that
+  // DoWork() will be called "soon", so there's no need to pay the
+  // cost of what will be a no-op nsThread::Dispatch(mDoWorkEvent).
+}
+
+void
 MessagePump::ScheduleDelayedWork(const base::Time& aDelayedTime)
 {
   if (!mDelayedWorkTimer) {
     mDelayedWorkTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
     if (!mDelayedWorkTimer) {
         // Called before XPCOM has started up? We can't do this correctly.
         NS_WARNING("Delayed task might not run!");
         delayed_work_time_ = aDelayedTime;
--- a/ipc/glue/MessagePump.h
+++ b/ipc/glue/MessagePump.h
@@ -71,16 +71,17 @@ private:
 class MessagePump : public base::MessagePumpDefault
 {
 
 public:
   MessagePump();
 
   virtual void Run(base::MessagePump::Delegate* aDelegate);
   virtual void ScheduleWork();
+  virtual void ScheduleWorkForNestedLoop();
   virtual void ScheduleDelayedWork(const base::Time& delayed_work_time);
 
   void DoDelayedWork(base::MessagePump::Delegate* aDelegate);
 
 private:
   nsRefPtr<DoWorkRunnable> mDoWorkEvent;
   nsCOMPtr<nsITimer> mDelayedWorkTimer;
 
--- a/js/src/xpconnect/src/nsCSSPropertiesQS.h
+++ b/js/src/xpconnect/src/nsCSSPropertiesQS.h
@@ -34,30 +34,30 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsCSSPropertiesQS_h__
 #define nsCSSPropertiesQS_h__
 
 #include "nsICSSDeclaration.h"
 
-#define CSS_PROP(name_, id_, method_, flags_, datastruct_, member_, type_,     \
-                 kwtable_, stylestruct_, stylestructoffset_, animtype_)        \
+#define CSS_PROP(name_, id_, method_, flags_, datastruct_, member_,     \
+                 kwtable_, stylestruct_, stylestructoffset_, animtype_) \
 static const nsCSSProperty QS_CSS_PROP_##method_ = eCSSProperty_##id_;
 
 #define CSS_PROP_LIST_EXCLUDE_INTERNAL
 #define CSS_PROP_SHORTHAND(name_, id_, method_, flags_) \
-  CSS_PROP(name_, id_, method_, flags_, X, X, X, X, X, X, X)
+  CSS_PROP(name_, id_, method_, flags_, X, X, X, X, X, X)
 #include "nsCSSPropList.h"
 
 // Aliases
-CSS_PROP(X, opacity, MozOpacity, 0, X, X, X, X, X, X, X)
-CSS_PROP(X, outline, MozOutline, 0, X, X, X, X, X, X, X)
-CSS_PROP(X, outline_color, MozOutlineColor, 0, X, X, X, X, X, X, X)
-CSS_PROP(X, outline_style, MozOutlineStyle, 0, X, X, X, X, X, X, X)
-CSS_PROP(X, outline_width, MozOutlineWidth, 0, X, X, X, X, X, X, X)
-CSS_PROP(X, outline_offset, MozOutlineOffset, 0, X, X, X, X, X, X, X)
+CSS_PROP(X, opacity, MozOpacity, X, X, X, X, X, X, X)
+CSS_PROP(X, outline, MozOutline, X, X, X, X, X, X, X)
+CSS_PROP(X, outline_color, MozOutlineColor, X, X, X, X, X, X, X)
+CSS_PROP(X, outline_style, MozOutlineStyle, X, X, X, X, X, X, X)
+CSS_PROP(X, outline_width, MozOutlineWidth, X, X, X, X, X, X, X)
+CSS_PROP(X, outline_offset, MozOutlineOffset, X, X, X, X, X, X, X)
 
 #undef CSS_PROP_SHORTHAND
 #undef CSS_PROP_LIST_EXCLUDE_INTERNAL
 #undef CSS_PROP
 
 #endif /* nsCSSPropertiesQS_h__ */
--- a/layout/reftests/ogg-video/poster-10.html
+++ b/layout/reftests/ogg-video/poster-10.html
@@ -3,16 +3,16 @@
 <!-- Test: Create video, add poster, load. Should display poster. -->
 <script>
 function runTest() {
   var v = document.createElement('video');
   v.addEventListener('loadeddata', function(){setTimeout(function(){document.documentElement.className = '';}, 0);}, false);
   v.id = 'v';
   v.src = "black140x100.ogv";
   v.poster = "blue250x200.png";
-  v.autobuffer = true;
+  v.preload = "auto";
   document.body.appendChild(v);
 }
 
 </script>
 <body style="background:white;" onload="runTest();">
 </body>
 </html>
--- a/layout/reftests/ogg-video/poster-11.html
+++ b/layout/reftests/ogg-video/poster-11.html
@@ -14,16 +14,16 @@ function runTest() {
     v.poster = "blue250x200.png";
     v.addEventListener('loadeddata', endTest, false);
     v.load();
   };
   
   v.addEventListener('loadeddata', addPoster, false);
   v.id = 'v';
   v.src = "black140x100.ogv";
-  v.autobuffer = true;
+  v.preload = "auto";
   document.body.appendChild(v);
 }
 
 </script>
 <body style="background:white;" onload="runTest();">
 </body>
 </html>
--- a/layout/reftests/ogg-video/poster-12.html
+++ b/layout/reftests/ogg-video/poster-12.html
@@ -25,16 +25,16 @@ function runTest() {
   v.addEventListener('loadeddata',
                      play,
                      false);
   v.addEventListener('playing',
                      addPoster,
                      false);
   v.id = 'v';
   v.src = "black140x100.ogv";
-  v.autobuffer = true;
+  v.preload = "auto";
   document.body.appendChild(v);
 }
 
 </script>
 <body style="background:white;" onload="runTest();">
 </body>
 </html>
--- a/layout/reftests/ogg-video/poster-14.html
+++ b/layout/reftests/ogg-video/poster-14.html
@@ -12,17 +12,17 @@ function runTest() {
       setTimeout(function() {document.documentElement.className = '';}, 150);
     };
 
   v.addEventListener('loadeddata',
                      loadeddata,
                      false);
   v.id = 'v';
   v.src = "black140x100.ogv";
-  v.autobuffer = true;
+  v.preload = "auto";
   document.body.appendChild(v);
   
 }
 
 </script>
 <body style="background:white;" onload="runTest();">
 </body>
 </html>
--- a/layout/reftests/ogg-video/poster-15.html
+++ b/layout/reftests/ogg-video/poster-15.html
@@ -1,13 +1,13 @@
 <!DOCTYPE HTML>
 <html>
 <!-- Test that poster is correctly laid out inside borders. Also test that 
      poster frames smaller than video don't have the video frame drawn behind
      them etc. -->
 <body style="background:white;">
 <video src="black140x100.ogv"
        poster="green70x30.png"
-       autobuffer
+       preload="auto"
        style="border: solid blue 2px;">
 </video>
 </body>
 </html>
--- a/layout/reftests/ogg-video/poster-3.html
+++ b/layout/reftests/ogg-video/poster-3.html
@@ -1,11 +1,11 @@
 <!DOCTYPE HTML>
 <html class="reftest-wait">
 <body style="background:white;">
 <!-- Test if poster hides after playing with autoplay. -->
 <video src="black140x100.ogv"
        poster="blue250x200.png"
-       autobuffer
+       preload="auto"
        autoplay
        onplaying="setTimeout(function(){document.documentElement.className = '';},0);"></video>
 </body>
 </html>
--- a/layout/reftests/ogg-video/poster-4.html
+++ b/layout/reftests/ogg-video/poster-4.html
@@ -1,11 +1,11 @@
 <!DOCTYPE HTML>
 <html class="reftest-wait">
 <body style="background:white;">
 <!-- Test if we show video frame after removing valid poster. -->
 <video src="black140x100.ogv"
-       autobuffer
+       preload="auto"
        id="v"
        onload="document.getElementById('v').poster = ''; setTimeout(function(){document.documentElement.className = '';}, 0);"
        poster="blue250x200.png"></video>
 </body>
 </html>
--- a/layout/reftests/ogg-video/poster-5.html
+++ b/layout/reftests/ogg-video/poster-5.html
@@ -1,13 +1,13 @@
 <!DOCTYPE HTML>
 <html class="reftest-wait">
 <body style="background:white;">
 <!-- Test to ensure that changing the poster after video has painted its first
      frame doesn't render the poster. The video frame should not change to the
      poster, since it's already painted its first video frame. -->
 <video src="black140x100.ogv"
-       autobuffer
+       preload="auto"
        id="v"
        autoplay
        onended="document.getElementById('v').poster = 'blue250x200.png'; setTimeout(function(){document.documentElement.className = '';},0);"></video>
 </body>
 </html>
--- a/layout/reftests/ogg-video/poster-6.html
+++ b/layout/reftests/ogg-video/poster-6.html
@@ -1,12 +1,12 @@
 <!DOCTYPE HTML>
 <html class="reftest-wait">
 <body style="background:white;">
 <!-- Test that poster frame should hide after completing a seek. -->
 <video src="black140x100.ogv"
-       autobuffer
+       preload="auto"
        id="v"
        onloadeddata="var v = document.getElementById('v'); v.currentTime = v.duration;"
        onseeked="setTimeout(function(){document.documentElement.className = '';}, 0);"
        poster="blue250x200.png"></video>
 </body>
 </html>
--- a/layout/reftests/ogg-video/poster-7.html
+++ b/layout/reftests/ogg-video/poster-7.html
@@ -1,11 +1,11 @@
 <!DOCTYPE HTML>
 <html class="reftest-wait">
 <body style="background:white;">
 <!-- Test that poster frame changes when you change the poster attribute. -->
 <video src="black140x100.ogv"
-       autobuffer
+       preload="auto"
        id="v"
        onload="document.getElementById('v').poster = 'red160x120.png'; setTimeout(function(){document.documentElement.className = '';}, 0);"
        poster="blue250x200.png"></video>
 </body>
 </html>
--- a/layout/reftests/ogg-video/poster-8.html
+++ b/layout/reftests/ogg-video/poster-8.html
@@ -1,12 +1,12 @@
 <!DOCTYPE HTML>
 <html class="reftest-wait">
 <body style="background:white;">
 <!-- Test if poster hides after playing with play() call. -->
 <video src="black140x100.ogv"
        poster="blue250x200.png"
        id="v"
-       autobuffer
+       preload="auto"
        onloadeddata="document.getElementById('v').play();"
        onplaying="setTimeout(function(){document.documentElement.className = '';}, 0);"></video>
 </body>
 </html>
--- a/layout/reftests/ogg-video/poster-ref-black140x100.html
+++ b/layout/reftests/ogg-video/poster-ref-black140x100.html
@@ -1,6 +1,6 @@
 <!DOCTYPE HTML>
 <html>
 <body style="background:white;">
-<video src="black140x100.ogv" autobuffer></video>
+<video src="black140x100.ogv" preload="auto"></video>
 </body>
 </html>
--- a/layout/style/Declaration.cpp
+++ b/layout/style/Declaration.cpp
@@ -39,30 +39,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /*
  * representation of a declaration block (or style attribute) in a CSS
  * stylesheet
  */
 
-#include "nscore.h"
-#include "prlog.h"
 #include "mozilla/css/Declaration.h"
-#include "nsString.h"
-#include "nsIAtom.h"
-#include "nsUnicharUtils.h"
-#include "nsReadableUtils.h"
-#include "nsCRT.h"
-#include "nsCSSProps.h"
-#include "nsFont.h"
-#include "nsReadableUtils.h"
-#include "nsStyleUtil.h"
-#include "nsStyleConsts.h"
-#include "nsCOMPtr.h"
+#include "nsPrintfCString.h"
 
 namespace mozilla {
 namespace css {
 
 // check that we can fit all the CSS properties into a PRUint8
 // for the mOrder array - if not, might need to use PRUint16!
 PR_STATIC_ASSERT(eCSSProperty_COUNT_no_shorthands - 1 <= PR_UINT8_MAX);
 
@@ -99,67 +87,47 @@ Declaration::ValueAppended(nsCSSProperty
   mOrder.AppendElement(aProperty);
 }
 
 void
 Declaration::RemoveProperty(nsCSSProperty aProperty)
 {
   nsCSSExpandedDataBlock data;
   ExpandTo(&data);
-  NS_ASSERTION(!mData && !mImportantData, "Expand didn't null things out");
+  NS_ABORT_IF_FALSE(!mData && !mImportantData, "Expand didn't null things out");
 
   if (nsCSSProps::IsShorthand(aProperty)) {
     CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProperty) {
       data.ClearLonghandProperty(*p);
       mOrder.RemoveElement(*p);
     }
   } else {
     data.ClearLonghandProperty(aProperty);
     mOrder.RemoveElement(aProperty);
   }
 
   CompressFrom(&data);
 }
 
-PRBool Declaration::AppendValueToString(nsCSSProperty aProperty,
-                                        nsAString& aResult) const
+PRBool
+Declaration::AppendValueToString(nsCSSProperty aProperty,
+                                 nsAString& aResult) const
 {
   NS_ABORT_IF_FALSE(0 <= aProperty &&
                     aProperty < eCSSProperty_COUNT_no_shorthands,
                     "property ID out of range");
 
   nsCSSCompressedDataBlock *data = GetValueIsImportant(aProperty)
                                       ? mImportantData : mData;
-  const void *storage = data->StorageFor(aProperty);
-  if (!storage) {
+  const nsCSSValue *val = data->ValueFor(aProperty);
+  if (!val) {
     return PR_FALSE;
   }
 
-  switch (nsCSSProps::kTypeTable[aProperty]) {
-    case eCSSType_Value:
-      static_cast<const nsCSSValue*>(storage)->
-        AppendToString(aProperty, aResult);
-      break;
-    case eCSSType_Rect:
-      static_cast<const nsCSSRect*>(storage)->
-        AppendToString(aProperty, aResult);
-      break;
-    case eCSSType_ValuePair:
-      static_cast<const nsCSSValuePair*>(storage)->
-        AppendToString(aProperty, aResult);
-      break;
-    case eCSSType_ValueList:
-      (*static_cast<nsCSSValueList*const*>(storage))->
-        AppendToString(aProperty, aResult);
-      break;
-    case eCSSType_ValuePairList:
-      (*static_cast<nsCSSValuePairList*const*>(storage))->
-        AppendToString(aProperty, aResult);
-      break;
-  }
+  val->AppendToString(aProperty, aResult);
   return PR_TRUE;
 }
 
 void
 Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
 {
   aValue.Truncate(0);
 
@@ -194,57 +162,30 @@ Declaration::GetValue(nsCSSProperty aPro
            initialCount = 0, inheritCount = 0;
   CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProperty) {
     if (*p == eCSSProperty__x_system_font ||
          nsCSSProps::PropHasFlags(*p, CSS_PROPERTY_DIRECTIONAL_SOURCE)) {
       // The system-font subproperty and the *-source properties don't count.
       continue;
     }
     ++totalCount;
-    const void *storage = mData->StorageFor(*p);
-    NS_ASSERTION(!storage || !mImportantData || !mImportantData->StorageFor(*p),
-                 "can't be in both blocks");
-    if (!storage && mImportantData) {
+    const nsCSSValue *val = mData->ValueFor(*p);
+    NS_ABORT_IF_FALSE(!val || !mImportantData || !mImportantData->ValueFor(*p),
+                      "can't be in both blocks");
+    if (!val && mImportantData) {
       ++importantCount;
-      storage = mImportantData->StorageFor(*p);
+      val = mImportantData->ValueFor(*p);
     }
-    if (!storage) {
+    if (!val) {
       // Case (1) above: some subproperties not specified.
       return;
     }
-    nsCSSUnit unit;
-    switch (nsCSSProps::kTypeTable[*p]) {
-      case eCSSType_Value: {
-        const nsCSSValue *val = static_cast<const nsCSSValue*>(storage);
-        unit = val->GetUnit();
-      } break;
-      case eCSSType_Rect: {
-        const nsCSSRect *rect = static_cast<const nsCSSRect*>(storage);
-        unit = rect->mTop.GetUnit();
-      } break;
-      case eCSSType_ValuePair: {
-        const nsCSSValuePair *pair = static_cast<const nsCSSValuePair*>(storage);
-        unit = pair->mXValue.GetUnit();
-      } break;
-      case eCSSType_ValueList: {
-        const nsCSSValueList* item =
-            *static_cast<nsCSSValueList*const*>(storage);
-        NS_ABORT_IF_FALSE(item, "null not allowed in compressed block");
-        unit = item->mValue.GetUnit();
-      } break;
-      case eCSSType_ValuePairList: {
-        const nsCSSValuePairList* item =
-            *static_cast<nsCSSValuePairList*const*>(storage);
-        NS_ABORT_IF_FALSE(item, "null not allowed in compressed block");
-        unit = item->mXValue.GetUnit();
-      } break;
-    }
-    if (unit == eCSSUnit_Inherit) {
+    if (val->GetUnit() == eCSSUnit_Inherit) {
       ++inheritCount;
-    } else if (unit == eCSSUnit_Initial) {
+    } else if (val->GetUnit() == eCSSUnit_Initial) {
       ++initialCount;
     }
   }
   if (importantCount != 0 && importantCount != totalCount) {
     // Case (3), no consistent importance.
     return;
   }
   if (initialCount == totalCount) {
@@ -266,111 +207,104 @@ Declaration::GetValue(nsCSSProperty aPro
   switch (aProperty) {
     case eCSSProperty_margin: 
     case eCSSProperty_padding: 
     case eCSSProperty_border_color: 
     case eCSSProperty_border_style: 
     case eCSSProperty_border_width: {
       const nsCSSProperty* subprops =
         nsCSSProps::SubpropertyEntryFor(aProperty);
-      NS_ASSERTION(nsCSSProps::kTypeTable[subprops[0]] == eCSSType_Value &&
-                   nsCSSProps::kTypeTable[subprops[1]] == eCSSType_Value &&
-                   nsCSSProps::kTypeTable[subprops[2]] == eCSSType_Value &&
-                   nsCSSProps::kTypeTable[subprops[3]] == eCSSType_Value,
-                   "type mismatch");
-      NS_ASSERTION(nsCSSProps::GetStringValue(subprops[0]).Find("-top") !=
-                     kNotFound, "first subprop must be top");
-      NS_ASSERTION(nsCSSProps::GetStringValue(subprops[1]).Find("-right") !=
-                     kNotFound, "second subprop must be right");
-      NS_ASSERTION(nsCSSProps::GetStringValue(subprops[2]).Find("-bottom") !=
-                     kNotFound, "third subprop must be bottom");
-      NS_ASSERTION(nsCSSProps::GetStringValue(subprops[3]).Find("-left") !=
-                     kNotFound, "fourth subprop must be left");
-      const nsCSSValue &topValue = *data->ValueStorageFor(subprops[0]);
-      const nsCSSValue &rightValue = *data->ValueStorageFor(subprops[1]);
-      const nsCSSValue &bottomValue = *data->ValueStorageFor(subprops[2]);
-      const nsCSSValue &leftValue = *data->ValueStorageFor(subprops[3]);
+      NS_ABORT_IF_FALSE(nsCSSProps::GetStringValue(subprops[0]).Find("-top") !=
+                        kNotFound, "first subprop must be top");
+      NS_ABORT_IF_FALSE(nsCSSProps::GetStringValue(subprops[1]).Find("-right") !=
+                        kNotFound, "second subprop must be right");
+      NS_ABORT_IF_FALSE(nsCSSProps::GetStringValue(subprops[2]).Find("-bottom") !=
+                        kNotFound, "third subprop must be bottom");
+      NS_ABORT_IF_FALSE(nsCSSProps::GetStringValue(subprops[3]).Find("-left") !=
+                        kNotFound, "fourth subprop must be left");
+      const nsCSSValue &topValue = *data->ValueFor(subprops[0]);
+      const nsCSSValue &rightValue = *data->ValueFor(subprops[1]);
+      const nsCSSValue &bottomValue = *data->ValueFor(subprops[2]);
+      const nsCSSValue &leftValue = *data->ValueFor(subprops[3]);
 
-      NS_ASSERTION(topValue.GetUnit() != eCSSUnit_Null, "null top");
+      NS_ABORT_IF_FALSE(topValue.GetUnit() != eCSSUnit_Null, "null top");
       topValue.AppendToString(subprops[0], aValue);
       if (topValue != rightValue || topValue != leftValue ||
           topValue != bottomValue) {
         aValue.Append(PRUnichar(' '));
-        NS_ASSERTION(rightValue.GetUnit() != eCSSUnit_Null, "null right");
+        NS_ABORT_IF_FALSE(rightValue.GetUnit() != eCSSUnit_Null, "null right");
         rightValue.AppendToString(subprops[1], aValue);
         if (topValue != bottomValue || rightValue != leftValue) {
           aValue.Append(PRUnichar(' '));
-          NS_ASSERTION(bottomValue.GetUnit() != eCSSUnit_Null, "null bottom");
+          NS_ABORT_IF_FALSE(bottomValue.GetUnit() != eCSSUnit_Null, "null bottom");
           bottomValue.AppendToString(subprops[2], aValue);
           if (rightValue != leftValue) {
             aValue.Append(PRUnichar(' '));
-            NS_ASSERTION(leftValue.GetUnit() != eCSSUnit_Null, "null left");
+            NS_ABORT_IF_FALSE(leftValue.GetUnit() != eCSSUnit_Null, "null left");
             leftValue.AppendToString(subprops[3], aValue);
           }
         }
       }
       break;
     }
-    case eCSSProperty__moz_border_radius: 
+    case eCSSProperty__moz_border_radius:
     case eCSSProperty__moz_outline_radius: {
       const nsCSSProperty* subprops =
         nsCSSProps::SubpropertyEntryFor(aProperty);
-      NS_ASSERTION(nsCSSProps::kTypeTable[subprops[0]] == eCSSType_ValuePair &&
-                   nsCSSProps::kTypeTable[subprops[1]] == eCSSType_ValuePair &&
-                   nsCSSProps::kTypeTable[subprops[2]] == eCSSType_ValuePair &&
-                   nsCSSProps::kTypeTable[subprops[3]] == eCSSType_ValuePair,
-                   "type mismatch");
-      const nsCSSValuePair* vals[4] = {
-        data->ValuePairStorageFor(subprops[0]),
-        data->ValuePairStorageFor(subprops[1]),
-        data->ValuePairStorageFor(subprops[2]),
-        data->ValuePairStorageFor(subprops[3])
+      const nsCSSValue* vals[4] = {
+        data->ValueFor(subprops[0]),
+        data->ValueFor(subprops[1]),
+        data->ValueFor(subprops[2]),
+        data->ValueFor(subprops[3])
       };
 
-      vals[0]->mXValue.AppendToString(subprops[0], aValue);
-      aValue.Append(PRUnichar(' '));
-      vals[1]->mXValue.AppendToString(subprops[1], aValue);
-      aValue.Append(PRUnichar(' '));
-      vals[2]->mXValue.AppendToString(subprops[2], aValue);
-      aValue.Append(PRUnichar(' '));
-      vals[3]->mXValue.AppendToString(subprops[3], aValue);
-
       // For compatibility, only write a slash and the y-values
       // if they're not identical to the x-values.
-      if (vals[0]->mXValue != vals[0]->mYValue ||
-          vals[1]->mXValue != vals[1]->mYValue ||
-          vals[2]->mXValue != vals[2]->mYValue ||
-          vals[3]->mXValue != vals[3]->mYValue) {
+      PRBool needY = PR_FALSE;
+      for (int i = 0; i < 4; i++) {
+        if (vals[i]->GetUnit() == eCSSUnit_Pair) {
+          needY = PR_TRUE;
+          vals[i]->GetPairValue().mXValue.AppendToString(subprops[i], aValue);
+        } else {
+          vals[i]->AppendToString(subprops[i], aValue);
+        }
+        if (i < 3)
+          aValue.Append(PRUnichar(' '));
+      }
+
+      if (needY) {
         aValue.AppendLiteral(" / ");
-        vals[0]->mYValue.AppendToString(subprops[0], aValue);
-        aValue.Append(PRUnichar(' '));
-        vals[1]->mYValue.AppendToString(subprops[1], aValue);
-        aValue.Append(PRUnichar(' '));
-        vals[2]->mYValue.AppendToString(subprops[2], aValue);
-        aValue.Append(PRUnichar(' '));
-        vals[3]->mYValue.AppendToString(subprops[3], aValue);
+        for (int i = 0; i < 4; i++) {
+          if (vals[i]->GetUnit() == eCSSUnit_Pair) {
+            vals[i]->GetPairValue().mYValue.AppendToString(subprops[i], aValue);
+          } else {
+            vals[i]->AppendToString(subprops[i], aValue);
+          }
+          if (i < 3)
+            aValue.Append(PRUnichar(' '));
+        }
       }
       break;
     }
     case eCSSProperty_border: {
       const nsCSSProperty* subproptables[3] = {
         nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_color),
         nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_style),
         nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_width)
       };
       PRBool match = PR_TRUE;
       for (const nsCSSProperty** subprops = subproptables,
                **subprops_end = subproptables + NS_ARRAY_LENGTH(subproptables);
            subprops < subprops_end; ++subprops) {
         // Check only the first four subprops in each table, since the
         // others are extras for dimensional box properties.
-        const nsCSSValue *firstSide = data->ValueStorageFor((*subprops)[0]);
+        const nsCSSValue *firstSide = data->ValueFor((*subprops)[0]);
         for (PRInt32 side = 1; side < 4; ++side) {
           const nsCSSValue *otherSide =
-            data->ValueStorageFor((*subprops)[side]);
+            data->ValueFor((*subprops)[side]);
           if (*firstSide != *otherSide)
             match = PR_FALSE;
         }
       }
       if (!match) {
         // We can't express what we have in the border shorthand
         break;
       }
@@ -382,26 +316,22 @@ Declaration::GetValue(nsCSSProperty aPro
     case eCSSProperty_border_bottom:
     case eCSSProperty_border_left:
     case eCSSProperty_border_start:
     case eCSSProperty_border_end:
     case eCSSProperty__moz_column_rule:
     case eCSSProperty_outline: {
       const nsCSSProperty* subprops =
         nsCSSProps::SubpropertyEntryFor(aProperty);
-      NS_ASSERTION(nsCSSProps::kTypeTable[subprops[0]] == eCSSType_Value &&
-                   nsCSSProps::kTypeTable[subprops[1]] == eCSSType_Value &&
-                   nsCSSProps::kTypeTable[subprops[2]] == eCSSType_Value,
-                   "type mismatch");
-      NS_ASSERTION(StringEndsWith(nsCSSProps::GetStringValue(subprops[2]),
-                                  NS_LITERAL_CSTRING("-color")) ||
-                   StringEndsWith(nsCSSProps::GetStringValue(subprops[2]),
-                                  NS_LITERAL_CSTRING("-color-value")),
-                   "third subprop must be the color property");
-      const nsCSSValue *colorValue = data->ValueStorageFor(subprops[2]);
+      NS_ABORT_IF_FALSE(StringEndsWith(nsCSSProps::GetStringValue(subprops[2]),
+                                       NS_LITERAL_CSTRING("-color")) ||
+                        StringEndsWith(nsCSSProps::GetStringValue(subprops[2]),
+                                       NS_LITERAL_CSTRING("-color-value")),
+                        "third subprop must be the color property");
+      const nsCSSValue *colorValue = data->ValueFor(subprops[2]);
       PRBool isMozUseTextColor =
         colorValue->GetUnit() == eCSSUnit_Enumerated &&
         colorValue->GetIntValue() == NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR;
       if (!AppendValueToString(subprops[0], aValue) ||
           !(aValue.Append(PRUnichar(' ')),
             AppendValueToString(subprops[1], aValue)) ||
           // Don't output a third value when it's -moz-use-text-color.
           !(isMozUseTextColor ||
@@ -428,43 +358,50 @@ Declaration::GetValue(nsCSSProperty aPro
     case eCSSProperty_border_start_color:
     case eCSSProperty_border_start_style:
     case eCSSProperty_border_start_width:
     case eCSSProperty_border_end_color:
     case eCSSProperty_border_end_style:
     case eCSSProperty_border_end_width: {
       const nsCSSProperty* subprops =
         nsCSSProps::SubpropertyEntryFor(aProperty);
-      NS_ASSERTION(subprops[3] == eCSSProperty_UNKNOWN,
-                   "not box property with physical vs. logical cascading");
+      NS_ABORT_IF_FALSE(subprops[3] == eCSSProperty_UNKNOWN,
+                        "not box property with physical vs. logical cascading");
       AppendValueToString(subprops[0], aValue);
       break;
     }
     case eCSSProperty_background: {
       // We know from above that all subproperties were specified.
       // However, we still can't represent that in the shorthand unless
       // they're all lists of the same length.  So if they're different
       // lengths, we need to bail out.
       // We also need to bail out if an item has background-clip and
       // background-origin that are different and not the default
       // values.  (We omit them if they're both default.)
       const nsCSSValueList *image =
-        * data->ValueListStorageFor(eCSSProperty_background_image);
+        data->ValueFor(eCSSProperty_background_image)->
+        GetListValue();
       const nsCSSValueList *repeat =
-        * data->ValueListStorageFor(eCSSProperty_background_repeat);
+        data->ValueFor(eCSSProperty_background_repeat)->
+        GetListValue();
       const nsCSSValueList *attachment =
-        * data->ValueListStorageFor(eCSSProperty_background_attachment);
+        data->ValueFor(eCSSProperty_background_attachment)->
+        GetListValue();
       const nsCSSValuePairList *position =
-        * data->ValuePairListStorageFor(eCSSProperty_background_position);
+        data->ValueFor(eCSSProperty_background_position)->
+        GetPairListValue();
       const nsCSSValueList *clip =
-        * data->ValueListStorageFor(eCSSProperty_background_clip);
+        data->ValueFor(eCSSProperty_background_clip)->
+        GetListValue();
       const nsCSSValueList *origin =
-        * data->ValueListStorageFor(eCSSProperty_background_origin);
+        data->ValueFor(eCSSProperty_background_origin)->
+        GetListValue();
       const nsCSSValuePairList *size =
-        * data->ValuePairListStorageFor(eCSSProperty_background_size);
+        data->ValueFor(eCSSProperty_background_size)->
+        GetPairListValue();
       for (;;) {
         if (size->mXValue.GetUnit() != eCSSUnit_Auto ||
             size->mYValue.GetUnit() != eCSSUnit_Auto) {
           // Non-default background-size, so can't be serialized as shorthand.
           aValue.Truncate();
           return;
         }
         image->mValue.AppendToString(eCSSProperty_background_image, aValue);
@@ -474,20 +411,20 @@ Declaration::GetValue(nsCSSProperty aPro
         attachment->mValue.AppendToString(eCSSProperty_background_attachment,
                                           aValue);
         aValue.Append(PRUnichar(' '));
         position->mXValue.AppendToString(eCSSProperty_background_position,
                                          aValue);
         aValue.Append(PRUnichar(' '));
         position->mYValue.AppendToString(eCSSProperty_background_position,
                                          aValue);
-        NS_ASSERTION(clip->mValue.GetUnit() == eCSSUnit_Enumerated &&
-                     origin->mValue.GetUnit() == eCSSUnit_Enumerated,
-                     "should not be inherit/initial within list and "
-                     "should have returned early for real inherit/initial");
+        NS_ABORT_IF_FALSE(clip->mValue.GetUnit() == eCSSUnit_Enumerated &&
+                          origin->mValue.GetUnit() == eCSSUnit_Enumerated,
+                          "should not be inherit/initial within list and "
+                          "should have returned early for real inherit/initial");
         if (clip->mValue.GetIntValue() != NS_STYLE_BG_CLIP_BORDER ||
             origin->mValue.GetIntValue() != NS_STYLE_BG_ORIGIN_PADDING) {
           PR_STATIC_ASSERT(NS_STYLE_BG_CLIP_BORDER ==
                            NS_STYLE_BG_ORIGIN_BORDER);
           PR_STATIC_ASSERT(NS_STYLE_BG_CLIP_PADDING ==
                            NS_STYLE_BG_ORIGIN_PADDING);
           PR_STATIC_ASSERT(NS_STYLE_BG_CLIP_CONTENT ==
                            NS_STYLE_BG_ORIGIN_CONTENT);
@@ -540,37 +477,37 @@ Declaration::GetValue(nsCSSProperty aPro
           aValue.Truncate();
       }
       break;
     }
     case eCSSProperty_font: {
       // systemFont might not be present; the others are guaranteed to be
       // based on the shorthand check at the beginning of the function
       const nsCSSValue *systemFont =
-        data->ValueStorageFor(eCSSProperty__x_system_font);
+        data->ValueFor(eCSSProperty__x_system_font);
       const nsCSSValue &style =
-        *data->ValueStorageFor(eCSSProperty_font_style);
+        *data->ValueFor(eCSSProperty_font_style);
       const nsCSSValue &variant =
-        *data->ValueStorageFor(eCSSProperty_font_variant);
+        *data->ValueFor(eCSSProperty_font_variant);
       const nsCSSValue &weight =
-        *data->ValueStorageFor(eCSSProperty_font_weight);
+        *data->ValueFor(eCSSProperty_font_weight);
       const nsCSSValue &size =
-        *data->ValueStorageFor(eCSSProperty_font_size);
+        *data->ValueFor(eCSSProperty_font_size);
       const nsCSSValue &lh =
-        *data->ValueStorageFor(eCSSProperty_line_height);
+        *data->ValueFor(eCSSProperty_line_height);
       const nsCSSValue &family =
-        *data->ValueStorageFor(eCSSProperty_font_family);
+        *data->ValueFor(eCSSProperty_font_family);
       const nsCSSValue &stretch =
-        *data->ValueStorageFor(eCSSProperty_font_stretch);
+        *data->ValueFor(eCSSProperty_font_stretch);
       const nsCSSValue &sizeAdjust =
-        *data->ValueStorageFor(eCSSProperty_font_size_adjust);
+        *data->ValueFor(eCSSProperty_font_size_adjust);
       const nsCSSValue &featureSettings =
-        *data->ValueStorageFor(eCSSProperty_font_feature_settings);
+        *data->ValueFor(eCSSProperty_font_feature_settings);
       const nsCSSValue &languageOverride =
-        *data->ValueStorageFor(eCSSProperty_font_language_override);
+        *data->ValueFor(eCSSProperty_font_language_override);
 
       if (systemFont &&
           systemFont->GetUnit() != eCSSUnit_None &&
           systemFont->GetUnit() != eCSSUnit_Null) {
         if (style.GetUnit() != eCSSUnit_System_Font ||
             variant.GetUnit() != eCSSUnit_System_Font ||
             weight.GetUnit() != eCSSUnit_System_Font ||
             size.GetUnit() != eCSSUnit_System_Font ||
@@ -626,87 +563,123 @@ Declaration::GetValue(nsCSSProperty aPro
       if (AppendValueToString(eCSSProperty_list_style_type, aValue))
         aValue.Append(PRUnichar(' '));
       if (AppendValueToString(eCSSProperty_list_style_position, aValue))
         aValue.Append(PRUnichar(' '));
       AppendValueToString(eCSSProperty_list_style_image, aValue);
       break;
     case eCSSProperty_overflow: {
       const nsCSSValue &xValue =
-        *data->ValueStorageFor(eCSSProperty_overflow_x);
+        *data->ValueFor(eCSSProperty_overflow_x);
       const nsCSSValue &yValue =
-        *data->ValueStorageFor(eCSSProperty_overflow_y);
+        *data->ValueFor(eCSSProperty_overflow_y);
       if (xValue == yValue)
         xValue.AppendToString(eCSSProperty_overflow_x, aValue);
       break;
     }
     case eCSSProperty_pause: {
       if (AppendValueToString(eCSSProperty_pause_before, aValue)) {
         aValue.Append(PRUnichar(' '));
         if (!AppendValueToString(eCSSProperty_pause_after, aValue))
           aValue.Truncate();
       }
       break;
     }
     case eCSSProperty_transition: {
-#define NUM_TRANSITION_SUBPROPS 4
-      const nsCSSProperty* subprops =
-        nsCSSProps::SubpropertyEntryFor(aProperty);
-#ifdef DEBUG
-      for (int i = 0; i < NUM_TRANSITION_SUBPROPS; ++i) {
-        NS_ASSERTION(nsCSSProps::kTypeTable[subprops[i]] == eCSSType_ValueList,
-                     "type mismatch");
-      }
-      NS_ASSERTION(subprops[NUM_TRANSITION_SUBPROPS] == eCSSProperty_UNKNOWN,
-                   "length mismatch");
-#endif
-      const nsCSSValueList* val[NUM_TRANSITION_SUBPROPS];
-      for (int i = 0; i < NUM_TRANSITION_SUBPROPS; ++i) {
-        val[i] = *data->ValueListStorageFor(subprops[i]);
-      }
-      // Merge the lists of the subproperties into a single list.
-      for (;;) {
-        for (int i = 0; i < NUM_TRANSITION_SUBPROPS; ++i) {
-          val[i]->mValue.AppendToString(subprops[i], aValue);
+      const nsCSSValue &transProp =
+        *data->ValueFor(eCSSProperty_transition_property);
+      const nsCSSValue &transDuration =
+        *data->ValueFor(eCSSProperty_transition_duration);
+      const nsCSSValue &transTiming =
+        *data->ValueFor(eCSSProperty_transition_timing_function);
+      const nsCSSValue &transDelay =
+        *data->ValueFor(eCSSProperty_transition_delay);
+
+      NS_ABORT_IF_FALSE(transDuration.GetUnit() == eCSSUnit_List ||
+                        transDuration.GetUnit() == eCSSUnit_ListDep,
+                        nsPrintfCString(32, "bad t-duration unit %d",
+                                        transDuration.GetUnit()).get());
+      NS_ABORT_IF_FALSE(transTiming.GetUnit() == eCSSUnit_List ||
+                        transTiming.GetUnit() == eCSSUnit_ListDep,
+                        nsPrintfCString(32, "bad t-timing unit %d",
+                                        transTiming.GetUnit()).get());
+      NS_ABORT_IF_FALSE(transDelay.GetUnit() == eCSSUnit_List ||
+                        transDelay.GetUnit() == eCSSUnit_ListDep,
+                        nsPrintfCString(32, "bad t-delay unit %d",
+                                        transDelay.GetUnit()).get());
+
+      const nsCSSValueList* dur = transDuration.GetListValue();
+      const nsCSSValueList* tim = transTiming.GetListValue();
+      const nsCSSValueList* del = transDelay.GetListValue();
+
+      if (transProp.GetUnit() == eCSSUnit_None ||
+          transProp.GetUnit() == eCSSUnit_All) {
+        // If any of the other three lists has more than one element,
+        // we can't use the shorthand.
+        if (!dur->mNext && !tim->mNext && !del->mNext) {
+          transProp.AppendToString(eCSSProperty_transition_property, aValue);
+          aValue.Append(PRUnichar(' '));
+          dur->mValue.AppendToString(eCSSProperty_transition_duration,aValue);
+          aValue.Append(PRUnichar(' '));
+          tim->mValue.AppendToString(eCSSProperty_transition_timing_function,
+                                     aValue);
           aValue.Append(PRUnichar(' '));
-          val[i] = val[i]->mNext;
-        }
-        // Remove the last space.
-        aValue.Truncate(aValue.Length() - 1);
-
-        PR_STATIC_ASSERT(NUM_TRANSITION_SUBPROPS == 4);
-        if (!val[0] || !val[1] || !val[2] || !val[3]) {
-          break;
+          del->mValue.AppendToString(eCSSProperty_transition_delay, aValue);
+          aValue.Append(PRUnichar(' '));
+        } else {
+          aValue.Truncate();
         }
-        aValue.AppendLiteral(", ");
+      } else {
+        NS_ABORT_IF_FALSE(transProp.GetUnit() == eCSSUnit_List ||
+                          transProp.GetUnit() == eCSSUnit_ListDep,
+                          nsPrintfCString(32, "bad t-prop unit %d",
+                                          transProp.GetUnit()).get());
+        const nsCSSValueList* pro = transProp.GetListValue();
+        for (;;) {
+          pro->mValue.AppendToString(eCSSProperty_transition_property,
+                                        aValue);
+          aValue.Append(PRUnichar(' '));
+          dur->mValue.AppendToString(eCSSProperty_transition_duration,
+                                        aValue);
+          aValue.Append(PRUnichar(' '));
+          tim->mValue.AppendToString(eCSSProperty_transition_timing_function,
+                                        aValue);
+          aValue.Append(PRUnichar(' '));
+          del->mValue.AppendToString(eCSSProperty_transition_delay,
+                                        aValue);
+          pro = pro->mNext;
+          dur = dur->mNext;
+          tim = tim->mNext;
+          del = del->mNext;
+          if (!pro || !dur || !tim || !del) {
+            break;
+          }
+          aValue.AppendLiteral(", ");
+        }
+        if (pro || dur || tim || del) {
+          // Lists not all the same length, can't use shorthand.
+          aValue.Truncate();
+        }
       }
-
-      PR_STATIC_ASSERT(NUM_TRANSITION_SUBPROPS == 4);
-      if (val[0] || val[1] || val[2] || val[3]) {
-        // The sublists are different lengths, so this can't be
-        // represented as the shorthand.
-        aValue.Truncate();
-      }
-#undef NUM_TRANSITION_SUBPROPS
       break;
     }
 
     case eCSSProperty_marker: {
       const nsCSSValue &endValue =
-        *data->ValueStorageFor(eCSSProperty_marker_end);
+        *data->ValueFor(eCSSProperty_marker_end);
       const nsCSSValue &midValue =
-        *data->ValueStorageFor(eCSSProperty_marker_mid);
+        *data->ValueFor(eCSSProperty_marker_mid);
       const nsCSSValue &startValue =
-        *data->ValueStorageFor(eCSSProperty_marker_start);
+        *data->ValueFor(eCSSProperty_marker_start);
       if (endValue == midValue && midValue == startValue)
         AppendValueToString(eCSSProperty_marker_end, aValue);
       break;
     }
     default:
-      NS_NOTREACHED("no other shorthands");
+      NS_ABORT_IF_FALSE(false, "no other shorthands");
       break;
   }
 }
 
 PRBool
 Declaration::GetValueIsImportant(const nsAString& aProperty) const
 {
   nsCSSProperty propID = nsCSSProps::LookupProperty(aProperty);
@@ -714,76 +687,67 @@ Declaration::GetValueIsImportant(const n
 }
 
 PRBool
 Declaration::GetValueIsImportant(nsCSSProperty aProperty) const
 {
   if (!mImportantData)
     return PR_FALSE;
 
-  // Calling StorageFor is inefficient, but we can assume '!important'
-  // is rare.
+  // Calling ValueFor is inefficient, but we can assume '!important' is rare.
 
-  if (nsCSSProps::IsShorthand(aProperty)) {
-    CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProperty) {
-      if (*p == eCSSProperty__x_system_font) {
-        // The system_font subproperty doesn't count.
-        continue;
-      }
-      if (!mImportantData->StorageFor(*p)) {
-        return PR_FALSE;
-      }
-    }
-    return PR_TRUE;
+  if (!nsCSSProps::IsShorthand(aProperty)) {
+    return mImportantData->ValueFor(aProperty) != nsnull;
   }
 
-  return mImportantData->StorageFor(aProperty) != nsnull;
-}
-
-/* static */ void
-Declaration::AppendImportanceToString(PRBool aIsImportant,
-                                      nsAString& aString)
-{
-  if (aIsImportant) {
-   aString.AppendLiteral(" ! important");
+  CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProperty) {
+    if (*p == eCSSProperty__x_system_font) {
+      // The system_font subproperty doesn't count.
+      continue;
+    }
+    if (!mImportantData->ValueFor(*p)) {
+      return PR_FALSE;
+    }
   }
+  return PR_TRUE;
 }
 
 void
 Declaration::AppendPropertyAndValueToString(nsCSSProperty aProperty,
                                             nsAutoString& aValue,
                                             nsAString& aResult) const
 {
-  NS_ASSERTION(0 <= aProperty && aProperty < eCSSProperty_COUNT,
-               "property enum out of range");
-  NS_ASSERTION((aProperty < eCSSProperty_COUNT_no_shorthands) ==
-                 aValue.IsEmpty(),
-               "aValue should be given for shorthands but not longhands");
+  NS_ABORT_IF_FALSE(0 <= aProperty && aProperty < eCSSProperty_COUNT,
+                    "property enum out of range");
+  NS_ABORT_IF_FALSE((aProperty < eCSSProperty_COUNT_no_shorthands) ==
+                    aValue.IsEmpty(),
+                    "aValue should be given for shorthands but not longhands");
   AppendASCIItoUTF16(nsCSSProps::GetStringValue(aProperty), aResult);
   aResult.AppendLiteral(": ");
   if (aValue.IsEmpty())
     AppendValueToString(aProperty, aResult);
   else
     aResult.Append(aValue);
-  PRBool  isImportant = GetValueIsImportant(aProperty);
-  AppendImportanceToString(isImportant, aResult);
+  if (GetValueIsImportant(aProperty)) {
+    aResult.AppendLiteral(" ! important");
+  }
   aResult.AppendLiteral("; ");
 }
 
 void
 Declaration::ToString(nsAString& aString) const
 {
   // Someone cares about this declaration's contents, so don't let it
   // change from under them.  See e.g. bug 338679.
   SetImmutable();
 
   nsCSSCompressedDataBlock *systemFontData =
     GetValueIsImportant(eCSSProperty__x_system_font) ? mImportantData : mData;
-  const nsCSSValue *systemFont = 
-    systemFontData->ValueStorageFor(eCSSProperty__x_system_font);
+  const nsCSSValue *systemFont =
+    systemFontData->ValueFor(eCSSProperty__x_system_font);
   const PRBool haveSystemFont = systemFont &&
                                 systemFont->GetUnit() != eCSSUnit_None &&
                                 systemFont->GetUnit() != eCSSUnit_Null;
   PRBool didSystemFont = PR_FALSE;
 
   PRInt32 count = mOrder.Length();
   PRInt32 index;
   nsAutoTArray<nsCSSProperty, 16> shorthandsUsed;
@@ -820,19 +784,19 @@ Declaration::ToString(nsAString& aString
       GetValue(shorthand, value);
       if (!value.IsEmpty()) {
         AppendPropertyAndValueToString(shorthand, value, aString);
         shorthandsUsed.AppendElement(shorthand);
         doneProperty = PR_TRUE;
         break;
       }
 
-      NS_ASSERTION(shorthand != eCSSProperty_font ||
-                   *(shorthands + 1) == eCSSProperty_UNKNOWN,
-                   "font should always be the only containing shorthand");
+      NS_ABORT_IF_FALSE(shorthand != eCSSProperty_font ||
+                        *(shorthands + 1) == eCSSProperty_UNKNOWN,
+                        "font should always be the only containing shorthand");
       if (shorthand == eCSSProperty_font) {
         if (haveSystemFont && !didSystemFont) {
           // Output the shorthand font declaration that we will
           // partially override later.  But don't add it to
           // |shorthandsUsed|, since we will have to override it.
           systemFont->AppendToString(eCSSProperty__x_system_font, value);
           AppendPropertyAndValueToString(eCSSProperty_font, value, aString);
           value.Truncate();
@@ -840,40 +804,39 @@ Declaration::ToString(nsAString& aString
         }
 
         // That we output the system font is enough for this property if:
         //   (1) it's the hidden system font subproperty (which either
         //       means we output it or we don't have it), or
         //   (2) its value is the hidden system font value and it matches
         //       the hidden system font subproperty in importance, and
         //       we output the system font subproperty.
-        NS_ASSERTION(nsCSSProps::kTypeTable[property] == eCSSType_Value,
-                     "not a value typed subproperty");
-        const nsCSSValue *val =
-          systemFontData->ValueStorageFor(property);
+        const nsCSSValue *val = systemFontData->ValueFor(property);
         if (property == eCSSProperty__x_system_font ||
             (haveSystemFont && val && val->GetUnit() == eCSSUnit_System_Font)) {
           doneProperty = PR_TRUE;
         }
       }
     }
     if (doneProperty)
       continue;
-    
-    NS_ASSERTION(value.IsEmpty(), "value should be empty now");
+
+    NS_ABORT_IF_FALSE(value.IsEmpty(), "value should be empty now");
     AppendPropertyAndValueToString(property, value, aString);
   }
   if (! aString.IsEmpty()) {
-    // if the string is not empty, we have a trailing whitespace we should remove
+    // if the string is not empty, we have trailing whitespace we
+    // should remove
     aString.Truncate(aString.Length() - 1);
   }
 }
 
 #ifdef DEBUG
-void Declaration::List(FILE* out, PRInt32 aIndent) const
+void
+Declaration::List(FILE* out, PRInt32 aIndent) const
 {
   for (PRInt32 index = aIndent; --index >= 0; ) fputs("  ", out);
 
   fputs("{ ", out);
   nsAutoString s;
   ToString(s);
   fputs(NS_ConvertUTF16toUTF8(s).get(), out);
   fputs("}", out);
@@ -890,24 +853,24 @@ Declaration::GetNthProperty(PRUint32 aIn
       AppendASCIItoUTF16(nsCSSProps::GetStringValue(property), aReturn);
     }
   }
 }
 
 void
 Declaration::InitializeEmpty()
 {
-  NS_ASSERTION(!mData && !mImportantData, "already initialized");
+  NS_ABORT_IF_FALSE(!mData && !mImportantData, "already initialized");
   mData = nsCSSCompressedDataBlock::CreateEmptyBlock();
 }
 
 Declaration*
 Declaration::EnsureMutable()
 {
-  NS_ASSERTION(mData, "should only be called when not expanded");
+  NS_ABORT_IF_FALSE(mData, "should only be called when not expanded");
   if (!IsMutable()) {
     return new Declaration(*this);
   } else {
     return this;
   }
 }
 
 } // namespace mozilla::css
--- a/layout/style/Declaration.h
+++ b/layout/style/Declaration.h
@@ -45,26 +45,22 @@
 #define mozilla_css_Declaration_h
 
 // This header is in EXPORTS because it's used in several places in content/,
 // but it's not really a public interface.
 #ifndef _IMPL_NS_LAYOUT
 #error "This file should only be included within the layout library"
 #endif
 
-#include "nsISupports.h"
-#include "nsColor.h"
+#include "nsCSSDataBlock.h"
+#include "nsCSSProperty.h"
+#include "nsCSSProps.h"
+#include "nsStringFwd.h"
+#include "nsTArray.h"
 #include <stdio.h>
-#include "nsString.h"
-#include "nsCoord.h"
-#include "nsCSSValue.h"
-#include "nsCSSProps.h"
-#include "nsTArray.h"
-#include "nsCSSDataBlock.h"
-#include "nsCSSStruct.h"
 
 namespace mozilla {
 namespace css {
 
 // Declaration objects have unusual lifetime rules.  Every declaration
 // begins life in an invalid state which ends when InitializeEmpty or
 // CompressFrom is called upon it.  After that, it can be attached to
 // exactly one style rule, and will be destroyed when that style rule
@@ -115,35 +111,35 @@ public:
    */
   void InitializeEmpty();
 
   /**
    * Transfer all of the state from |aExpandedData| into this declaration.
    * After calling, |aExpandedData| should be in its initial state.
    */
   void CompressFrom(nsCSSExpandedDataBlock *aExpandedData) {
-    NS_ASSERTION(!mData, "oops");
-    NS_ASSERTION(!mImportantData, "oops");
+    NS_ABORT_IF_FALSE(!mData, "oops");
+    NS_ABORT_IF_FALSE(!mImportantData, "oops");
     aExpandedData->Compress(getter_Transfers(mData),
                             getter_Transfers(mImportantData));
     aExpandedData->AssertInitialState();
   }
 
   /**
    * Transfer all of the state from this declaration into
    * |aExpandedData| and put this declaration temporarily into an
    * invalid state (ended by |CompressFrom| or |InitializeEmpty|) that
    * should last only during parsing.  During this time only
    * |ValueAppended| should be called.
    */
   void ExpandTo(nsCSSExpandedDataBlock *aExpandedData) {
     AssertMutable();
     aExpandedData->AssertInitialState();
 
-    NS_ASSERTION(mData, "oops");
+    NS_ABORT_IF_FALSE(mData, "oops");
     aExpandedData->Expand(mData.forget(), mImportantData.forget());
   }
 
   /**
    * Do what |nsIStyleRule::MapRuleInfoInto| needs to do for a style
    * rule using this declaration for storage.
    */
   void MapNormalRuleInfoInto(nsRuleData *aRuleData) const {
@@ -152,50 +148,57 @@ public:
   }
   void MapImportantRuleInfoInto(nsRuleData *aRuleData) const {
     NS_ABORT_IF_FALSE(mData, "called while expanded");
     NS_ABORT_IF_FALSE(mImportantData, "must have important data");
     mImportantData->MapRuleInfoInto(aRuleData);
   }
 
   /**
-   * Return a pointer to our current value for this property.
-   * Only returns non-null if the property is longhand, set, and
-   * has the indicated importance level.
-   *
-   * May only be called when not expanded, and the caller must call
-   * EnsureMutable first.
+   * Attempt to replace the value for |aProperty| stored in this
+   * declaration with the matching value from |aFromBlock|.
+   * This method may only be called on a mutable declaration.
+   * It will fail (returning PR_FALSE) if |aProperty| is shorthand,
+   * is not already in this declaration, or does not have the indicated
+   * importance level.  If it returns PR_TRUE, it erases the value in
+   * |aFromBlock|.  |aChanged| is set to PR_TRUE if the declaration
+   * changed as a result of the call, and to PR_FALSE otherwise.
    */
-  void* SlotForValue(nsCSSProperty aProperty, PRBool aIsImportant) {
+  PRBool TryReplaceValue(nsCSSProperty aProperty, PRBool aIsImportant,
+                         nsCSSExpandedDataBlock& aFromBlock,
+                         PRBool* aChanged)
+  {
     AssertMutable();
     NS_ABORT_IF_FALSE(mData, "called while expanded");
 
     if (nsCSSProps::IsShorthand(aProperty)) {
-      return nsnull;
+      *aChanged = PR_FALSE;
+      return PR_FALSE;
     }
     nsCSSCompressedDataBlock *block = aIsImportant ? mImportantData : mData;
     // mImportantData might be null
     if (!block) {
-      return nsnull;
+      *aChanged = PR_FALSE;
+      return PR_FALSE;
     }
 
-    void *slot = block->SlotForValue(aProperty);
 #ifdef DEBUG
     {
       nsCSSCompressedDataBlock *other = aIsImportant ? mData : mImportantData;
-      NS_ABORT_IF_FALSE(!slot || !other || !other->StorageFor(aProperty),
+      NS_ABORT_IF_FALSE(!other || !other->ValueFor(aProperty) ||
+                        !block->ValueFor(aProperty),
                         "Property both important and not?");
     }
 #endif
-    return slot;
+    return block->TryReplaceValue(aProperty, aFromBlock, aChanged);
   }
 
   PRBool HasNonImportantValueFor(nsCSSProperty aProperty) const {
     NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(aProperty), "must be longhand");
-    return !!mData->StorageFor(aProperty);
+    return !!mData->ValueFor(aProperty);
   }
 
   /**
    * Return whether |this| may be modified.
    */
   bool IsMutable() const {
     return !mImmutable;
   }
--- a/layout/style/nsCSSDataBlock.cpp
+++ b/layout/style/nsCSSDataBlock.cpp
@@ -37,70 +37,35 @@
 
 /*
  * compact representation of the property-value pairs within a CSS
  * declaration, and the code for expanding and compacting it
  */
 
 #include "nsCSSDataBlock.h"
 #include "mozilla/css/Declaration.h"
-#include "nsCSSProps.h"
 #include "nsRuleData.h"
-#include "nsRuleNode.h"
 #include "nsStyleSet.h"
 #include "nsStyleContext.h"
 
 namespace css = mozilla::css;
 
 /*
- * nsCSSCompressedDataBlock holds property-value pairs corresponding to
- * CSS declaration blocks.  The value is stored in one of the five CSS
- * data types: nsCSSValue, nsCSSRect, nsCSSValueList, nsCSSValuePair,
- * and nsCSSValuePairList, which each correspond to a value of the
- * nsCSSType enumeration.
- *
- * The storage strategy uses the CDB*Storage structs below to help
- * ensure that all the types remain properly aligned.  nsCSSValue's
- * alignment requirements cannot be weaker than any others, since it
- * contains a pointer and an enumeration.
- *
- * The simple types, nsCSSValue and nsCSSRect have the nsCSSValue or
- * nsCSSRect objects stored in the block.  The list types have only a
- * pointer to the first element in the list stored in the block.
+ * nsCSSCompressedDataBlock holds property-value pairs corresponding
+ * to CSS declaration blocks.  Each pair is stored in a CDBValueStorage
+ * object; these objects form an array at the end of the data block.
  */
 
 struct CDBValueStorage {
     nsCSSProperty property;
     nsCSSValue value;
 };
 
-struct CDBRectStorage {
-    nsCSSProperty property;
-    nsCSSRect value;
-
-};
-
-struct CDBValuePairStorage {
-    nsCSSProperty property;
-    nsCSSValuePair value;
-};
-
-struct CDBPointerStorage {
-    nsCSSProperty property;
-    void *value;
-};
-
 enum {
-    CDBValueStorage_advance = sizeof(CDBValueStorage),
-    CDBRectStorage_advance = sizeof(CDBRectStorage),
-    CDBValuePairStorage_advance = sizeof(CDBValuePairStorage),
-    // round up using the closest estimate we can get of the alignment
-    // requirements of nsCSSValue:
-    CDBPointerStorage_advance = PR_ROUNDUP(sizeof(CDBPointerStorage),
-                                sizeof(CDBValueStorage) - sizeof(nsCSSValue))
+    CDBValueStorage_advance = sizeof(CDBValueStorage)
 };
 
 /*
  * Define a bunch of utility functions for getting the property or any
  * of the value types when the cursor is at the beginning of the storage
  * for the property-value pair.  The versions taking a non-const cursor
  * argument return a reference so that the caller can assign into the
  * result.
@@ -117,58 +82,30 @@ inline nsCSSProperty PropertyAtCursor(co
 inline nsCSSValue* ValueAtCursor(char *aCursor) {
     return & reinterpret_cast<CDBValueStorage*>(aCursor)->value;
 }
 
 inline const nsCSSValue* ValueAtCursor(const char *aCursor) {
     return & reinterpret_cast<const CDBValueStorage*>(aCursor)->value;
 }
 
-inline nsCSSRect* RectAtCursor(char *aCursor) {
-    return & reinterpret_cast<CDBRectStorage*>(aCursor)->value;
-}
-
-inline const nsCSSRect* RectAtCursor(const char *aCursor) {
-    return & reinterpret_cast<const CDBRectStorage*>(aCursor)->value;
-}
-
-inline nsCSSValuePair* ValuePairAtCursor(char *aCursor) {
-  return & reinterpret_cast<CDBValuePairStorage*>(aCursor)->value;
-}
-
-inline const nsCSSValuePair* ValuePairAtCursor(const char *aCursor) {
-  return & reinterpret_cast<const CDBValuePairStorage*>(aCursor)->value;
-}
-
-inline void*& PointerAtCursor(char *aCursor) {
-    return reinterpret_cast<CDBPointerStorage*>(aCursor)->value;
-}
-
-inline void* PointerAtCursor(const char *aCursor) {
-    return reinterpret_cast<const CDBPointerStorage*>(aCursor)->value;
-}
-
-inline nsCSSValueList*& ValueListAtCursor(char *aCursor) {
-    return * reinterpret_cast<nsCSSValueList**>
-                             (& reinterpret_cast<CDBPointerStorage*>(aCursor)->value);
-}
-
-inline nsCSSValueList* ValueListAtCursor(const char *aCursor) {
-    return static_cast<nsCSSValueList*>
-                      (reinterpret_cast<const CDBPointerStorage*>(aCursor)->value);
-}
-
-inline nsCSSValuePairList*& ValuePairListAtCursor(char *aCursor) {
-    return * reinterpret_cast<nsCSSValuePairList**>
-                             (& reinterpret_cast<CDBPointerStorage*>(aCursor)->value);
-}
-
-inline nsCSSValuePairList* ValuePairListAtCursor(const char *aCursor) {
-    return static_cast<nsCSSValuePairList*>
-                      (reinterpret_cast<const CDBPointerStorage*>(aCursor)->value);
+/**
+ * Does a fast move of aSource to aDest.  The previous value in
+ * aDest is cleanly destroyed, and aSource is cleared.  Returns
+ * true if, before the copy, the value at aSource compared unequal
+ * to the value at aDest; false otherwise.
+ */
+static PRBool
+MoveValue(nsCSSValue* aSource, nsCSSValue* aDest)
+{
+    PRBool changed = (*aSource != *aDest);
+    aDest->~nsCSSValue();
+    memcpy(aDest, aSource, sizeof(nsCSSValue));
+    new (aSource) nsCSSValue();
+    return changed;
 }
 
 static PRBool
 ShouldIgnoreColors(nsRuleData *aRuleData)
 {
     return aRuleData->mLevel != nsStyleSet::eAgentSheet &&
            aRuleData->mLevel != nsStyleSet::eUserSheet &&
            !aRuleData->mPresContext->UseDocumentColors();
@@ -193,17 +130,22 @@ TryToStartImageLoadOnValue(const nsCSSVa
       image.StartImageLoad(aDocument);
   }
 }
 
 static void
 TryToStartImageLoad(const nsCSSValue& aValue, nsIDocument* aDocument,
                     nsCSSProperty aProperty)
 {
-  if (nsCSSProps::PropHasFlags(aProperty, CSS_PROPERTY_IMAGE_IS_IN_ARRAY_0)) {
+  if (aValue.GetUnit() == eCSSUnit_List) {
+    for (const nsCSSValueList* l = aValue.GetListValue(); l; l = l->mNext) {
+      TryToStartImageLoad(l->mValue, aDocument, aProperty);
+    }
+  } else if (nsCSSProps::PropHasFlags(aProperty,
+                                      CSS_PROPERTY_IMAGE_IS_IN_ARRAY_0)) {
     if (aValue.GetUnit() == eCSSUnit_Array) {
       TryToStartImageLoadOnValue(aValue.GetArrayValue()->Item(0), aDocument);
     }
   } else {
     TryToStartImageLoadOnValue(aValue, aDocument);
   }
 }
 
@@ -232,418 +174,174 @@ nsCSSCompressedDataBlock::MapRuleInfoInt
         return;
 
     nsIDocument* doc = aRuleData->mPresContext->Document();
 
     const char* cursor = Block();
     const char* cursor_end = BlockEnd();
     while (cursor < cursor_end) {
         nsCSSProperty iProp = PropertyAtCursor(cursor);
-        NS_ASSERTION(0 <= iProp && iProp < eCSSProperty_COUNT_no_shorthands,
-                     "out of range");
+        NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(iProp), "out of range");
         if (nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[iProp]) &
             aRuleData->mSIDs) {
-            void *prop = aRuleData->StorageFor(iProp);
-            switch (nsCSSProps::kTypeTable[iProp]) {
-                case eCSSType_Value: {
-                    nsCSSValue* target = static_cast<nsCSSValue*>(prop);
-                    if (target->GetUnit() == eCSSUnit_Null) {
-                        const nsCSSValue *val = ValueAtCursor(cursor);
-                        NS_ASSERTION(val->GetUnit() != eCSSUnit_Null, "oops");
-                        if (ShouldStartImageLoads(aRuleData, iProp)) {
-                            TryToStartImageLoad(*val, doc, iProp);
-                        }
-                        *target = *val;
-                        if (iProp == eCSSProperty_font_family) {
-                            // XXX Are there other things like this?
-                            aRuleData->mFontData->mFamilyFromHTML = PR_FALSE;
+            nsCSSValue* target = aRuleData->ValueFor(iProp);
+            if (target->GetUnit() == eCSSUnit_Null) {
+                const nsCSSValue *val = ValueAtCursor(cursor);
+                NS_ABORT_IF_FALSE(val->GetUnit() != eCSSUnit_Null, "oops");
+                if (ShouldStartImageLoads(aRuleData, iProp)) {
+                    TryToStartImageLoad(*val, doc, iProp);
+                }
+                *target = *val;
+                if (iProp == eCSSProperty_font_family) {
+                    // XXX Are there other things like this?
+                    aRuleData->mFontData->mFamilyFromHTML = PR_FALSE;
+                }
+                if (nsCSSProps::PropHasFlags(iProp,
+                        CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED) &&
+                    ShouldIgnoreColors(aRuleData))
+                {
+                    if (iProp == eCSSProperty_background_color) {
+                        // Force non-'transparent' background
+                        // colors to the user's default.
+                        if (target->IsNonTransparentColor()) {
+                            target->SetColorValue(aRuleData->mPresContext->
+                                                  DefaultBackgroundColor());
                         }
-                        if (nsCSSProps::PropHasFlags(iProp,
-                                CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED) &&
-                            ShouldIgnoreColors(aRuleData))
-                        {
-                            if (iProp == eCSSProperty_background_color) {
-                                // Force non-'transparent' background
-                                // colors to the user's default.
-                                if (target->IsNonTransparentColor()) {
-                                    target->SetColorValue(aRuleData->
-                                        mPresContext->
-                                        DefaultBackgroundColor());
-                                }
-                            } else {
-                                // Ignore 'color', 'border-*-color', etc.
-                                *target = nsCSSValue();
-                            }
-                        }
+                    } else {
+                        // Ignore 'color', 'border-*-color', etc.
+                        *target = nsCSSValue();
                     }
-                    cursor += CDBValueStorage_advance;
-                } break;
-
-                case eCSSType_Rect: {
-                    NS_ABORT_IF_FALSE(!nsCSSProps::PropHasFlags(iProp,
-                        CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED),
-                        "this case needs to handle color properties");
-                    const nsCSSRect* val = RectAtCursor(cursor);
-                    NS_ASSERTION(val->HasValue(), "oops");
-                    nsCSSRect* target = static_cast<nsCSSRect*>(prop);
-                    if (target->mTop.GetUnit() == eCSSUnit_Null)
-                        target->mTop = val->mTop;
-                    if (target->mRight.GetUnit() == eCSSUnit_Null)
-                        target->mRight = val->mRight;
-                    if (target->mBottom.GetUnit() == eCSSUnit_Null)
-                        target->mBottom = val->mBottom;
-                    if (target->mLeft.GetUnit() == eCSSUnit_Null)
-                        target->mLeft = val->mLeft;
-                    cursor += CDBRectStorage_advance;
-                } break;
-
-                case eCSSType_ValuePair: {
-                    NS_ABORT_IF_FALSE(!nsCSSProps::PropHasFlags(iProp,
-                        CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED),
-                        "this case needs to handle color properties");
-                    const nsCSSValuePair* val = ValuePairAtCursor(cursor);
-                    NS_ASSERTION(val->mXValue.GetUnit() != eCSSUnit_Null ||
-                                 val->mYValue.GetUnit() != eCSSUnit_Null, "oops");
-                    nsCSSValuePair* target = static_cast<nsCSSValuePair*>(prop);
-                    NS_ASSERTION((target->mXValue.GetUnit() == eCSSUnit_Null)
-                              == (target->mYValue.GetUnit() == eCSSUnit_Null),
-                                 "half a property?");
-                    if (target->mXValue.GetUnit() == eCSSUnit_Null) {
-                        target->mXValue = val->mXValue;
-                        target->mYValue = val->mYValue;
-                    }
-                    cursor += CDBValuePairStorage_advance;
-                } break;
-
-                case eCSSType_ValueList:
-                case eCSSType_ValuePairList: {
-                    void** target = static_cast<void**>(prop);
-                    if (!*target) {
-                        if (ShouldStartImageLoads(aRuleData, iProp)) {
-                            for (nsCSSValueList* l = ValueListAtCursor(cursor);
-                                 l; l = l->mNext) {
-                                TryToStartImageLoad(l->mValue, doc, iProp);
-                            }
-                        }
-
-                        void* val = PointerAtCursor(cursor);
-                        NS_ASSERTION(val, "oops");
-                        *target = val;
-
-                        if (nsCSSProps::PropHasFlags(iProp,
-                                CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED) &&
-                            ShouldIgnoreColors(aRuleData))
-                        {
-                            *target = nsnull;
-                        }
-                    }
-                    cursor += CDBPointerStorage_advance;
-                } break;
-            }
-        } else {
-            switch (nsCSSProps::kTypeTable[iProp]) {
-                case eCSSType_Value: {
-                    cursor += CDBValueStorage_advance;
-                } break;
-
-                case eCSSType_Rect: {
-                    cursor += CDBRectStorage_advance;
-                } break;
-
-                case eCSSType_ValuePair: {
-                    cursor += CDBValuePairStorage_advance;
-                } break;
-
-                case eCSSType_ValueList:
-                case eCSSType_ValuePairList: {
-                    cursor += CDBPointerStorage_advance;
-                } break;
+                }
             }
         }
+        cursor += CDBValueStorage_advance;
     }
-    NS_ASSERTION(cursor == cursor_end, "inconsistent data");
+    NS_ABORT_IF_FALSE(cursor == cursor_end, "inconsistent data");
 }
 
-const void*
-nsCSSCompressedDataBlock::StorageFor(nsCSSProperty aProperty) const
+const nsCSSValue*
+nsCSSCompressedDataBlock::ValueFor(nsCSSProperty aProperty) const
 {
-    NS_PRECONDITION(!nsCSSProps::IsShorthand(aProperty),
-                    "Don't call for shorthands");
+    NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(aProperty),
+                      "Don't call for shorthands");
 
     // If we have no data for this struct, then return immediately.
     // This optimization should make us return most of the time, so we
     // have to worry much less (although still some) about the speed of
     // the rest of the function.
     if (!(nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[aProperty]) &
           mStyleBits))
         return nsnull;
 
     const char* cursor = Block();
     const char* cursor_end = BlockEnd();
     while (cursor < cursor_end) {
         nsCSSProperty iProp = PropertyAtCursor(cursor);
-        NS_ASSERTION(0 <= iProp && iProp < eCSSProperty_COUNT_no_shorthands,
-                     "out of range");
+        NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(iProp), "out of range");
         if (iProp == aProperty) {
-            switch (nsCSSProps::kTypeTable[iProp]) {
-                case eCSSType_Value: {
-                    return ValueAtCursor(cursor);
-                }
-                case eCSSType_Rect: {
-                    return RectAtCursor(cursor);
-                }
-                case eCSSType_ValuePair: {
-                    return ValuePairAtCursor(cursor);
-                }
-                case eCSSType_ValueList:
-                case eCSSType_ValuePairList: {
-                    return &PointerAtCursor(const_cast<char*>(cursor));
-                }
-            }
+            return ValueAtCursor(cursor);
         }
-        switch (nsCSSProps::kTypeTable[iProp]) {
-            case eCSSType_Value: {
-                cursor += CDBValueStorage_advance;
-            } break;
-
-            case eCSSType_Rect: {
-                cursor += CDBRectStorage_advance;
-            } break;
-
-            case eCSSType_ValuePair: {
-                cursor += CDBValuePairStorage_advance;
-            } break;
-
-            case eCSSType_ValueList:
-            case eCSSType_ValuePairList: {
-                cursor += CDBPointerStorage_advance;
-            } break;
-        }
+        cursor += CDBValueStorage_advance;
     }
-    NS_ASSERTION(cursor == cursor_end, "inconsistent data");
+    NS_ABORT_IF_FALSE(cursor == cursor_end, "inconsistent data");
 
     return nsnull;
 }
 
+PRBool
+nsCSSCompressedDataBlock::TryReplaceValue(nsCSSProperty aProperty,
+                                          nsCSSExpandedDataBlock& aFromBlock,
+                                          PRBool *aChanged)
+{
+    nsCSSValue* newValue = aFromBlock.PropertyAt(aProperty);
+    NS_ABORT_IF_FALSE(newValue && newValue->GetUnit() != eCSSUnit_Null,
+                      "cannot replace with empty value");
+
+    const nsCSSValue* oldValue = ValueFor(aProperty);
+    if (!oldValue) {
+        *aChanged = PR_FALSE;
+        return PR_FALSE;
+    }
+
+    *aChanged = MoveValue(newValue, const_cast<nsCSSValue*>(oldValue));
+    aFromBlock.ClearPropertyBit(aProperty);
+    return PR_TRUE;
+}
+
 nsCSSCompressedDataBlock*
 nsCSSCompressedDataBlock::Clone() const
 {
     const char *cursor = Block(), *cursor_end = BlockEnd();
     char *result_cursor;
 
     nsAutoPtr<nsCSSCompressedDataBlock> result
         (new(cursor_end - cursor) nsCSSCompressedDataBlock());
     if (!result)
         return nsnull;
     result_cursor = result->Block();
 
     while (cursor < cursor_end) {
         nsCSSProperty iProp = PropertyAtCursor(cursor);
-        NS_ASSERTION(0 <= iProp && iProp < eCSSProperty_COUNT_no_shorthands,
-                     "out of range");
+        NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(iProp), "out of range");
         PropertyAtCursor(result_cursor) = iProp;
 
-        switch (nsCSSProps::kTypeTable[iProp]) {
-            case eCSSType_Value: {
-                const nsCSSValue* val = ValueAtCursor(cursor);
-                NS_ASSERTION(val->GetUnit() != eCSSUnit_Null, "oops");
-                nsCSSValue *result_val = ValueAtCursor(result_cursor);
-                new (result_val) nsCSSValue(*val);
-                cursor += CDBValueStorage_advance;
-                result_cursor +=  CDBValueStorage_advance;
-            } break;
-
-            case eCSSType_Rect: {
-                const nsCSSRect* val = RectAtCursor(cursor);
-                NS_ASSERTION(val->HasValue(), "oops");
-                nsCSSRect* result_val = RectAtCursor(result_cursor);
-                new (result_val) nsCSSRect(*val);
-                cursor += CDBRectStorage_advance;
-                result_cursor += CDBRectStorage_advance;
-            } break;
-
-            case eCSSType_ValuePair: {
-                const nsCSSValuePair* val = ValuePairAtCursor(cursor);
-                NS_ASSERTION(val->mXValue.GetUnit() != eCSSUnit_Null ||
-                             val->mYValue.GetUnit() != eCSSUnit_Null, "oops");
-                nsCSSValuePair* result_val = ValuePairAtCursor(result_cursor);
-                new (result_val) nsCSSValuePair(*val);
-                cursor += CDBValuePairStorage_advance;
-                result_cursor += CDBValuePairStorage_advance;
-            } break;
-
-            case eCSSType_ValueList:
-            case eCSSType_ValuePairList: {
-                void *copy;
-                NS_ASSERTION(PointerAtCursor(cursor), "oops");
-                switch (nsCSSProps::kTypeTable[iProp]) {
-                    default:
-                        NS_NOTREACHED("unreachable");
-                        // fall through to keep gcc's uninitialized
-                        // variable warning quiet
-                    case eCSSType_ValueList:
-                        copy = ValueListAtCursor(cursor)->Clone();
-                        break;
-                    case eCSSType_ValuePairList:
-                        copy = ValuePairListAtCursor(cursor)->Clone();
-                        break;
-                }
-                if (!copy) {
-                    // so the destructor knows where to stop clearing
-                    result->mBlockEnd = result_cursor;
-                    return nsnull;
-                }
-                PointerAtCursor(result_cursor) = copy;
-                cursor += CDBPointerStorage_advance;
-                result_cursor += CDBPointerStorage_advance;
-            } break;
-        }
+        const nsCSSValue* val = ValueAtCursor(cursor);
+        nsCSSValue *result_val = ValueAtCursor(result_cursor);
+        new (result_val) nsCSSValue(*val);
+        cursor += CDBValueStorage_advance;
+        result_cursor +=  CDBValueStorage_advance;
     }
-    NS_ASSERTION(cursor == cursor_end, "inconsistent data");
+    NS_ABORT_IF_FALSE(cursor == cursor_end, "inconsistent data");
 
     result->mBlockEnd = result_cursor;
     result->mStyleBits = mStyleBits;
-    NS_ASSERTION(result->DataSize() == DataSize(), "wrong size");
+    NS_ABORT_IF_FALSE(result->DataSize() == DataSize(), "wrong size");
 
     return result.forget();
 }
 
 nsCSSCompressedDataBlock::~nsCSSCompressedDataBlock()
 {
     const char* cursor = Block();
     const char* cursor_end = BlockEnd();
     while (cursor < cursor_end) {
         nsCSSProperty iProp = PropertyAtCursor(cursor);
-        NS_ASSERTION(0 <= iProp && iProp < eCSSProperty_COUNT_no_shorthands,
-                     "out of range");
-
-        switch (nsCSSProps::kTypeTable[iProp]) {
-            case eCSSType_Value: {
-                const nsCSSValue* val = ValueAtCursor(cursor);
-                NS_ASSERTION(val->GetUnit() != eCSSUnit_Null, "oops");
-                val->~nsCSSValue();
-                cursor += CDBValueStorage_advance;
-            } break;
-
-            case eCSSType_Rect: {
-                const nsCSSRect* val = RectAtCursor(cursor);
-                NS_ASSERTION(val->HasValue(), "oops");
-                val->~nsCSSRect();
-                cursor += CDBRectStorage_advance;
-            } break;
+        NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(iProp), "out of range");
 
-            case eCSSType_ValuePair: {
-                const nsCSSValuePair* val = ValuePairAtCursor(cursor);
-                NS_ASSERTION(val->mXValue.GetUnit() != eCSSUnit_Null ||
-                             val->mYValue.GetUnit() != eCSSUnit_Null, "oops");
-                val->~nsCSSValuePair();
-                cursor += CDBValuePairStorage_advance;
-            } break;
-
-            case eCSSType_ValueList: {
-                nsCSSValueList* val = ValueListAtCursor(cursor);
-                NS_ASSERTION(val, "oops");
-                delete val;
-                cursor += CDBPointerStorage_advance;
-            } break;
-
-            case eCSSType_ValuePairList: {
-                nsCSSValuePairList* val = ValuePairListAtCursor(cursor);
-                NS_ASSERTION(val, "oops");
-                delete val;
-                cursor += CDBPointerStorage_advance;
-            } break;
-        }
+        const nsCSSValue* val = ValueAtCursor(cursor);
+        NS_ABORT_IF_FALSE(val->GetUnit() != eCSSUnit_Null, "oops");
+        val->~nsCSSValue();
+        cursor += CDBValueStorage_advance;
     }
-    NS_ASSERTION(cursor == cursor_end, "inconsistent data");
+    NS_ABORT_IF_FALSE(cursor == cursor_end, "inconsistent data");
 }
 
 /* static */ nsCSSCompressedDataBlock*
 nsCSSCompressedDataBlock::CreateEmptyBlock()
 {
     nsCSSCompressedDataBlock *result = new(0) nsCSSCompressedDataBlock();
     result->mBlockEnd = result->Block();
     return result;
 }
 
-/* static */ void
-nsCSSCompressedDataBlock::MoveValue(void *aSource, void *aDest,
-                                    nsCSSProperty aPropID,
-                                    PRBool* aChanged)
-{
-  switch (nsCSSProps::kTypeTable[aPropID]) {
-    case eCSSType_Value: {
-      nsCSSValue *source = static_cast<nsCSSValue*>(aSource);
-      nsCSSValue *dest = static_cast<nsCSSValue*>(aDest);
-      if (*source != *dest)
-        *aChanged = PR_TRUE;
-      dest->~nsCSSValue();
-      memcpy(dest, source, sizeof(nsCSSValue));
-      new (source) nsCSSValue();
-    } break;
-
-    case eCSSType_Rect: {
-      nsCSSRect *source = static_cast<nsCSSRect*>(aSource);
-      nsCSSRect *dest = static_cast<nsCSSRect*>(aDest);
-      if (*source != *dest)
-        *aChanged = PR_TRUE;
-      dest->~nsCSSRect();
-      memcpy(dest, source, sizeof(nsCSSRect));
-      new (source) nsCSSRect();
-    } break;
-
-    case eCSSType_ValuePair: {
-      nsCSSValuePair *source = static_cast<nsCSSValuePair*>(aSource);
-      nsCSSValuePair *dest = static_cast<nsCSSValuePair*>(aDest);
-      if (*source != *dest)
-        *aChanged = PR_TRUE;
-      dest->~nsCSSValuePair();
-      memcpy(dest, source, sizeof(nsCSSValuePair));
-      new (source) nsCSSValuePair();
-    } break;
-
-    case eCSSType_ValueList: {
-      nsCSSValueList **source = static_cast<nsCSSValueList**>(aSource);
-      nsCSSValueList **dest = static_cast<nsCSSValueList**>(aDest);
-      if (**source != **dest)
-        *aChanged = PR_TRUE;
-      delete *dest;
-      *dest = *source;
-      *source = nsnull;
-    } break;
-
-    case eCSSType_ValuePairList: {
-      nsCSSValuePairList **source =
-        static_cast<nsCSSValuePairList**>(aSource);
-      nsCSSValuePairList **dest =
-        static_cast<nsCSSValuePairList**>(aDest);
-      if (**source != **dest)
-        *aChanged = PR_TRUE;
-      delete *dest;
-      *dest = *source;
-      *source = nsnull;
-    } break;
-  }
-}
-
 /*****************************************************************************/
 
 nsCSSExpandedDataBlock::nsCSSExpandedDataBlock()
 {
     AssertInitialState();
 }
 
 nsCSSExpandedDataBlock::~nsCSSExpandedDataBlock()
 {
     AssertInitialState();
 }
 
 const size_t
 nsCSSExpandedDataBlock::kOffsetTable[] = {
-    #define CSS_PROP(name_, id_, method_, flags_, datastruct_, member_, type_, \
+    #define CSS_PROP(name_, id_, method_, flags_, datastruct_, member_,        \
                      kwtable_, stylestruct_, stylestructoffset_, animtype_)    \
         offsetof(nsCSSExpandedDataBlock, m##datastruct_.member_),
     #include "nsCSSPropList.h"
     #undef CSS_PROP
 };
 
 void
 nsCSSExpandedDataBlock::DoExpand(nsCSSCompressedDataBlock *aBlock,
@@ -652,90 +350,46 @@ nsCSSExpandedDataBlock::DoExpand(nsCSSCo
     /*
      * Save needless copying and allocation by copying the memory
      * corresponding to the stored data in the compressed block.
      */
     const char* cursor = aBlock->Block();
     const char* cursor_end = aBlock->BlockEnd();
     while (cursor < cursor_end) {
         nsCSSProperty iProp = PropertyAtCursor(cursor);
-        NS_ASSERTION(0 <= iProp && iProp < eCSSProperty_COUNT_no_shorthands,
-                     "out of range");
-        NS_ASSERTION(!HasPropertyBit(iProp),
-                     "compressed block has property multiple times");
+        NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(iProp), "out of range");
+        NS_ABORT_IF_FALSE(!HasPropertyBit(iProp),
+                          "compressed block has property multiple times");
         SetPropertyBit(iProp);
         if (aImportant)
             SetImportantBit(iProp);
-        void *prop = PropertyAt(iProp);
 
-        switch (nsCSSProps::kTypeTable[iProp]) {
-            case eCSSType_Value: {
-                const nsCSSValue* val = ValueAtCursor(cursor);
-                nsCSSValue* dest = static_cast<nsCSSValue*>(prop);
-                NS_ASSERTION(val->GetUnit() != eCSSUnit_Null, "oops");
-                NS_ASSERTION(dest->GetUnit() == eCSSUnit_Null,
-                             "expanding into non-empty block");
+        const nsCSSValue* val = ValueAtCursor(cursor);
+        nsCSSValue* dest = PropertyAt(iProp);
+        NS_ABORT_IF_FALSE(val->GetUnit() != eCSSUnit_Null, "oops");
+        NS_ABORT_IF_FALSE(dest->GetUnit() == eCSSUnit_Null,
+                          "expanding into non-empty block");
 #ifdef NS_BUILD_REFCNT_LOGGING
-                dest->~nsCSSValue();
-#endif
-                memcpy(dest, val, sizeof(nsCSSValue));
-                cursor += CDBValueStorage_advance;
-            } break;
-
-            case eCSSType_Rect: {
-                const nsCSSRect* val = RectAtCursor(cursor);
-                nsCSSRect* dest = static_cast<nsCSSRect*>(prop);
-                NS_ASSERTION(val->HasValue(), "oops");
-                NS_ASSERTION(!dest->HasValue(),
-                             "expanding into non-empty block");
-#ifdef NS_BUILD_REFCNT_LOGGING
-                dest->~nsCSSRect();
+        dest->~nsCSSValue();
 #endif
-                memcpy(dest, val, sizeof(nsCSSRect));
-                cursor += CDBRectStorage_advance;
-            } break;
-
-            case eCSSType_ValuePair: {
-                const nsCSSValuePair* val = ValuePairAtCursor(cursor);
-                nsCSSValuePair* dest = static_cast<nsCSSValuePair*>(prop);
-                NS_ASSERTION(val->mXValue.GetUnit() != eCSSUnit_Null ||
-                             val->mYValue.GetUnit() != eCSSUnit_Null, "oops");
-                NS_ASSERTION(dest->mXValue.GetUnit() == eCSSUnit_Null &&
-                             dest->mYValue.GetUnit() == eCSSUnit_Null,
-                             "expanding into non-empty block");
-#ifdef NS_BUILD_REFCNT_LOGGING
-                dest->~nsCSSValuePair();
-#endif
-                memcpy(dest, val, sizeof(nsCSSValuePair));
-                cursor += CDBValuePairStorage_advance;
-            } break;
-
-            case eCSSType_ValueList:
-            case eCSSType_ValuePairList: {
-                void* val = PointerAtCursor(cursor);
-                void** dest = static_cast<void**>(prop);
-                NS_ASSERTION(val, "oops");
-                NS_ASSERTION(!*dest, "expanding into non-empty block");
-                *dest = val;
-                cursor += CDBPointerStorage_advance;
-            } break;
-        }
+        memcpy(dest, val, sizeof(nsCSSValue));
+        cursor += CDBValueStorage_advance;
     }
-    NS_ASSERTION(cursor == cursor_end, "inconsistent data");
+    NS_ABORT_IF_FALSE(cursor == cursor_end, "inconsistent data");
 
     // Don't destroy remnants of what we just copied
     aBlock->mBlockEnd = aBlock->Block();
     delete aBlock;
 }
 
 void
 nsCSSExpandedDataBlock::Expand(nsCSSCompressedDataBlock *aNormalBlock,
                                nsCSSCompressedDataBlock *aImportantBlock)
 {
-    NS_PRECONDITION(aNormalBlock, "unexpected null block");
+    NS_ABORT_IF_FALSE(aNormalBlock, "unexpected null block");
     AssertInitialState();
 
     DoExpand(aNormalBlock, PR_FALSE);
     if (aImportantBlock) {
         DoExpand(aImportantBlock, PR_TRUE);
     }
 }
 
@@ -745,189 +399,109 @@ nsCSSExpandedDataBlock::ComputeSize()
     ComputeSizeResult result = {0, 0};
     for (size_t iHigh = 0; iHigh < nsCSSPropertySet::kChunkCount; ++iHigh) {
         if (!mPropertiesSet.HasPropertyInChunk(iHigh))
             continue;
         for (size_t iLow = 0; iLow < nsCSSPropertySet::kBitsInChunk; ++iLow) {
             if (!mPropertiesSet.HasPropertyAt(iHigh, iLow))
                 continue;
             nsCSSProperty iProp = nsCSSPropertySet::CSSPropertyAt(iHigh, iLow);
-            NS_ASSERTION(0 <= iProp && iProp < eCSSProperty_COUNT_no_shorthands,
-                         "out of range");
-#ifdef DEBUG
-            void *prop = PropertyAt(iProp);
-#endif
-            PRUint32 increment = 0;
-            switch (nsCSSProps::kTypeTable[iProp]) {
-                case eCSSType_Value: {
-#ifdef DEBUG
-                    nsCSSValue* val = static_cast<nsCSSValue*>(prop);
-                    NS_ASSERTION(val->GetUnit() != eCSSUnit_Null,
-                                 "null value while computing size");
-#endif
-                    increment = CDBValueStorage_advance;
-                } break;
-
-                case eCSSType_Rect: {
-#ifdef DEBUG
-                    nsCSSRect* val = static_cast<nsCSSRect*>(prop);
-                    NS_ASSERTION(val->HasValue(),
-                                 "Valueless rect while computing size");
-#endif
-                    increment = CDBRectStorage_advance;
-                } break;
-
-                case eCSSType_ValuePair: {
-#ifdef DEBUG
-                    nsCSSValuePair* val = static_cast<nsCSSValuePair*>(prop);
-                    NS_ASSERTION(val->mXValue.GetUnit() != eCSSUnit_Null ||
-                                 val->mYValue.GetUnit() != eCSSUnit_Null,
-                                 "Valueless pair while computing size");
-#endif
-                    increment = CDBValuePairStorage_advance;
-                } break;
-
-                case eCSSType_ValueList:
-                case eCSSType_ValuePairList: {
-#ifdef DEBUG
-                    void* val = *static_cast<void**>(prop);
-                    NS_ASSERTION(val, "Null pointer while computing size");
-#endif
-                    increment = CDBPointerStorage_advance;
-                } break;
-            }
+            NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(iProp), "out of range");
+            NS_ABORT_IF_FALSE(PropertyAt(iProp)->GetUnit() != eCSSUnit_Null,
+                              "null value while computing size");
             if (mPropertiesImportant.HasPropertyAt(iHigh, iLow))
-                result.important += increment;
+                result.important += CDBValueStorage_advance;
             else
-                result.normal += increment;
+                result.normal += CDBValueStorage_advance;
         }
     }
     return result;
 }
 
 void
 nsCSSExpandedDataBlock::Compress(nsCSSCompressedDataBlock **aNormalBlock,
                                  nsCSSCompressedDataBlock **aImportantBlock)
 {
     nsAutoPtr<nsCSSCompressedDataBlock> result_normal, result_important;
     char *cursor_normal, *cursor_important;
 
     ComputeSizeResult size = ComputeSize();
 
     result_normal = new(size.normal) nsCSSCompressedDataBlock();
-    if (!result_normal) {
-        *aNormalBlock = nsnull;
-        *aImportantBlock = nsnull;
-        return;
-    }
     cursor_normal = result_normal->Block();
 
     if (size.important != 0) {
         result_important = new(size.important) nsCSSCompressedDataBlock();
-        if (!result_important) {
-            *aNormalBlock = nsnull;
-            *aImportantBlock = nsnull;
-            return;
-        }
         cursor_important = result_important->Block();
     } else {
         result_important = nsnull;
+        cursor_important = nsnull;
     }
 
     /*
      * Save needless copying and allocation by copying the memory
      * corresponding to the stored data in the expanded block, and then
      * clearing the data in the expanded block.
      */
     for (size_t iHigh = 0; iHigh < nsCSSPropertySet::kChunkCount; ++iHigh) {
         if (!mPropertiesSet.HasPropertyInChunk(iHigh))
             continue;
         for (size_t iLow = 0; iLow < nsCSSPropertySet::kBitsInChunk; ++iLow) {
             if (!mPropertiesSet.HasPropertyAt(iHigh, iLow))
                 continue;
             nsCSSProperty iProp = nsCSSPropertySet::CSSPropertyAt(iHigh, iLow);
-            NS_ASSERTION(0 <= iProp && iProp < eCSSProperty_COUNT_no_shorthands,
-                         "out of range");
-            void *prop = PropertyAt(iProp);
+            NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(iProp), "out of range");
             PRBool important =
                 mPropertiesImportant.HasPropertyAt(iHigh, iLow);
             char *&cursor = important ? cursor_important : cursor_normal;
             nsCSSCompressedDataBlock *result =
                 important ? result_important : result_normal;
-            switch (nsCSSProps::kTypeTable[iProp]) {
-                case eCSSType_Value: {
-                    nsCSSValue* val = static_cast<nsCSSValue*>(prop);
-                    NS_ASSERTION(val->GetUnit() != eCSSUnit_Null,
-                                 "Null value while compressing");
-                    CDBValueStorage *storage =
-                        reinterpret_cast<CDBValueStorage*>(cursor);
-                    storage->property = iProp;
-                    memcpy(&storage->value, val, sizeof(nsCSSValue));
-                    new (val) nsCSSValue();
-                    cursor += CDBValueStorage_advance;
-                } break;
-
-                case eCSSType_Rect: {
-                    nsCSSRect* val = static_cast<nsCSSRect*>(prop);
-                    NS_ASSERTION(val->HasValue(),
-                                 "Valueless rect while compressing");
-                    CDBRectStorage *storage =
-                        reinterpret_cast<CDBRectStorage*>(cursor);
-                    storage->property = iProp;
-                    memcpy(&storage->value, val, sizeof(nsCSSRect));
-                    new (val) nsCSSRect();
-                    cursor += CDBRectStorage_advance;
-                } break;
-
-                case eCSSType_ValuePair: {
-                    nsCSSValuePair* val = static_cast<nsCSSValuePair*>(prop);
-                    NS_ASSERTION(val->mXValue.GetUnit() != eCSSUnit_Null ||
-                                 val->mYValue.GetUnit() != eCSSUnit_Null,
-                                 "Valueless pair while compressing");
-                    CDBValuePairStorage *storage =
-                        reinterpret_cast<CDBValuePairStorage*>(cursor);
-                    storage->property = iProp;
-                    memcpy(&storage->value, val, sizeof(nsCSSValuePair));
-                    new (val) nsCSSValuePair();
-                    cursor += CDBValuePairStorage_advance;
-                } break;
-
-                case eCSSType_ValueList:
-                case eCSSType_ValuePairList: {
-                    void*& val = *static_cast<void**>(prop);
-                    NS_ASSERTION(val, "Null pointer while compressing");
-                    CDBPointerStorage *storage =
-                        reinterpret_cast<CDBPointerStorage*>(cursor);
-                    storage->property = iProp;
-                    storage->value = val;
-                    val = nsnull;
-                    cursor += CDBPointerStorage_advance;
-                } break;
-            }
+            nsCSSValue* val = PropertyAt(iProp);
+            NS_ABORT_IF_FALSE(val->GetUnit() != eCSSUnit_Null,
+                              "Null value while compressing");
+            CDBValueStorage *storage =
+                reinterpret_cast<CDBValueStorage*>(cursor);
+            storage->property = iProp;
+            memcpy(&storage->value, val, sizeof(nsCSSValue));
+            new (val) nsCSSValue();
+            cursor += CDBValueStorage_advance;
             result->mStyleBits |=
                 nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[iProp]);
         }
     }
 
     result_normal->mBlockEnd = cursor_normal;
-    NS_ASSERTION(result_normal->DataSize() == ptrdiff_t(size.normal),
-                 "size miscalculation");
+    NS_ABORT_IF_FALSE(result_normal->DataSize() == ptrdiff_t(size.normal),
+                      "size miscalculation");
+
     if (result_important) {
         result_important->mBlockEnd = cursor_important;
-        NS_ASSERTION(result_important->DataSize() == ptrdiff_t(size.important),
-                     "size miscalculation");
+        NS_ABORT_IF_FALSE(result_important->DataSize() ==
+                          ptrdiff_t(size.important),
+                          "size miscalculation");
     }
 
     ClearSets();
     AssertInitialState();
     *aNormalBlock = result_normal.forget();
     *aImportantBlock = result_important.forget();
 }
 
 void
+nsCSSExpandedDataBlock::AddLonghandProperty(nsCSSProperty aProperty,
+                                            const nsCSSValue& aValue)
+{
+    NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(aProperty),
+                      "property out of range");
+    nsCSSValue& storage = *static_cast<nsCSSValue*>(PropertyAt(aProperty));
+    storage = aValue;
+    SetPropertyBit(aProperty);
+}
+
+void
 nsCSSExpandedDataBlock::Clear()
 {
     for (size_t iHigh = 0; iHigh < nsCSSPropertySet::kChunkCount; ++iHigh) {
         if (!mPropertiesSet.HasPropertyInChunk(iHigh))
             continue;
         for (size_t iLow = 0; iLow < nsCSSPropertySet::kBitsInChunk; ++iLow) {
             if (!mPropertiesSet.HasPropertyAt(iHigh, iLow))
                 continue;
@@ -949,169 +523,97 @@ nsCSSExpandedDataBlock::ClearProperty(ns
   } else {
     ClearLonghandProperty(aPropID);
   }
 }
 
 void
 nsCSSExpandedDataBlock::ClearLonghandProperty(nsCSSProperty aPropID)
 {
-    NS_ABORT_IF_FALSE(0 <= aPropID &&
-                      aPropID < eCSSProperty_COUNT_no_shorthands,
-                      "out of range");
+    NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(aPropID), "out of range");
 
     ClearPropertyBit(aPropID);
     ClearImportantBit(aPropID);
-
-    void *prop = PropertyAt(aPropID);
-    switch (nsCSSProps::kTypeTable[aPropID]) {
-        case eCSSType_Value: {
-            nsCSSValue* val = static_cast<nsCSSValue*>(prop);
-            val->Reset();
-        } break;
-
-        case eCSSType_Rect: {
-            nsCSSRect* val = static_cast<nsCSSRect*>(prop);
-            val->Reset();
-        } break;
-
-        case eCSSType_ValuePair: {
-            nsCSSValuePair* val = static_cast<nsCSSValuePair*>(prop);
-            val->mXValue.Reset();
-            val->mYValue.Reset();
-        } break;
-
-        case eCSSType_ValueList: {
-            nsCSSValueList*& val = *static_cast<nsCSSValueList**>(prop);
-            if (val) {
-                delete val;
-                val = nsnull;
-            }
-        } break;
-
-        case eCSSType_ValuePairList: {
-            nsCSSValuePairList*& val =
-              *static_cast<nsCSSValuePairList**>(prop);
-            if (val) {
-                delete val;
-                val = nsnull;
-            }
-        } break;
-    }
+    PropertyAt(aPropID)->Reset();
 }
 
-void
+PRBool
 nsCSSExpandedDataBlock::TransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
                                           nsCSSProperty aPropID,
                                           PRBool aIsImportant,
                                           PRBool aOverrideImportant,
                                           PRBool aMustCallValueAppended,
-                                          css::Declaration* aDeclaration,
-                                          PRBool* aChanged)
+                                          css::Declaration* aDeclaration)
 {
-  if (nsCSSProps::IsShorthand(aPropID)) {
+    if (!nsCSSProps::IsShorthand(aPropID)) {
+        return DoTransferFromBlock(aFromBlock, aPropID,
+                                   aIsImportant, aOverrideImportant,
+                                   aMustCallValueAppended, aDeclaration);
+    }
+
+    PRBool changed = PR_FALSE;
     CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aPropID) {
-      DoTransferFromBlock(aFromBlock, *p, aIsImportant, aOverrideImportant,
-                          aMustCallValueAppended, aDeclaration, aChanged);
+        changed |= DoTransferFromBlock(aFromBlock, *p,
+                                       aIsImportant, aOverrideImportant,
+                                       aMustCallValueAppended, aDeclaration);
     }
-  } else {
-    DoTransferFromBlock(aFromBlock, aPropID, aIsImportant, aOverrideImportant,
-                        aMustCallValueAppended, aDeclaration, aChanged);
-  }
+    return changed;
 }
 
-void
+PRBool
 nsCSSExpandedDataBlock::DoTransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
                                             nsCSSProperty aPropID,
                                             PRBool aIsImportant,
                                             PRBool aOverrideImportant,
                                             PRBool aMustCallValueAppended,
-                                            css::Declaration* aDeclaration,
-                                            PRBool* aChanged)
+                                            css::Declaration* aDeclaration)
 {
-  NS_ASSERTION(aFromBlock.HasPropertyBit(aPropID), "oops");
+  PRBool changed = PR_FALSE;
+  NS_ABORT_IF_FALSE(aFromBlock.HasPropertyBit(aPropID), "oops");
   if (aIsImportant) {
     if (!HasImportantBit(aPropID))
-      *aChanged = PR_TRUE;
+      changed = PR_TRUE;
     SetImportantBit(aPropID);
   } else {
     if (HasImportantBit(aPropID)) {
       // When parsing a declaration block, an !important declaration
       // is not overwritten by an ordinary declaration of the same
       // property later in the block.  However, CSSOM manipulations
       // come through here too, and in that case we do want to
       // overwrite the property.
       if (!aOverrideImportant) {
         aFromBlock.ClearLonghandProperty(aPropID);
-        return;
+        return PR_FALSE;
       }
-      *aChanged = PR_TRUE;
+      changed = PR_TRUE;
       ClearImportantBit(aPropID);
     }
   }
 
   if (aMustCallValueAppended || !HasPropertyBit(aPropID)) {
     aDeclaration->ValueAppended(aPropID);
   }
 
   SetPropertyBit(aPropID);
   aFromBlock.ClearPropertyBit(aPropID);
 
   /*
    * Save needless copying and allocation by calling the destructor in
    * the destination, copying memory directly, and then using placement
    * new.
    */
-  void *v_source = aFromBlock.PropertyAt(aPropID);
-  void *v_dest = PropertyAt(aPropID);
-  nsCSSCompressedDataBlock::MoveValue(v_source, v_dest, aPropID, aChanged);
+  changed |= MoveValue(aFromBlock.PropertyAt(aPropID), PropertyAt(aPropID));
+  return changed;
 }
 
 #ifdef DEBUG
 void
 nsCSSExpandedDataBlock::DoAssertInitialState()
 {
     mPropertiesSet.AssertIsEmpty("not initial state");
     mPropertiesImportant.AssertIsEmpty("not initial state");
 
     for (PRUint32 i = 0; i < eCSSProperty_COUNT_no_shorthands; ++i) {
-        void *prop = PropertyAt(nsCSSProperty(i));
-        switch (nsCSSProps::kTypeTable[i]) {
-            case eCSSType_Value: {
-                nsCSSValue* val = static_cast<nsCSSValue*>(prop);
-                NS_ASSERTION(val->GetUnit() == eCSSUnit_Null,
-                             "not initial state");
-            } break;
-
-            case eCSSType_Rect: {
-                nsCSSRect* val = static_cast<nsCSSRect*>(prop);
-                NS_ASSERTION(val->mTop.GetUnit() == eCSSUnit_Null,
-                             "not initial state");
-                NS_ASSERTION(val->mRight.GetUnit() == eCSSUnit_Null,
-                             "not initial state");
-                NS_ASSERTION(val->mBottom.GetUnit() == eCSSUnit_Null,
-                             "not initial state");
-                NS_ASSERTION(val->mLeft.GetUnit() == eCSSUnit_Null,
-                             "not initial state");
-            } break;
-
-            case eCSSType_ValuePair: {
-                nsCSSValuePair* val = static_cast<nsCSSValuePair*>(prop);
-                NS_ASSERTION(val->mXValue.GetUnit() == eCSSUnit_Null,
-                             "not initial state");
-                NS_ASSERTION(val->mYValue.GetUnit() == eCSSUnit_Null,
-                             "not initial state");
-            } break;
-
-            case eCSSType_ValueList: {
-                nsCSSValueList* val = *static_cast<nsCSSValueList**>(prop);
-                NS_ASSERTION(val == nsnull, "not initial state");
-            } break;
-
-            case eCSSType_ValuePairList: {
-                nsCSSValuePairList* val =
-                  *static_cast<nsCSSValuePairList**>(prop);
-                NS_ASSERTION(val == nsnull, "not initial state");
-            } break;
-        }
+        NS_ABORT_IF_FALSE(PropertyAt(nsCSSProperty(i))->GetUnit() ==
+                          eCSSUnit_Null, "not initial state");
     }
 }
 #endif
--- a/layout/style/nsCSSDataBlock.h
+++ b/layout/style/nsCSSDataBlock.h
@@ -77,91 +77,46 @@ public:
      * Do what |nsIStyleRule::MapRuleInfoInto| needs to do for a style
      * rule using this block for storage.
      */
     void MapRuleInfoInto(nsRuleData *aRuleData) const;
 
     /**
      * Return the location at which the *value* for the property is
      * stored, or null if the block does not contain a value for the
-     * property.  This is either an |nsCSSValue*|, |nsCSSRect*|, or an
-     * |nsCSSValueList**|, etc.
+     * property.
      *
      * Inefficient (by design).
      *
      * Must not be called for shorthands.
      */
-    const void* StorageFor(nsCSSProperty aProperty) const;
-
-    /**
-     * As above, but provides mutable access to a value slot.
-     */
-    void* SlotForValue(nsCSSProperty aProperty) {
-      return const_cast<void*>(StorageFor(aProperty));
-    }
+    const nsCSSValue* ValueFor(nsCSSProperty aProperty) const;
 
     /**
-     * A set of slightly more typesafe helpers for the above.  All
-     * return null if the value is not present.
+     * Attempt to replace the value for |aProperty| stored in this block
+     * with the matching value stored in |aFromBlock|.
+     * This method will fail (returning PR_FALSE) if |aProperty| is not
+     * already in this block.  It will set |aChanged| to true if it
+     * actually made a change to the block, but regardless, if it
+     * returns PR_TRUE, the value in |aFromBlock| was erased.
      */
-    const nsCSSValue* ValueStorageFor(nsCSSProperty aProperty) const {
-      NS_ABORT_IF_FALSE(nsCSSProps::kTypeTable[aProperty] == eCSSType_Value,
-                        "type mismatch");
-      return static_cast<const nsCSSValue*>(StorageFor(aProperty));
-    }
-    const nsCSSRect* RectStorageFor(nsCSSProperty aProperty) const {
-      NS_ABORT_IF_FALSE(nsCSSProps::kTypeTable[aProperty] == eCSSType_Rect,
-                        "type mismatch");
-      return static_cast<const nsCSSRect*>(StorageFor(aProperty));
-    }
-    const nsCSSValuePair* ValuePairStorageFor(nsCSSProperty aProperty) const {
-      NS_ABORT_IF_FALSE(nsCSSProps::kTypeTable[aProperty] ==
-                          eCSSType_ValuePair,
-                        "type mismatch");
-      return static_cast<const nsCSSValuePair*>(StorageFor(aProperty));
-    }
-    const nsCSSValueList*const*
-    ValueListStorageFor(nsCSSProperty aProperty) const {
-      NS_ABORT_IF_FALSE(nsCSSProps::kTypeTable[aProperty] ==
-                          eCSSType_ValueList,
-                        "type mismatch");
-      return static_cast<const nsCSSValueList*const*>(StorageFor(aProperty));
-    }
-    const nsCSSValuePairList*const*
-    ValuePairListStorageFor(nsCSSProperty aProperty) const {
-      NS_ABORT_IF_FALSE(nsCSSProps::kTypeTable[aProperty] ==
-                          eCSSType_ValuePairList,
-                        "type mismatch");
-      return static_cast<const nsCSSValuePairList*const*>(
-               StorageFor(aProperty));
-    }
+    PRBool TryReplaceValue(nsCSSProperty aProperty,
+                           nsCSSExpandedDataBlock& aFromBlock,
+                           PRBool* aChanged);
 
     /**
      * Clone this block, or return null on out-of-memory.
      */
     nsCSSCompressedDataBlock* Clone() const;
 
     /**
      * Create a new nsCSSCompressedDataBlock holding no declarations.
      */
     static nsCSSCompressedDataBlock* CreateEmptyBlock();
 
-    /**
-     * Does a fast move of aSource to aDest.  The previous value in
-     * aDest is cleanly destroyed, and aSource is cleared.  *aChanged
-     * is set true if, before the copy, the value at aSource compares
-     * unequal to the value at aDest.
-     *
-     * This can only be used for non-shorthand properties.  The caller
-     * must make sure that the source and destination locations point
-     * to the right kind of objects for the property id.
-     */
-    static void MoveValue(void *aSource, void *aDest, nsCSSProperty aPropID,
-                          PRBool* aChanged);
-
 private:
     PRInt32 mStyleBits; // the structs for which we have data, according to
                         // |nsCachedStyleData::GetBitForSID|.
 
     enum { block_chars = 4 }; // put 4 chars in the definition of the class
                               // to ensure size not inflated by alignment
 
     void* operator new(size_t aBaseSize, size_t aDataSize) {
@@ -181,22 +136,25 @@ private:
     char* Block() { return mBlock_; }
     char* BlockEnd() { return mBlockEnd; }
     const char* Block() const { return mBlock_; }
     const char* BlockEnd() const { return mBlockEnd; }
     ptrdiff_t DataSize() const { return BlockEnd() - Block(); }
 };
 
 class nsCSSExpandedDataBlock {
+    friend class nsCSSCompressedDataBlock;
+
 public:
     nsCSSExpandedDataBlock();
     ~nsCSSExpandedDataBlock();
-    /*
-     * When setting properties in an |nsCSSExpandedDataBlock|, callers
-     * must make the appropriate |AddPropertyBit| call.
+
+private:
+    /* Property storage may not be accessed directly; use AddLonghandProperty
+     * and friends.
      */
 
     nsCSSFont mFont;
     nsCSSDisplay mDisplay;
     nsCSSMargin mMargin;
     nsCSSList mList;
     nsCSSPosition mPosition;
     nsCSSTable mTable;
@@ -206,37 +164,47 @@ public:
     nsCSSUserInterface mUserInterface;
     nsCSSAural mAural;
     nsCSSPage mPage;
     nsCSSBreaks mBreaks;
     nsCSSXUL mXUL;
     nsCSSSVG mSVG;
     nsCSSColumn mColumn;
 
+public:
     /**
      * Transfer all of the state from a pair of compressed data blocks
      * to this expanded block.  This expanded block must be clear
      * beforehand.
      *
      * This method DELETES both of the compressed data blocks it is
      * passed.  (This is necessary because ownership of sub-objects
      * is transferred to the expanded block.)
      */
     void Expand(nsCSSCompressedDataBlock *aNormalBlock,
                 nsCSSCompressedDataBlock *aImportantBlock);
 
     /**
-     * Allocate a new compressed block and transfer all of the state
-     * from this expanded block to the new compressed block, clearing
-     * the state of this expanded block.
+     * Allocate new compressed blocks and transfer all of the state
+     * from this expanded block to the new blocks, clearing this
+     * expanded block.  A normal block will always be allocated, but
+     * an important block will only be allocated if there are
+     * !important properties in the expanded block; otherwise
+     * |*aImportantBlock| will be set to null.
      */
     void Compress(nsCSSCompressedDataBlock **aNormalBlock,
                   nsCSSCompressedDataBlock **aImportantBlock);
 
     /**
+     * Copy a value into this expanded block.  This does NOT destroy
+     * the source value object.  |aProperty| cannot be a shorthand.
+     */
+    void AddLonghandProperty(nsCSSProperty aProperty, const nsCSSValue& aValue);
+
+    /**
      * Clear the state of this expanded block.
      */
     void Clear();
 
     /**
      * Clear the data for the given property (including the set and
      * important bits).  Can be used with shorthand properties.
      */
@@ -249,28 +217,26 @@ public:
 
     /**
      * Transfer the state for |aPropID| (which may be a shorthand)
      * from |aFromBlock| to this block.  The property being transferred
      * is !important if |aIsImportant| is true, and should replace an
      * existing !important property regardless of its own importance
      * if |aOverrideImportant| is true.
      *
-     * Sets |*aChanged| to true if something changed, leaves it
-     * unmodified otherwise.  Calls |ValueAppended| on |aDeclaration|
-     * if the property was not previously set, or in any case if
-     * |aMustCallValueAppended| is true.
+     * Returns true if something changed, false otherwise.  Calls
+     * |ValueAppended| on |aDeclaration| if the property was not
+     * previously set, or in any case if |aMustCallValueAppended| is true.
      */
-    void TransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
-                           nsCSSProperty aPropID,
-                           PRBool aIsImportant,
-                           PRBool aOverrideImportant,
-                           PRBool aMustCallValueAppended,
-                           mozilla::css::Declaration* aDeclaration,
-                           PRBool* aChanged);
+    PRBool TransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
+                             nsCSSProperty aPropID,
+                             PRBool aIsImportant,
+                             PRBool aOverrideImportant,
+                             PRBool aMustCallValueAppended,
+                             mozilla::css::Declaration* aDeclaration);
 
     void AssertInitialState() {
 #ifdef DEBUG
         DoAssertInitialState();
 #endif
     }
 
 private:
@@ -283,23 +249,22 @@ private:
     };
     ComputeSizeResult ComputeSize();
 
     void DoExpand(nsCSSCompressedDataBlock *aBlock, PRBool aImportant);
 
     /**
      * Worker for TransferFromBlock; cannot be used with shorthands.
      */
-    void DoTransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
-                             nsCSSProperty aPropID,
-                             PRBool aIsImportant,
-                             PRBool aOverrideImportant,
-                             PRBool aMustCallValueAppended,
-                             mozilla::css::Declaration* aDeclaration,
-                             PRBool* aChanged);
+    PRBool DoTransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
+                               nsCSSProperty aPropID,
+                               PRBool aIsImportant,
+                               PRBool aOverrideImportant,
+                               PRBool aMustCallValueAppended,
+                               mozilla::css::Declaration* aDeclaration);
 
 #ifdef DEBUG
     void DoAssertInitialState();
 #endif
 
     // XXX These could probably be pointer-to-member, if the casting can
     // be done correctly.
     static const size_t kOffsetTable[];
@@ -311,25 +276,24 @@ private:
      * property is set in this block.
      */
     nsCSSPropertySet mPropertiesSet;
     /*
      * mPropertiesImportant indicates which properties are '!important'.
      */
     nsCSSPropertySet mPropertiesImportant;
 
-public:
     /*
      * Return the storage location within |this| of the value of the
-     * property (i.e., either an |nsCSSValue*|, |nsCSSRect*|, or
-     * |nsCSSValueList**| (etc.).
+     * property |aProperty|.
      */
-    void* PropertyAt(nsCSSProperty aProperty) {
+    nsCSSValue* PropertyAt(nsCSSProperty aProperty) {
         size_t offset = nsCSSExpandedDataBlock::kOffsetTable[aProperty];
-        return reinterpret_cast<void*>(reinterpret_cast<char*>(this) + offset);
+        return reinterpret_cast<nsCSSValue*>(reinterpret_cast<char*>(this) +
+                                             offset);
     }
 
     void SetPropertyBit(nsCSSProperty aProperty) {
         mPropertiesSet.AddProperty(aProperty);
     }
 
     void ClearPropertyBit(nsCSSProperty aProperty) {
         mPropertiesSet.RemoveProperty(aProperty);
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -151,16 +151,17 @@ namespace css = mozilla::css;
 #define VARIANT_HUO  (VARIANT_INHERIT | VARIANT_URL | VARIANT_NONE)
 #define VARIANT_AHUO (VARIANT_AUTO | VARIANT_HUO)
 #define VARIANT_HPN  (VARIANT_INHERIT | VARIANT_PERCENT | VARIANT_NUMBER)
 #define VARIANT_HN   (VARIANT_INHERIT | VARIANT_NUMBER)
 #define VARIANT_HON  (VARIANT_HN | VARIANT_NONE)
 #define VARIANT_HOS  (VARIANT_INHERIT | VARIANT_NONE | VARIANT_STRING)
 #define VARIANT_TIMING_FUNCTION (VARIANT_KEYWORD | VARIANT_CUBIC_BEZIER)
 #define VARIANT_UK   (VARIANT_URL | VARIANT_KEYWORD)
+#define VARIANT_UO   (VARIANT_URL | VARIANT_NONE)
 #define VARIANT_ANGLE_OR_ZERO (VARIANT_ANGLE | VARIANT_ZERO_ANGLE)
 #define VARIANT_TRANSFORM_LPCALC (VARIANT_LP | VARIANT_CALC | \
                                   VARIANT_CALC_NO_MIN_MAX)
 #define VARIANT_IMAGE (VARIANT_URL | VARIANT_NONE | VARIANT_GRADIENT | \
                        VARIANT_IMAGE_RECT | VARIANT_ELEMENT)
 
 //----------------------------------------------------------------------
 
@@ -425,45 +426,36 @@ protected:
 #endif
 
   void InitBoxPropsAsPhysical(const nsCSSProperty *aSourceProperties);
 
   // Property specific parsing routines
   PRBool ParseAzimuth(nsCSSValue& aValue);
   PRBool ParseBackground();
 
-  struct BackgroundItem;
-  friend struct BackgroundItem;
-  struct BackgroundItem {
-    nsCSSValue mImage;
-    nsCSSValue mRepeat;
-    nsCSSValue mAttachment;
-    nsCSSValuePair mPosition;
-    nsCSSValue mClip;
-    nsCSSValue mOrigin;
-    nsCSSValuePair mSize;
-    // The background-color is set as a side-effect, and if so, mLastItem
-    // is set to true.
-    PRBool mLastItem;
+  struct BackgroundParseState {
+    nsCSSValue&  mColor;
+    nsCSSValueList* mImage;
+    nsCSSValueList* mRepeat;
+    nsCSSValueList* mAttachment;
+    nsCSSValueList* mClip;
+    nsCSSValueList* mOrigin;
+    nsCSSValuePairList* mPosition;
+    nsCSSValuePairList* mSize;
   };
-  struct BackgroundItemSimpleValueInfo {
-    nsCSSValue BackgroundItem::*member;
-    nsCSSProperty propID;
-  };
-
-  PRBool ParseBackgroundItem(BackgroundItem& aItem, PRBool aFirstItem);
+
+  PRBool ParseBackgroundItem(BackgroundParseState& aState);
 
   PRBool ParseBackgroundList(nsCSSProperty aPropID); // a single value prop-id
   PRBool ParseBackgroundPosition();
   PRBool ParseBoxPositionValues(nsCSSValuePair& aOut, PRBool aAcceptsInherit);
   PRBool ParseBackgroundSize();
   PRBool ParseBackgroundSizeValues(nsCSSValuePair& aOut);
   PRBool ParseBorderColor();
-  PRBool ParseBorderColors(nsCSSValueList** aResult,
-                           nsCSSProperty aProperty);
+  PRBool ParseBorderColors(nsCSSProperty aProperty);
   PRBool ParseBorderImage();
   PRBool ParseBorderSpacing();
   PRBool ParseBorderSide(const nsCSSProperty aPropIDs[],
                          PRBool aSetAllSides);
   PRBool ParseDirectionalBorderSide(const nsCSSProperty aPropIDs[],
                                     PRInt32 aSourceType);
   PRBool ParseBorderStyle();
   PRBool ParseBorderWidth();
@@ -475,22 +467,19 @@ protected:
                                            PRInt32& aVariantMask,
                                            PRBool *aHadFinalWS);
   PRBool ParseCalcTerm(nsCSSValue& aValue, PRInt32& aVariantMask);
   PRBool ParseCalcMinMax(nsCSSValue& aValue, nsCSSUnit aUnit,
                          PRInt32& aVariantMask);
   PRBool RequireWhitespace();
 
   // for 'clip' and '-moz-image-region'
-  PRBool ParseRect(nsCSSRect& aRect,
-                   nsCSSProperty aPropID);
-  PRBool DoParseRect(nsCSSRect& aRect);
+  PRBool ParseRect(nsCSSProperty aPropID);
   PRBool ParseContent();
-  PRBool ParseCounterData(nsCSSValuePairList** aResult,
-                          nsCSSProperty aPropID);
+  PRBool ParseCounterData(nsCSSProperty aPropID);
   PRBool ParseCue();
   PRBool ParseCursor();
   PRBool ParseFont();
   PRBool ParseFontWeight(nsCSSValue& aValue);
   PRBool ParseOneFamily(nsAString& aValue);
   PRBool ParseFamily(nsCSSValue& aValue);
   PRBool ParseFontSrc(nsCSSValue& aValue);
   PRBool ParseFontSrcFormat(nsTArray<nsCSSValue>& values);
@@ -502,46 +491,40 @@ protected:
   PRBool ParseOutline();
   PRBool ParseOverflow();
   PRBool ParsePadding();
   PRBool ParsePause();
   PRBool ParseQuotes();
   PRBool ParseSize();
   PRBool ParseTextDecoration(nsCSSValue& aValue);
 
-  nsCSSValueList* ParseCSSShadowList(PRBool aIsBoxShadow);
-  PRBool ParseTextShadow();
-  PRBool ParseBoxShadow();
+  PRBool ParseShadowItem(nsCSSValue& aValue, PRBool aIsBoxShadow);
+  PRBool ParseShadowList(nsCSSProperty aProperty);
   PRBool ParseTransitionTime(nsCSSProperty aPropID);
   PRBool ParseTransitionProperty();
   PRBool ParseTransition();
   PRBool ParseTransitionTimingFunction();
   PRBool ParseTransitionTimingFunctionValues(nsCSSValue& aValue);
   PRBool ParseTransitionTimingFunctionValueComponent(float& aComponent,
                                                      char aStop,
                                                      PRBool aCheckRange);
-  PRBool AppendValueToList(nsCSSValueList**& aListTail,
-                           const nsCSSValue& aValue);
 
 #ifdef MOZ_SVG
-  PRBool ParsePaint(nsCSSValuePair* aResult,
-                    nsCSSProperty aPropID);
+  PRBool ParsePaint(nsCSSProperty aPropID);
   PRBool ParseDasharray();
   PRBool ParseMarker();
 #endif
 
   // Reused utility parsing routines
   void AppendValue(nsCSSProperty aPropID, const nsCSSValue& aValue);
-  PRBool ParseBoxProperties(nsCSSRect& aResult,
-                            const nsCSSProperty aPropIDs[]);
+  PRBool ParseBoxProperties(const nsCSSProperty aPropIDs[]);
   PRBool ParseDirectionalBoxProperty(nsCSSProperty aProperty,
                                      PRInt32 aSourceType);
   PRBool ParseBoxCornerRadius(const nsCSSProperty aPropID);
-  PRBool ParseBoxCornerRadii(nsCSSCornerSizes& aRadii,
-                             const nsCSSProperty aPropIDs[]);
+  PRBool ParseBoxCornerRadii(const nsCSSProperty aPropIDs[]);
   PRInt32 ParseChoice(nsCSSValue aValues[],
                       const nsCSSProperty aPropIDs[], PRInt32 aNumIDs);
   PRBool ParseColor(nsCSSValue& aValue);
   PRBool ParseColorComponent(PRUint8& aComponent,
                              PRInt32& aType, char aStop);
   // ParseHSLColor parses everything starting with the opening '('
   // up through and including the aStop char.
   PRBool ParseHSLColor(nscolor& aColor, char aStop);
@@ -574,17 +557,17 @@ protected:
     NS_ASSERTION(aBool == PR_TRUE || aBool == PR_FALSE, "bad PRBool value");
     mParsingCompoundProperty = aBool;
   }
   PRBool IsParsingCompoundProperty(void) const {
     return mParsingCompoundProperty;
   }
 
   /* Functions for -moz-transform Parsing */
-  PRBool ReadSingleTransform(nsCSSValueList**& aTail);
+  PRBool ParseSingleTransform(nsCSSValue& aValue);
   PRBool ParseFunction(const nsString &aFunction, const PRInt32 aAllowedTypes[],
                        PRUint16 aMinElems, PRUint16 aMaxElems,
                        nsCSSValue &aValue);
   PRBool ParseFunctionInternals(const PRInt32 aVariantMask[],
                                 PRUint16 aMinElems,
                                 PRUint16 aMaxElems,
                                 nsTArray<nsCSSValue>& aOutput);
 
@@ -1134,25 +1117,22 @@ CSSParserImpl::ParseProperty(const nsCSS
   } else {
 
     // We know we don't need to force a ValueAppended call for the new
     // value.  So if we are not processing a shorthand, and there's
     // already a value for this property in the declaration at the
     // same importance level, then we can just copy our parsed value
     // directly into the declaration without going through the whole
     // expand/compress thing.
-    void* valueSlot = aDeclaration->SlotForValue(aPropID, aIsImportant);
-    if (valueSlot) {
-      nsCSSCompressedDataBlock::MoveValue(mTempData.PropertyAt(aPropID),
-                                          valueSlot, aPropID, aChanged);
-      mTempData.ClearPropertyBit(aPropID);
-    } else {
+    if (!aDeclaration->TryReplaceValue(aPropID, aIsImportant, mTempData,
+                                       aChanged)) {
+      // Do it the slow way
       aDeclaration->ExpandTo(&mData);
-      mData.TransferFromBlock(mTempData, aPropID, aIsImportant, PR_TRUE,
-                              PR_FALSE, aDeclaration, aChanged);
+      *aChanged = mData.TransferFromBlock(mTempData, aPropID, aIsImportant,
+                                          PR_TRUE, PR_FALSE, aDeclaration);
       aDeclaration->CompressFrom(&mData);
     }
     CLEAR_ERROR();
   }
 
   mTempData.AssertInitialState();
 
   nsresult result = mScanner.GetLowLevelError();
@@ -4041,19 +4021,20 @@ CSSParserImpl::ParseDeclaration(css::Dec
     }
     REPORT_UNEXPECTED(PEDeclDropped);
     OUTPUT_ERROR();
     mTempData.ClearProperty(propID);
     mTempData.AssertInitialState();
     return PR_FALSE;
   }
 
-  mData.TransferFromBlock(mTempData, propID, status == ePriority_Important,
-                          PR_FALSE, aMustCallValueAppended,
-                          aDeclaration, aChanged);
+  *aChanged |= mData.TransferFromBlock(mTempData, propID,
+                                       status == ePriority_Important,
+                                       PR_FALSE, aMustCallValueAppended,
+                                       aDeclaration);
   return PR_TRUE;
 }
 
 static const nsCSSProperty kBorderTopIDs[] = {
   eCSSProperty_border_top_width,
   eCSSProperty_border_top_style,
   eCSSProperty_border_top_color
 };
@@ -4879,24 +4860,17 @@ CSSParserImpl::ParseGradient(nsCSSValue&
   }
 
   if (haveGradientLine) {
     PRBool haveAngle =
       ParseVariant(cssGradient->mAngle, VARIANT_ANGLE, nsnull);
 
     // if we got an angle, we might now have a comma, ending the gradient-line
     if (!haveAngle || !ExpectSymbol(',', PR_TRUE)) {
-      // This intermediate is necessary because nsCSSValueGradient cannot
-      // contain a nsCSSValuePair (because the latter type is defined in
-      // nsCSSStruct.h rather than nsCSSValue.h).
-      nsCSSValuePair bgPos;
-      if (ParseBoxPositionValues(bgPos, PR_FALSE)) {
-        cssGradient->mBgPosX = bgPos.mXValue;
-        cssGradient->mBgPosY = bgPos.mYValue;
-      } else {
+      if (!ParseBoxPositionValues(cssGradient->mBgPos, PR_FALSE)) {
         SkipUntil(')');
         return PR_FALSE;
       }
 
       if (!ExpectSymbol(',', PR_TRUE) &&
           // if we didn't already get an angle, we might have one now,
           // otherwise it's an error
           (haveAngle ||
@@ -5012,35 +4986,26 @@ CSSParserImpl::ParseChoice(nsCSSValue aV
     }
   }
   return found;
 }
 
 void
 CSSParserImpl::AppendValue(nsCSSProperty aPropID, const nsCSSValue& aValue)
 {
-  NS_ASSERTION(0 <= aPropID && aPropID < eCSSProperty_COUNT_no_shorthands,
-               "property out of range");
-  NS_ASSERTION(nsCSSProps::kTypeTable[aPropID] == eCSSType_Value,
-               nsPrintfCString(64, "type error (property=\'%s\')",
-                             nsCSSProps::GetStringValue(aPropID).get()).get());
-  nsCSSValue& storage =
-      *static_cast<nsCSSValue*>(mTempData.PropertyAt(aPropID));
-  storage = aValue;
-  mTempData.SetPropertyBit(aPropID);
+  mTempData.AddLonghandProperty(aPropID, aValue);
 }
 
 /**
  * Parse a "box" property. Box properties have 1 to 4 values. When less
  * than 4 values are provided a standard mapping is used to replicate
  * existing values.
  */
 PRBool
-CSSParserImpl::ParseBoxProperties(nsCSSRect& aResult,
-                                  const nsCSSProperty aPropIDs[])
+CSSParserImpl::ParseBoxProperties(const nsCSSProperty aPropIDs[])
 {
   // Get up to four values for the property
   PRInt32 count = 0;
   nsCSSRect result;
   NS_FOR_CSS_SIDES (index) {
     if (! ParseSingleValueProperty(result.*(nsCSSRect::sides[index]),
                                    aPropIDs[index])) {
       break;
@@ -5066,19 +5031,18 @@ CSSParserImpl::ParseBoxProperties(nsCSSR
       result.mRight = result.mTop;
     case 2: // Make bottom == top
       result.mBottom = result.mTop;
     case 3: // Make left == right
       result.mLeft = result.mRight;
   }
 
   NS_FOR_CSS_SIDES (index) {
-    mTempData.SetPropertyBit(aPropIDs[index]);
-  }
-  aResult = result;
+    AppendValue(aPropIDs[index], result.*(nsCSSRect::sides[index]));
+  }
   return PR_TRUE;
 }
 
 PRBool
 CSSParserImpl::ParseDirectionalBoxProperty(nsCSSProperty aProperty,
                                            PRInt32 aSourceType)
 {
   const nsCSSProperty* subprops = nsCSSProps::SubpropertyEntryFor(aProperty);
@@ -5098,37 +5062,35 @@ CSSParserImpl::ParseDirectionalBoxProper
 
 PRBool
 CSSParserImpl::ParseBoxCornerRadius(nsCSSProperty aPropID)
 {
   nsCSSValue dimenX, dimenY;
   // required first value
   if (! ParseNonNegativeVariant(dimenX, VARIANT_HLP, nsnull))
     return PR_FALSE;
+
   // optional second value (forbidden if first value is inherit/initial)
-  if (dimenX.GetUnit() == eCSSUnit_Inherit ||
-      dimenX.GetUnit() == eCSSUnit_Initial ||
-      ! ParseNonNegativeVariant(dimenY, VARIANT_LP, nsnull))
-    dimenY = dimenX;
-
-  NS_ASSERTION(nsCSSProps::kTypeTable[aPropID] == eCSSType_ValuePair,
-               nsPrintfCString(64, "type error (property='%s')",
-                               nsCSSProps::GetStringValue(aPropID).get())
-               .get());
-  nsCSSValuePair& storage =
-    *static_cast<nsCSSValuePair*>(mTempData.PropertyAt(aPropID));
-  storage.mXValue = dimenX;
-  storage.mYValue = dimenY;
-  mTempData.SetPropertyBit(aPropID);
+  if (dimenX.GetUnit() != eCSSUnit_Inherit &&
+      dimenX.GetUnit() != eCSSUnit_Initial) {
+    ParseNonNegativeVariant(dimenY, VARIANT_LP, nsnull);
+  }
+
+  if (dimenX == dimenY || dimenY.GetUnit() == eCSSUnit_Null) {
+    AppendValue(aPropID, dimenX);
+  } else {
+    nsCSSValue value;
+    value.SetPairValue(dimenX, dimenY);
+    AppendValue(aPropID, value);
+  }
   return PR_TRUE;
 }
 
 PRBool
-CSSParserImpl::ParseBoxCornerRadii(nsCSSCornerSizes& aRadii,
-                                   const nsCSSProperty aPropIDs[])
+CSSParserImpl::ParseBoxCornerRadii(const nsCSSProperty aPropIDs[])
 {
   // Rectangles are used as scratch storage.
   // top => top-left, right => top-right,
   // bottom => bottom-right, left => bottom-left.
   nsCSSRect dimenX, dimenY;
   PRInt32 countX = 0, countY = 0;
 
   NS_FOR_CSS_SIDES (side) {
@@ -5175,21 +5137,26 @@ CSSParserImpl::ParseBoxCornerRadii(nsCSS
 
   switch (countY) {
     case 1: dimenY.mRight = dimenY.mTop;  // top-right same as top-left, and
     case 2: dimenY.mBottom = dimenY.mTop; // bottom-right same as top-left, and 
     case 3: dimenY.mLeft = dimenY.mRight; // bottom-left same as top-right
   }
 
   NS_FOR_CSS_SIDES(side) {
-    nsCSSValuePair& corner =
-      aRadii.GetFullCorner(NS_SIDE_TO_FULL_CORNER(side, PR_FALSE));
-    corner.mXValue = dimenX.*nsCSSRect::sides[side];
-    corner.mYValue = dimenY.*nsCSSRect::sides[side];
-    mTempData.SetPropertyBit(aPropIDs[side]);
+    nsCSSValue& x = dimenX.*nsCSSRect::sides[side];
+    nsCSSValue& y = dimenY.*nsCSSRect::sides[side];
+
+    if (x == y) {
+      AppendValue(aPropIDs[side], x);
+    } else {
+      nsCSSValue pair;
+      pair.SetPairValue(x, y);
+      AppendValue(aPropIDs[side], pair);
+    }
   }
   return PR_TRUE;
 }
 
 // These must be in CSS order (top,right,bottom,left) for indexing to work
 static const nsCSSProperty kBorderStyleIDs[] = {
   eCSSProperty_border_top_style,
   eCSSProperty_border_right_style_value,
@@ -5259,27 +5226,20 @@ CSSParserImpl::ParseProperty(nsCSSProper
     return ParseDirectionalBorderSide(kBorderRightIDs,
                                       NS_BOXPROP_SOURCE_PHYSICAL);
   case eCSSProperty_border_start:
     return ParseDirectionalBorderSide(kBorderStartIDs,
                                       NS_BOXPROP_SOURCE_LOGICAL);
   case eCSSProperty_border_top:
     return ParseBorderSide(kBorderTopIDs, PR_FALSE);
   case eCSSProperty_border_bottom_colors:
-    return ParseBorderColors(&mTempData.mMargin.mBorderColors.mBottom,
-                             aPropID);
   case eCSSProperty_border_left_colors:
-    return ParseBorderColors(&mTempData.mMargin.mBorderColors.mLeft,
-                             aPropID);
   case eCSSProperty_border_right_colors:
-    return ParseBorderColors(&mTempData.mMargin.mBorderColors.mRight,
-                             aPropID);
   case eCSSProperty_border_top_colors:
-    return ParseBorderColors(&mTempData.mMargin.mBorderColors.mTop,
-                             aPropID);
+    return ParseBorderColors(aPropID);
   case eCSSProperty_border_image:
     return ParseBorderImage();
   case eCSSProperty_border_width:
     return ParseBorderWidth();
   case eCSSProperty_border_end_color:
     return ParseDirectionalBoxProperty(eCSSProperty_border_end_color,
                                        NS_BOXPROP_SOURCE_LOGICAL);
   case eCSSProperty_border_left_color:
@@ -5311,55 +5271,51 @@ CSSParserImpl::ParseProperty(nsCSSProper
                                        NS_BOXPROP_SOURCE_PHYSICAL);
   case eCSSProperty_border_right_style:
     return ParseDirectionalBoxProperty(eCSSProperty_border_right_style,
                                        NS_BOXPROP_SOURCE_PHYSICAL);
   case eCSSProperty_border_start_style:
     return ParseDirectionalBoxProperty(eCSSProperty_border_start_style,
                                        NS_BOXPROP_SOURCE_LOGICAL);
   case eCSSProperty__moz_border_radius:
-    return ParseBoxCornerRadii(mTempData.mMargin.mBorderRadius,
-                               kBorderRadiusIDs);
+    return ParseBoxCornerRadii(kBorderRadiusIDs);
   case eCSSProperty__moz_outline_radius:
-    return ParseBoxCornerRadii(mTempData.mMargin.mOutlineRadius,
-                               kOutlineRadiusIDs);
+    return ParseBoxCornerRadii(kOutlineRadiusIDs);
 
   case eCSSProperty__moz_border_radius_topLeft:
   case eCSSProperty__moz_border_radius_topRight:
   case eCSSProperty__moz_border_radius_bottomRight:
   case eCSSProperty__moz_border_radius_bottomLeft:
   case eCSSProperty__moz_outline_radius_topLeft:
   case eCSSProperty__moz_outline_radius_topRight:
   case eCSSProperty__moz_outline_radius_bottomRight:
   case eCSSProperty__moz_outline_radius_bottomLeft:
     return ParseBoxCornerRadius(aPropID);
 
   case eCSSProperty_box_shadow:
-    return ParseBoxShadow();
+  case eCSSProperty_text_shadow:
+    return ParseShadowList(aPropID);
+
   case eCSSProperty_clip:
-    return ParseRect(mTempData.mDisplay.mClip, eCSSProperty_clip);
+    return ParseRect(eCSSProperty_clip);
   case eCSSProperty__moz_column_rule:
     return ParseBorderSide(kColumnRuleIDs, PR_FALSE);
   case eCSSProperty_content:
     return ParseContent();
   case eCSSProperty_counter_increment:
-    return ParseCounterData(&mTempData.mContent.mCounterIncrement,
-                            aPropID);
   case eCSSProperty_counter_reset:
-    return ParseCounterData(&mTempData.mContent.mCounterReset,
-                            aPropID);
+    return ParseCounterData(aPropID);
   case eCSSProperty_cue:
     return ParseCue();
   case eCSSProperty_cursor:
     return ParseCursor();
   case eCSSProperty_font:
     return ParseFont();
   case eCSSProperty_image_region:
-    return ParseRect(mTempData.mList.mImageRegion,
-                     eCSSProperty_image_region);
+    return ParseRect(eCSSProperty_image_region);
   case eCSSProperty_list_style:
     return ParseListStyle();
   case eCSSProperty_margin:
     return ParseMargin();
   case eCSSProperty_margin_end:
     return ParseDirectionalBoxProperty(eCSSProperty_margin_end,
                                        NS_BOXPROP_SOURCE_LOGICAL);
   case eCSSProperty_margin_left:
@@ -5390,37 +5346,34 @@ CSSParserImpl::ParseProperty(nsCSSProper
     return ParseDirectionalBoxProperty(eCSSProperty_padding_start,
                                        NS_BOXPROP_SOURCE_LOGICAL);
   case eCSSProperty_pause:
     return ParsePause();
   case eCSSProperty_quotes:
     return ParseQuotes();
   case eCSSProperty_size:
     return ParseSize();
-  case eCSSProperty_text_shadow:
-    return ParseTextShadow();
   case eCSSProperty__moz_transform:
     return ParseMozTransform();
   case eCSSProperty__moz_transform_origin:
     return ParseMozTransformOrigin();
   case eCSSProperty_transition:
       return ParseTransition();
   case eCSSProperty_transition_property:
     return ParseTransitionProperty();
   case eCSSProperty_transition_timing_function:
     return ParseTransitionTimingFunction();
   case eCSSProperty_transition_duration:
   case eCSSProperty_transition_delay:
     return ParseTransitionTime(aPropID);
 
 #ifdef MOZ_SVG
   case eCSSProperty_fill:
-    return ParsePaint(&mTempData.mSVG.mFill, eCSSProperty_fill);
   case eCSSProperty_stroke:
-    return ParsePaint(&mTempData.mSVG.mStroke, eCSSProperty_stroke);
+    return ParsePaint(aPropID);
   case eCSSProperty_stroke_dasharray:
     return ParseDasharray();
   case eCSSProperty_marker:
     return ParseMarker();
 #endif
 
   // Strip out properties we use internally.
   case eCSSProperty__x_system_font:
@@ -5615,37 +5568,37 @@ CSSParserImpl::ParseSingleValueProperty(
 
   case eCSSProperty_appearance:
     return ParseVariant(aValue, VARIANT_HK,
                         nsCSSProps::kAppearanceKTable);
   case eCSSProperty_azimuth:
     return ParseAzimuth(aValue);
   case eCSSProperty_background_attachment:
     // Used only internally.
-    return ParseVariant(aValue, VARIANT_HK,
+    return ParseVariant(aValue, VARIANT_KEYWORD,
                         nsCSSProps::kBackgroundAttachmentKTable);
   case eCSSProperty_background_clip:
     // Used only internally.
-    return ParseVariant(aValue, VARIANT_HK,
+    return ParseVariant(aValue, VARIANT_KEYWORD,
                         nsCSSProps::kBackgroundOriginKTable);
   case eCSSProperty_background_color:
     return ParseVariant(aValue, VARIANT_HC, nsnull);
   case eCSSProperty_background_image:
     // Used only internally.
-    return ParseVariant(aValue, VARIANT_IMAGE | VARIANT_INHERIT, nsnull);
+    return ParseVariant(aValue, VARIANT_IMAGE, nsnull);
   case eCSSProperty__moz_background_inline_policy:
     return ParseVariant(aValue, VARIANT_HK,
                         nsCSSProps::kBackgroundInlinePolicyKTable);
   case eCSSProperty_background_origin:
     // Used only internally.
-    return ParseVariant(aValue, VARIANT_HK,
+    return ParseVariant(aValue, VARIANT_KEYWORD,
                         nsCSSProps::kBackgroundOriginKTable);
   case eCSSProperty_background_repeat:
     // Used only internally.
-    return ParseVariant(aValue, VARIANT_HK,
+    return ParseVariant(aValue, VARIANT_KEYWORD,
                         nsCSSProps::kBackgroundRepeatKTable);
   case eCSSProperty_binding:
     return ParseVariant(aValue, VARIANT_HUO, nsnull);
   case eCSSProperty_border_collapse:
     return ParseVariant(aValue, VARIANT_HK,
                         nsCSSProps::kBorderCollapseKTable);
   case eCSSProperty_border_bottom_color:
   case eCSSProperty_border_end_color_value: // for internal use
@@ -6184,353 +6137,314 @@ BoxPositionMaskToCSSValue(PRInt32 aMask,
   return nsCSSValue(val, eCSSUnit_Enumerated);
 }
 
 PRBool
 CSSParserImpl::ParseBackground()
 {
   nsAutoParseCompoundProperty compound(this);
 
-  // These two are set through side-effects of ParseBackgroundItem.
-  mTempData.SetPropertyBit(eCSSProperty_background_color);
-  mTempData.mColor.mBackColor.SetColorValue(NS_RGBA(0, 0, 0, 0));
-
-  BackgroundItem bgitem;
-  nsCSSValuePairList *positionHead = nsnull, **positionTail = &positionHead;
-  nsCSSValuePairList *sizeHead = nsnull, **sizeTail = &sizeHead;
-  static const BackgroundItemSimpleValueInfo simpleValues[] = {
-    { &BackgroundItem::mImage,      eCSSProperty_background_image },
-    { &BackgroundItem::mRepeat,     eCSSProperty_background_repeat },
-    { &BackgroundItem::mAttachment, eCSSProperty_background_attachment },
-    { &BackgroundItem::mClip,       eCSSProperty_background_clip },
-    { &BackgroundItem::mOrigin,     eCSSProperty_background_origin }
+  // background-color can only be set once, so it's not a list.
+  nsCSSValue color;
+
+  // Check first for inherit/initial.
+  if (ParseVariant(color, VARIANT_INHERIT, nsnull)) {
+    // must be alone
+    if (!ExpectEndProperty()) {
+      return PR_FALSE;
+    }
+    for (const nsCSSProperty* subprops =
+           nsCSSProps::SubpropertyEntryFor(eCSSProperty_background);
+         *subprops != eCSSProperty_UNKNOWN; ++subprops) {
+      AppendValue(*subprops, color);
+    }
+    return PR_TRUE;
+  }
+
+  nsCSSValue image, repeat, attachment, clip, origin, position, size;
+  BackgroundParseState state = {
+    color,
+    image.SetListValue(),
+    repeat.SetListValue(),
+    attachment.SetListValue(),
+    clip.SetListValue(),
+    origin.SetListValue(),
+    position.SetPairListValue(),
+    size.SetPairListValue()
   };
-  nsCSSValueList *simpleHeads[NS_ARRAY_LENGTH(simpleValues)];
-  nsCSSValueList **simpleTails[NS_ARRAY_LENGTH(simpleValues)];
-  for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(simpleValues); ++i) {
-    simpleHeads[i] = nsnull;
-    simpleTails[i] = &simpleHeads[i];
-  }
+
   for (;;) {
-    if (!ParseBackgroundItem(bgitem, !positionHead)) {
-      break;
-    }
-
-    nsCSSValuePairList *positionItem = new nsCSSValuePairList;
-    if (!positionItem) {
-      mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
-      break;
-    }
-    positionItem->mXValue = bgitem.mPosition.mXValue;
-    positionItem->mYValue = bgitem.mPosition.mYValue;
-    *positionTail = positionItem;
-    positionTail = &positionItem->mNext;
-
-    nsCSSValuePairList *sizeItem = new nsCSSValuePairList;
-    if (!sizeItem) {
-      mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
+    if (!ParseBackgroundItem(state)) {
+      return PR_FALSE;
+    }
+    if (CheckEndProperty()) {
       break;
     }
-    sizeItem->mXValue = bgitem.mSize.mXValue;
-    sizeItem->mYValue = bgitem.mSize.mYValue;
-    *sizeTail = sizeItem;
-    sizeTail = &sizeItem->mNext;
-
-    PRBool fail = PR_FALSE;
-    for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(simpleValues); ++i) {
-      nsCSSValueList *item = new nsCSSValueList;
-      if (!item) {
-        mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
-        fail = PR_TRUE;
-        break;
-      }
-      item->mValue = bgitem.*(simpleValues[i].member);
-      *simpleTails[i] = item;
-      simpleTails[i] = &item->mNext;
-    }
-    if (fail) {
-      break;
-    }
-
-    if (!bgitem.mLastItem && ExpectSymbol(',', PR_TRUE)) {
-      continue;
-    }
-    if (!ExpectEndProperty()) {
-      break;
-    }
-
-    mTempData.mColor.mBackPosition = positionHead;
-    mTempData.mColor.mBackSize = sizeHead;
-    for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(simpleValues); ++i) {
-      nsCSSValueList **source = static_cast<nsCSSValueList**>(
-        mTempData.PropertyAt(simpleValues[i].propID));
-      *source = simpleHeads[i];
-    }
-
-    mTempData.SetPropertyBit(eCSSProperty_background_image);
-    mTempData.SetPropertyBit(eCSSProperty_background_repeat);
-    mTempData.SetPropertyBit(eCSSProperty_background_attachment);
-    mTempData.SetPropertyBit(eCSSProperty_background_position);
-    mTempData.SetPropertyBit(eCSSProperty_background_clip);
-    mTempData.SetPropertyBit(eCSSProperty_background_origin);
-    mTempData.SetPropertyBit(eCSSProperty_background_size);
-    return PR_TRUE;
-  }
-  delete positionHead;
-  delete sizeHead;
-  for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(simpleValues); ++i) {
-    delete simpleHeads[i];
-  }
-  return PR_FALSE;
+    // If we saw a color, this must be the last item.
+    if (color.GetUnit() != eCSSUnit_Null) {
+      REPORT_UNEXPECTED_TOKEN(PEExpectEndValue);
+      return PR_FALSE;
+    }
+    // Otherwise, a comma is mandatory.
+    if (!ExpectSymbol(',', PR_TRUE)) {
+      return PR_FALSE;
+    }
+    // Chain another entry on all the lists.
+    state.mImage->mNext = new nsCSSValueList;
+    state.mImage = state.mImage->mNext;
+    state.mRepeat->mNext = new nsCSSValueList;
+    state.mRepeat = state.mRepeat->mNext;
+    state.mAttachment->mNext = new nsCSSValueList;
+    state.mAttachment = state.mAttachment->mNext;
+    state.mClip->mNext = new nsCSSValueList;
+    state.mClip = state.mClip->mNext;
+    state.mOrigin->mNext = new nsCSSValueList;
+    state.mOrigin = state.mOrigin->mNext;
+    state.mPosition->mNext = new nsCSSValuePairList;
+    state.mPosition = state.mPosition->mNext;
+    state.mSize->mNext = new nsCSSValuePairList;
+    state.mSize = state.mSize->mNext;
+  }
+
+  // If we get to this point without seeing a color, provide a default.
+  if (color.GetUnit() == eCSSUnit_Null) {
+    color.SetColorValue(NS_RGBA(0,0,0,0));
+  }
+
+  AppendValue(eCSSProperty_background_image,      image);
+  AppendValue(eCSSProperty_background_repeat,     repeat);
+  AppendValue(eCSSProperty_background_attachment, attachment);
+  AppendValue(eCSSProperty_background_clip,       clip);
+  AppendValue(eCSSProperty_background_origin,     origin);
+  AppendValue(eCSSProperty_background_position,   position);
+  AppendValue(eCSSProperty_background_size,       size);
+  AppendValue(eCSSProperty_background_color,      color);
+  return PR_TRUE;
 }
 
 // Parse one item of the background shorthand property.
 PRBool
-CSSParserImpl::ParseBackgroundItem(CSSParserImpl::BackgroundItem& aItem,
-                                   PRBool aFirstItem)
+CSSParserImpl::ParseBackgroundItem(CSSParserImpl::BackgroundParseState& aState)
+
 {
   // Fill in the values that the shorthand will set if we don't find
   // other values.
-  aItem.mImage.SetNoneValue();
-  aItem.mRepeat.SetIntValue(NS_STYLE_BG_REPEAT_XY, eCSSUnit_Enumerated);
-  aItem.mAttachment.SetIntValue(NS_STYLE_BG_ATTACHMENT_SCROLL,
-                                eCSSUnit_Enumerated);
-  aItem.mPosition.mXValue.SetPercentValue(0.0f);
-  aItem.mPosition.mYValue.SetPercentValue(0.0f);
-  aItem.mClip.SetIntValue(NS_STYLE_BG_CLIP_BORDER, eCSSUnit_Enumerated);
-  aItem.mOrigin.SetIntValue(NS_STYLE_BG_ORIGIN_PADDING, eCSSUnit_Enumerated);
-  aItem.mSize.mXValue.SetAutoValue();
-  aItem.mSize.mYValue.SetAutoValue();
-  aItem.mLastItem = PR_FALSE;
+  aState.mImage->mValue.SetNoneValue();
+  aState.mRepeat->mValue.SetIntValue(NS_STYLE_BG_REPEAT_XY,
+                                     eCSSUnit_Enumerated);
+  aState.mAttachment->mValue.SetIntValue(NS_STYLE_BG_ATTACHMENT_SCROLL,
+                                         eCSSUnit_Enumerated);
+  aState.mClip->mValue.SetIntValue(NS_STYLE_BG_CLIP_BORDER,
+                                   eCSSUnit_Enumerated);
+  aState.mOrigin->mValue.SetIntValue(NS_STYLE_BG_ORIGIN_PADDING,
+                                     eCSSUnit_Enumerated);
+  aState.mPosition->mXValue.SetPercentValue(0.0f);
+  aState.mPosition->mYValue.SetPercentValue(0.0f);
+  aState.mSize->mXValue.SetAutoValue();
+  aState.mSize->mYValue.SetAutoValue();
 
   PRBool haveColor = PR_FALSE,
          haveImage = PR_FALSE,
          haveRepeat = PR_FALSE,
          haveAttach = PR_FALSE,
          havePosition = PR_FALSE,
          haveOrigin = PR_FALSE,
          haveSomething = PR_FALSE;
+
   while (GetToken(PR_TRUE)) {
     nsCSSTokenType tt = mToken.mType;
     UngetToken(); // ...but we'll still cheat and use mToken
     if (tt == eCSSToken_Symbol) {
       // ExpectEndProperty only looks for symbols, and nothing else will
       // show up as one.
       break;
     }
 
     if (tt == eCSSToken_Ident) {
       nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent);
       PRInt32 dummy;
       if (keyword == eCSSKeyword_inherit ||
           keyword == eCSSKeyword__moz_initial) {
-        if (haveSomething || !aFirstItem)
-          return PR_FALSE;
-        haveColor = haveImage = haveRepeat = haveAttach = havePosition = haveOrigin =
-          PR_TRUE;
-        GetToken(PR_TRUE); // undo the UngetToken above
-        nsCSSValue val;
-        if (keyword == eCSSKeyword_inherit) {
-          val.SetInheritValue();
-        } else {
-          val.SetInitialValue();
-        }
-        mTempData.mColor.mBackColor = val;
-        aItem.mImage = val;
-        aItem.mRepeat = val;
-        aItem.mAttachment = val;
-        aItem.mPosition.SetBothValuesTo(val);
-        aItem.mClip = val;
-        aItem.mOrigin = val;
-        aItem.mSize.mXValue = val;
-        aItem.mSize.mYValue = val;
-        aItem.mLastItem = PR_TRUE;
-        haveSomething = PR_TRUE;
-        break;
+        return PR_FALSE;
       } else if (keyword == eCSSKeyword_none) {
         if (haveImage)
           return PR_FALSE;
         haveImage = PR_TRUE;
-        if (!ParseSingleValueProperty(aItem.mImage,
+        if (!ParseSingleValueProperty(aState.mImage->mValue,
                                       eCSSProperty_background_image)) {
           NS_NOTREACHED("should be able to parse");
           return PR_FALSE;
         }
       } else if (nsCSSProps::FindKeyword(keyword,
                    nsCSSProps::kBackgroundAttachmentKTable, dummy)) {
         if (haveAttach)
           return PR_FALSE;
         haveAttach = PR_TRUE;
-        if (!ParseSingleValueProperty(aItem.mAttachment,
+        if (!ParseSingleValueProperty(aState.mAttachment->mValue,
                                       eCSSProperty_background_attachment)) {
           NS_NOTREACHED("should be able to parse");
           return PR_FALSE;
         }
       } else if (nsCSSProps::FindKeyword(keyword,
                    nsCSSProps::kBackgroundRepeatKTable, dummy)) {
         if (haveRepeat)
           return PR_FALSE;
         haveRepeat = PR_TRUE;
-        if (!ParseSingleValueProperty(aItem.mRepeat,
+        if (!ParseSingleValueProperty(aState.mRepeat->mValue,
                                       eCSSProperty_background_repeat)) {
           NS_NOTREACHED("should be able to parse");
           return PR_FALSE;
         }
       } else if (nsCSSProps::FindKeyword(keyword,
                    nsCSSProps::kBackgroundPositionKTable, dummy)) {
         if (havePosition)
           return PR_FALSE;
         havePosition = PR_TRUE;
-        if (!ParseBoxPositionValues(aItem.mPosition, PR_FALSE)) {
+        nsCSSValuePair scratch;
+        if (!ParseBoxPositionValues(scratch, PR_FALSE)) {
           return PR_FALSE;
         }
+        aState.mPosition->mXValue = scratch.mXValue;
+        aState.mPosition->mYValue = scratch.mYValue;
       } else if (nsCSSProps::FindKeyword(keyword,
                    nsCSSProps::kBackgroundOriginKTable, dummy)) {
         if (haveOrigin)
           return PR_FALSE;
         haveOrigin = PR_TRUE;
-        if (!ParseSingleValueProperty(aItem.mOrigin,
+        if (!ParseSingleValueProperty(aState.mOrigin->mValue,
                                       eCSSProperty_background_origin)) {
           NS_NOTREACHED("should be able to parse");
           return PR_FALSE;
         }
         PR_STATIC_ASSERT(NS_STYLE_BG_CLIP_BORDER ==
                          NS_STYLE_BG_ORIGIN_BORDER);
         PR_STATIC_ASSERT(NS_STYLE_BG_CLIP_PADDING ==
                          NS_STYLE_BG_ORIGIN_PADDING);
         PR_STATIC_ASSERT(NS_STYLE_BG_CLIP_CONTENT ==
                          NS_STYLE_BG_ORIGIN_CONTENT);
-        aItem.mClip = aItem.mOrigin;
+        aState.mClip->mValue = aState.mOrigin->mValue;
       } else {
         if (haveColor)
           return PR_FALSE;
         haveColor = PR_TRUE;
-        if (!ParseSingleValueProperty(mTempData.mColor.mBackColor,
+        if (!ParseSingleValueProperty(aState.mColor,
                                       eCSSProperty_background_color)) {
           return PR_FALSE;
         }
-        aItem.mLastItem = PR_TRUE;
-      }
-    } else if (eCSSToken_Function == tt &&
+      }
+    } else if (tt == eCSSToken_Function &&
                (mToken.mIdent.LowerCaseEqualsLiteral("url") ||
                 mToken.mIdent.LowerCaseEqualsLiteral("-moz-linear-gradient") ||
                 mToken.mIdent.LowerCaseEqualsLiteral("-moz-radial-gradient") ||
                 mToken.mIdent.LowerCaseEqualsLiteral("-moz-repeating-linear-gradient") ||
                 mToken.mIdent.LowerCaseEqualsLiteral("-moz-repeating-radial-gradient") ||
                 mToken.mIdent.LowerCaseEqualsLiteral("-moz-image-rect") ||
                 mToken.mIdent.LowerCaseEqualsLiteral("-moz-element"))) {
       if (haveImage)
         return PR_FALSE;
       haveImage = PR_TRUE;
-      if (!ParseSingleValueProperty(aItem.mImage,
+      if (!ParseSingleValueProperty(aState.mImage->mValue,
                                     eCSSProperty_background_image)) {
         return PR_FALSE;
       }
-    } else if (tt == eCSSToken_Dimension || tt == eCSSToken_Number ||
+    } else if (tt == eCSSToken_Dimension ||
+               tt == eCSSToken_Number ||
                tt == eCSSToken_Percentage) {
       if (havePosition)
         return PR_FALSE;
       havePosition = PR_TRUE;
-      if (!ParseBoxPositionValues(aItem.mPosition, PR_FALSE)) {
+      nsCSSValuePair scratch;
+      if (!ParseBoxPositionValues(scratch, PR_FALSE)) {
         return PR_FALSE;
       }
+      aState.mPosition->mXValue = scratch.mXValue;
+      aState.mPosition->mYValue = scratch.mYValue;
     } else {
       if (haveColor)
         return PR_FALSE;
       haveColor = PR_TRUE;
       // Note: This parses 'inherit' and 'initial', but
       // we've already checked for them, so it's ok.
-      if (!ParseSingleValueProperty(mTempData.mColor.mBackColor,
+      if (!ParseSingleValueProperty(aState.mColor,
                                     eCSSProperty_background_color)) {
         return PR_FALSE;
       }
-      aItem.mLastItem = PR_TRUE;
     }
     haveSomething = PR_TRUE;
   }
 
   return haveSomething;
 }
 
 // This function is very similar to ParseBackgroundPosition and
 // ParseBackgroundSize.
 PRBool
 CSSParserImpl::ParseBackgroundList(nsCSSProperty aPropID)
 {
   // aPropID is a single value prop-id
   nsCSSValue value;
-  nsCSSValueList *head = nsnull, **tail = &head;
-  for (;;) {
-    if (!ParseSingleValueProperty(value, aPropID)) {
-      break;
-    }
-    PRBool inheritOrInitial = value.GetUnit() == eCSSUnit_Inherit ||
-                              value.GetUnit() == eCSSUnit_Initial;
-    if (inheritOrInitial && head) {
-      // inherit and initial are only allowed on their own
-      break;
-    }
-    nsCSSValueList *item = new nsCSSValueList;
-    if (!item) {
-      mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
-      break;
-    }
-    item->mValue = value;
-    *tail = item;
-    tail = &item->mNext;
-    if (!inheritOrInitial && ExpectSymbol(',', PR_TRUE)) {
-      continue;
-    }
+  if (ParseVariant(value, VARIANT_INHERIT, nsnull)) {
+    // 'initial' and 'inherit' stand alone, no list permitted.
     if (!ExpectEndProperty()) {
-      break;
-    }
-    nsCSSValueList **source =
-      static_cast<nsCSSValueList**>(mTempData.PropertyAt(aPropID));
-    *source = head;
-    mTempData.SetPropertyBit(aPropID);
-    return PR_TRUE;
-  }
-  delete head;
-  return PR_FALSE;
+      return PR_FALSE;
+    }
+  } else {
+    nsCSSValueList* item = value.SetListValue();
+    for (;;) {
+      if (!ParseSingleValueProperty(item->mValue, aPropID)) {
+        return PR_FALSE;
+      }
+      if (CheckEndProperty()) {
+        break;
+      }
+      if (!ExpectSymbol(',', PR_TRUE)) {
+        return PR_FALSE;
+      }
+      item->mNext = new nsCSSValueList;
+      item = item->mNext;
+    }
+  }
+  AppendValue(aPropID, value);
+  return PR_TRUE;
 }
 
 // This function is very similar to ParseBackgroundList and ParseBackgroundSize.
 PRBool
 CSSParserImpl::ParseBackgroundPosition()
 {
-  // aPropID is a single value prop-id
-  nsCSSValuePair valuePair;
-  nsCSSValuePairList *head = nsnull, **tail = &head;
-  for (;;) {
-    if (!ParseBoxPositionValues(valuePair, !head)) {
-      break;
-    }
-    PRBool inheritOrInitial = valuePair.mXValue.GetUnit() == eCSSUnit_Inherit ||
-                              valuePair.mXValue.GetUnit() == eCSSUnit_Initial;
-    nsCSSValuePairList *item = new nsCSSValuePairList;
-    if (!item) {
-      mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
-      break;
-    }
-    item->mXValue = valuePair.mXValue;
-    item->mYValue = valuePair.mYValue;
-    *tail = item;
-    tail = &item->mNext;
-    if (!inheritOrInitial && ExpectSymbol(',', PR_TRUE)) {
-      continue;
-    }
+  nsCSSValue value;
+  if (ParseVariant(value, VARIANT_INHERIT, nsnull)) {
+    // 'initial' and 'inherit' stand alone, no list permitted.
     if (!ExpectEndProperty()) {
-      break;
-    }
-    mTempData.mColor.mBackPosition = head;
-    mTempData.SetPropertyBit(eCSSProperty_background_position);
-    return PR_TRUE;
-  }
-  delete head;
-  return PR_FALSE;
+      return PR_FALSE;
+    }
+  } else {
+    nsCSSValuePair valuePair;
+    if (!ParseBoxPositionValues(valuePair, PR_FALSE)) {
+      return PR_FALSE;
+    }
+    nsCSSValuePairList* item = value.SetPairListValue();
+    for (;;) {
+      item->mXValue = valuePair.mXValue;
+      item->mYValue = valuePair.mYValue;
+      if (CheckEndProperty()) {
+        break;
+      }
+      if (!ExpectSymbol(',', PR_TRUE)) {
+        return PR_FALSE;
+      }
+      if (!ParseBoxPositionValues(valuePair, PR_FALSE)) {
+        return PR_FALSE;
+      }
+      item->mNext = new nsCSSValuePairList;
+      item = item->mNext;
+    }
+  }
+  AppendValue(eCSSProperty_background_position, value);
+  return PR_TRUE;
 }
 
 /**
  * Parses two values that correspond to positions in a box.  These can be
  * values corresponding to percentages of the box, raw offsets, or keywords
  * like "top," "left center," etc.
  *
  * @param aOut The nsCSSValuePair in which to place the result.
@@ -6618,57 +6532,46 @@ PRBool CSSParserImpl::ParseBoxPositionVa
   return PR_TRUE;
 }
 
 // This function is very similar to ParseBackgroundList and
 // ParseBackgroundPosition.
 PRBool
 CSSParserImpl::ParseBackgroundSize()
 {
-  nsCSSValuePair valuePair;
-  nsCSSValuePairList *head = nsnull, **tail = &head;
-  if (ParseVariant(valuePair.mXValue, VARIANT_INHERIT, nsnull)) {
-    // 'initial' and 'inherit' stand alone, no second value.
-    head = new nsCSSValuePairList;
-    if (!head) {
-      mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
+  nsCSSValue value;
+  if (ParseVariant(value, VARIANT_INHERIT, nsnull)) {
+    // 'initial' and 'inherit' stand alone, no list permitted.
+    if (!ExpectEndProperty()) {
       return PR_FALSE;
     }
-    head->mXValue = valuePair.mXValue;
-    head->mYValue.Reset();
-    mTempData.mColor.mBackSize = head;
-    mTempData.SetPropertyBit(eCSSProperty_background_size);
-    return ExpectEndProperty();
-  }
-
-  for (;;) {
+  } else {
+    nsCSSValuePair valuePair;
     if (!ParseBackgroundSizeValues(valuePair)) {
-      break;
-    }
-    nsCSSValuePairList *item = new nsCSSValuePairList;
-    if (!item) {
-      mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
-      break;
-    }
-    item->mXValue = valuePair.mXValue;
-    item->mYValue = valuePair.mYValue;
-    *tail = item;
-    tail = &item->mNext;
-    if (ExpectSymbol(',', PR_TRUE)) {
-      continue;
-    }
-    if (!ExpectEndProperty()) {
-      break;
-    }
-    mTempData.mColor.mBackSize = head;
-    mTempData.SetPropertyBit(eCSSProperty_background_size);
-    return PR_TRUE;
-  }
-  delete head;
-  return PR_FALSE;
+      return PR_FALSE;
+    }
+    nsCSSValuePairList* item = value.SetPairListValue();
+    for (;;) {
+      item->mXValue = valuePair.mXValue;
+      item->mYValue = valuePair.mYValue;
+      if (CheckEndProperty()) {
+        break;
+      }
+      if (!ExpectSymbol(',', PR_TRUE)) {
+        return PR_FALSE;
+      }
+      if (!ParseBackgroundSizeValues(valuePair)) {
+        return PR_FALSE;
+      }
+      item->mNext = new nsCSSValuePairList;
+      item = item->mNext;
+    }
+  }
+  AppendValue(eCSSProperty_background_size, value);
+  return PR_TRUE;
 }
 
 /**
  * Parses two values that correspond to lengths for the background-size
  * property.  These can be one or two lengths (or the 'auto' keyword) or
  * percentages corresponding to the element's dimensions or the single keywords
  * 'contain' or 'cover'.  'initial' and 'inherit' must be handled by the caller
  * if desired.
@@ -6710,30 +6613,30 @@ CSSParserImpl::ParseBorderColor()
     eCSSProperty_border_left_color_rtl_source,
     eCSSProperty_border_right_color_ltr_source,
     eCSSProperty_border_right_color_rtl_source,
     eCSSProperty_UNKNOWN
   };
 
   // do this now, in case 4 values weren't specified
   InitBoxPropsAsPhysical(kBorderColorSources);
-  return ParseBoxProperties(mTempData.mMargin.mBorderColor,
-                            kBorderColorIDs);
+  return ParseBoxProperties(kBorderColorIDs);
 }
 
 PRBool
 CSSParserImpl::ParseBorderImage()
 {
-  if (ParseVariant(mTempData.mMargin.mBorderImage,
-                   VARIANT_INHERIT | VARIANT_NONE, nsnull)) {
-    mTempData.SetPropertyBit(eCSSProperty_border_image);
+  nsCSSValue val;
+  if (ParseVariant(val, VARIANT_INHERIT | VARIANT_NONE, nsnull)) {
+    AppendValue(eCSSProperty_border_image, val);
     return PR_TRUE;
   }
 
-  // <uri> [<number> | <percentage>]{1,4} [ / <border-width>{1,4} ]? [stretch | repeat | round]{0,2}
+  // <uri> [<number> | <percentage>]{1,4}
+  //       [ / <border-width>{1,4} ]? [stretch | repeat | round]{0,2}
   nsRefPtr<nsCSSValue::Array> arr = nsCSSValue::Array::Create(11);
   if (!arr) {
     mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
     return PR_FALSE;
   }
 
   nsCSSValue& url = arr->Item(0);
   nsCSSValue& splitTop = arr->Item(1);
@@ -6792,52 +6695,48 @@ CSSParserImpl::ParseBorderImage()
   if (ParseEnum(horizontalKeyword, nsCSSProps::kBorderImageKTable)) {
     (void)ParseEnum(verticalKeyword, nsCSSProps::kBorderImageKTable);
   }
 
   if (!ExpectEndProperty()) {
     return PR_FALSE;
   }
 
-  mTempData.mMargin.mBorderImage.SetArrayValue(arr, eCSSUnit_Array);
-  mTempData.SetPropertyBit(eCSSProperty_border_image);
+  val.SetArrayValue(arr, eCSSUnit_Array);
+  AppendValue(eCSSProperty_border_image, val);
 
   return PR_TRUE;
 }
 
 PRBool
 CSSParserImpl::ParseBorderSpacing()
 {
-  nsCSSValue  xValue;
-  if (ParseNonNegativeVariant(xValue, VARIANT_HL | VARIANT_CALC, nsnull)) {
-    if (xValue.IsLengthUnit() || xValue.IsCalcUnit()) {
-      // We have one length. Get the optional second length.
-      nsCSSValue yValue;
-      if (ParseNonNegativeVariant(yValue, VARIANT_LENGTH | VARIANT_CALC,
-                                  nsnull)) {
-        // We have two numbers
-        if (ExpectEndProperty()) {
-          mTempData.mTable.mBorderSpacing.mXValue = xValue;
-          mTempData.mTable.mBorderSpacing.mYValue = yValue;
-          mTempData.SetPropertyBit(eCSSProperty_border_spacing);
-          return PR_TRUE;
-        }
-        return PR_FALSE;
-      }
-    }
-
-    // We have one length which is the horizontal spacing. Create a value for
-    // the vertical spacing which is equal
-    if (ExpectEndProperty()) {
-      mTempData.mTable.mBorderSpacing.SetBothValuesTo(xValue);
-      mTempData.SetPropertyBit(eCSSProperty_border_spacing);
-      return PR_TRUE;
-    }
-  }
-  return PR_FALSE;
+  nsCSSValue xValue, yValue;
+  if (!ParseNonNegativeVariant(xValue, VARIANT_HL | VARIANT_CALC, nsnull)) {
+    return PR_FALSE;
+  }
+
+  // If we have one length, get the optional second length.
+  // set the second value equal to the first.
+  if (xValue.IsLengthUnit() || xValue.IsCalcUnit()) {
+    ParseNonNegativeVariant(yValue, VARIANT_LENGTH | VARIANT_CALC, nsnull);
+  }
+
+  if (!ExpectEndProperty()) {
+    return PR_FALSE;
+  }
+
+  if (yValue == xValue || yValue.GetUnit() == eCSSUnit_Null) {
+    AppendValue(eCSSProperty_border_spacing, xValue);
+  } else {
+    nsCSSValue pair;
+    pair.SetPairValue(xValue, yValue);
+    AppendValue(eCSSProperty_border_spacing, pair);
+  }
+  return PR_TRUE;
 }
 
 PRBool
 CSSParserImpl::ParseBorderSide(const nsCSSProperty aPropIDs[],
                                PRBool aSetAllSides)
 {
   const PRInt32 numProps = 3;
   nsCSSValue  values[numProps];
@@ -6895,27 +6794,19 @@ CSSParserImpl::ParseBorderSide(const nsC
     // initial values.
     nsCSSValue extraValue;
     switch (values[0].GetUnit()) {
       case eCSSUnit_Inherit:    extraValue.SetInheritValue();    break;
       case eCSSUnit_Initial:    extraValue.SetInitialValue();    break;
       default:                  extraValue.SetNoneValue();       break;
     }
     NS_FOR_CSS_SIDES(side) {
-      nsCSSValueList *l = new nsCSSValueList;
-      if (!l) {
-        mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
-        return PR_FALSE;
-      }
-      l->mValue = extraValue;
-      mTempData.mMargin.mBorderColors.*(nsCSSValueListRect::sides[side]) = l;
-      mTempData.SetPropertyBit(kBorderColorsProps[side]);
-    }
-    mTempData.mMargin.mBorderImage = extraValue;
-    mTempData.SetPropertyBit(eCSSProperty_border_image);
+      AppendValue(kBorderColorsProps[side], extraValue);
+    }
+    AppendValue(eCSSProperty_border_image, extraValue);
   }
   else {
     // Just set our one side
     for (PRInt32 index = 0; index < numProps; index++) {
       AppendValue(aPropIDs[index], values[index]);
     }
   }
   return PR_TRUE;
@@ -6963,72 +6854,60 @@ CSSParserImpl::ParseBorderStyle()
     eCSSProperty_border_left_style_rtl_source,
     eCSSProperty_border_right_style_ltr_source,
     eCSSProperty_border_right_style_rtl_source,
     eCSSProperty_UNKNOWN
   };
 
   // do this now, in case 4 values weren't specified
   InitBoxPropsAsPhysical(kBorderStyleSources);
-  return ParseBoxProperties(mTempData.mMargin.mBorderStyle,
-                            kBorderStyleIDs);
+  return ParseBoxProperties(kBorderStyleIDs);
 }
 
 PRBool
 CSSParserImpl::ParseBorderWidth()
 {
   static const nsCSSProperty kBorderWidthSources[] = {
     eCSSProperty_border_left_width_ltr_source,
     eCSSProperty_border_left_width_rtl_source,
     eCSSProperty_border_right_width_ltr_source,
     eCSSProperty_border_right_width_rtl_source,
     eCSSProperty_UNKNOWN
   };
 
   // do this now, in case 4 values weren't specified
   InitBoxPropsAsPhysical(kBorderWidthSources);
-  return ParseBoxProperties(mTempData.mMargin.mBorderWidth,
-                            kBorderWidthIDs);
+  return ParseBoxProperties(kBorderWidthIDs);
 }
 
 PRBool
-CSSParserImpl::ParseBorderColors(nsCSSValueList** aResult,
-                                 nsCSSProperty aProperty)
-{
-  nsCSSValueList *list = nsnull;
-  for (nsCSSValueList **curp = &list, *cur; ; curp = &cur->mNext) {
-    cur = *curp = new nsCSSValueList();
-    if (!cur) {
-      mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
-      break;
-    }
-    if (!ParseVariant(cur->mValue,
-                      (cur == list)
-                        ? (VARIANT_HCK | VARIANT_NONE)
-                        : (VARIANT_COLOR | VARIANT_KEYWORD),
-                      nsCSSProps::kBorderColorKTable)) {
-      break;
-    }
-    if (ExpectEndProperty()) {
-      // Only success case here, since having the failure case at the
-      // end allows more sharing of code.
-      mTempData.SetPropertyBit(aProperty);
-      *aResult = list;
-      return PR_TRUE;
-    }
-    if (cur->mValue.GetUnit() == eCSSUnit_Inherit ||
-        cur->mValue.GetUnit() == eCSSUnit_Initial ||
-        cur->mValue.GetUnit() == eCSSUnit_None) {
-      // 'inherit', 'initial', and 'none' are only allowed on their own
-      break;
-    }
-  }
-  // Have failure case at the end so we can |break| to get to it.
-  delete list;
-  return PR_FALSE;
+CSSParserImpl::ParseBorderColors(nsCSSProperty aProperty)
+{
+  nsCSSValue value;
+  if (ParseVariant(value, VARIANT_INHERIT | VARIANT_NONE, nsnull)) {
+    // 'inherit', 'initial', and 'none' are only allowed on their own
+    if (!ExpectEndProperty()) {
+      return PR_FALSE;
+    }
+  } else {
+    nsCSSValueList *cur = value.SetListValue();
+    for (;;) {
+      if (!ParseVariant(cur->mValue, VARIANT_COLOR | VARIANT_KEYWORD,
+                        nsCSSProps::kBorderColorKTable)) {
+        return PR_FALSE;
+      }
+      if (CheckEndProperty()) {
+        break;
+      }
+      cur->mNext = new nsCSSValueList;
+      cur = cur->mNext;
+    }
+  }
+  AppendValue(aProperty, value);
+  return PR_TRUE;
 }
 
 static PRBool
 HasMinMax(const nsCSSValue::Array *aArray)
 {
   for (PRUint32 i = 0, i_end = aArray->Count(); i != i_end; ++i) {
     const nsCSSValue &v = aArray->Item(i);
     if (v.IsCalcUnit() &&
@@ -7398,206 +7277,164 @@ CSSParserImpl::RequireWhitespace()
   // Skip any additional whitespace tokens.
   if (GetToken(PR_TRUE)) {
     UngetToken();
   }
   return PR_TRUE;
 }
 
 PRBool
-CSSParserImpl::ParseRect(nsCSSRect& aRect, nsCSSProperty aPropID)
-{
-  nsCSSRect rect;
-  PRBool result;
-  if ((result = DoParseRect(rect)) &&
-      rect != aRect) {
-    aRect = rect;
-    mTempData.SetPropertyBit(aPropID);
-  }
-  return result;
-}
-
-PRBool
-CSSParserImpl::DoParseRect(nsCSSRect& aRect)
+CSSParserImpl::ParseRect(nsCSSProperty aPropID)
 {
   if (! GetToken(PR_TRUE)) {
     return PR_FALSE;
   }
-  if (eCSSToken_Ident == mToken.mType) {
+
+  nsCSSValue val;
+
+  if (mToken.mType == eCSSToken_Ident) {
     nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent);
     switch (keyword) {
       case eCSSKeyword_auto:
-        if (ExpectEndProperty()) {
-          aRect.SetAllSidesTo(nsCSSValue(eCSSUnit_RectIsAuto));
-          return PR_TRUE;
+        if (!ExpectEndProperty()) {
+          return PR_FALSE;
         }
+        val.SetAutoValue();
         break;
       case eCSSKeyword_inherit:
-        if (ExpectEndProperty()) {
-          aRect.SetAllSidesTo(nsCSSValue(eCSSUnit_Inherit));
-          return PR_TRUE;
+        if (!ExpectEndProperty()) {
+          return PR_FALSE;
         }
+        val.SetInheritValue();
         break;
       case eCSSKeyword__moz_initial:
-        if (ExpectEndProperty()) {
-          aRect.SetAllSidesTo(nsCSSValue(eCSSUnit_Initial));
-          return PR_TRUE;
+        if (!ExpectEndProperty()) {
+          return PR_FALSE;
         }
+        val.SetInitialValue();
         break;
       default:
         UngetToken();
-        break;
-    }
-  } else if ((eCSSToken_Function == mToken.mType) &&
+        return PR_FALSE;
+    }
+  } else if (mToken.mType == eCSSToken_Function &&
              mToken.mIdent.LowerCaseEqualsLiteral("rect")) {
+    nsCSSRect& rect = val.SetRectValue();
     NS_FOR_CSS_SIDES(side) {
-      if (! ParseVariant(aRect.*(nsCSSRect::sides[side]),
+      if (! ParseVariant(rect.*(nsCSSRect::sides[side]),
                          VARIANT_AL, nsnull)) {
         return PR_FALSE;
       }
-      if (3 != side) {
+      if (side < 3) {
         // skip optional commas between elements
         (void)ExpectSymbol(',', PR_TRUE);
       }
     }
     if (!ExpectSymbol(')', PR_TRUE)) {
       return PR_FALSE;
     }
-    if (ExpectEndProperty()) {
-      return PR_TRUE;
+    if (!ExpectEndProperty()) {
+      return PR_FALSE;
     }
   } else {
     UngetToken();
-  }
-  return PR_FALSE;
+    return PR_FALSE;
+  }
+
+  AppendValue(aPropID, val);
+  return PR_TRUE;
 }
 
 #define VARIANT_CONTENT (VARIANT_STRING | VARIANT_URL | VARIANT_COUNTER | VARIANT_ATTR | \
                          VARIANT_KEYWORD)
 PRBool
 CSSParserImpl::ParseContent()
 {
-  // XXX Rewrite to make it look more like ParseCursor or ParseCounterData?
-  nsCSSValue  value;
-  if (ParseVariant(value,
-                   VARIANT_CONTENT | VARIANT_INHERIT | VARIANT_NORMAL |
-                     VARIANT_NONE,
-                   nsCSSProps::kContentKTable)) {
-    nsCSSValueList* listHead = new nsCSSValueList();
-    nsCSSValueList* list = listHead;
-    if (nsnull == list) {
-      mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
+  // We need to divide the 'content' keywords into two classes for
+  // ParseVariant's sake, so we can't just use nsCSSProps::kContentKTable.
+  static const PRInt32 kContentListKWs[] = {
+    eCSSKeyword_open_quote, NS_STYLE_CONTENT_OPEN_QUOTE,
+    eCSSKeyword_close_quote, NS_STYLE_CONTENT_CLOSE_QUOTE,
+    eCSSKeyword_no_open_quote, NS_STYLE_CONTENT_NO_OPEN_QUOTE,
+    eCSSKeyword_no_close_quote, NS_STYLE_CONTENT_NO_CLOSE_QUOTE,
+    eCSSKeyword_UNKNOWN,-1
+  };
+
+  static const PRInt32 kContentSolitaryKWs[] = {
+    eCSSKeyword__moz_alt_content, NS_STYLE_CONTENT_ALT_CONTENT,
+    eCSSKeyword_UNKNOWN,-1
+  };
+
+  // Verify that these two lists add up to the size of
+  // nsCSSProps::kContentKTable.
+  NS_ABORT_IF_FALSE(nsCSSProps::kContentKTable[
+                      NS_ARRAY_LENGTH(kContentListKWs) +
+                      NS_ARRAY_LENGTH(kContentSolitaryKWs) - 4] ==
+                    eCSSKeyword_UNKNOWN &&
+                    nsCSSProps::kContentKTable[
+                      NS_ARRAY_LENGTH(kContentListKWs) +
+                      NS_ARRAY_LENGTH(kContentSolitaryKWs) - 3] == -1,
+                    "content keyword tables out of sync");
+
+  nsCSSValue value;
+  if (ParseVariant(value, VARIANT_HMK | VARIANT_NONE,
+                   kContentSolitaryKWs)) {
+    // 'inherit', 'initial', 'normal', 'none', and 'alt-content' must be alone
+    if (!ExpectEndProperty()) {
       return PR_FALSE;
     }
-    list->mValue = value;
-
-    while (nsnull != list) {
-      if (ExpectEndProperty()) {
-        mTempData.SetPropertyBit(eCSSProperty_content);
-        mTempData.mContent.mContent = listHead;
-        return PR_TRUE;
-      }
-      if (eCSSUnit_Inherit == value.GetUnit() ||
-          eCSSUnit_Initial == value.GetUnit() ||
-          eCSSUnit_Normal == value.GetUnit() ||
-          eCSSUnit_None == value.GetUnit() ||
-          (eCSSUnit_Enumerated == value.GetUnit() &&
-           NS_STYLE_CONTENT_ALT_CONTENT == value.GetIntValue())) {
-        // This only matters the first time through the loop.
-        delete listHead;
+  } else {
+    nsCSSValueList* cur = value.SetListValue();
+    for (;;) {
+      if (!ParseVariant(cur->mValue, VARIANT_CONTENT, kContentListKWs)) {
         return PR_FALSE;
       }
-      if (ParseVariant(value, VARIANT_CONTENT, nsCSSProps::kContentKTable) &&
-          // Make sure we didn't end up with NS_STYLE_CONTENT_ALT_CONTENT here
-          (value.GetUnit() != eCSSUnit_Enumerated ||
-           value.GetIntValue() != NS_STYLE_CONTENT_ALT_CONTENT)) {
-        list->mNext = new nsCSSValueList();
-        list = list->mNext;
-        if (nsnull != list) {
-          list->mValue = value;
-        }
-        else {
-          mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
-        }
-      }
-      else {
+      if (CheckEndProperty()) {
         break;
       }
-    }
-    delete listHead;
-  }
-  return PR_FALSE;
-}
-
-struct SingleCounterPropValue {
-  char str[13];
-  nsCSSUnit unit;
-};
+      cur->mNext = new nsCSSValueList;
+      cur = cur->mNext;
+    }
+  }
+  AppendValue(eCSSProperty_content, value);
+  return PR_TRUE;
+}
 
 PRBool
-CSSParserImpl::ParseCounterData(nsCSSValuePairList** aResult,
-                                nsCSSProperty aPropID)
-{
-  nsSubstring* ident = NextIdent();
-  if (nsnull == ident) {
-    return PR_FALSE;
-  }
-  static const SingleCounterPropValue singleValues[] = {
-    { "none", eCSSUnit_None },
-    { "inherit", eCSSUnit_Inherit },
-    { "-moz-initial", eCSSUnit_Initial }
-  };
-  for (const SingleCounterPropValue *sv = singleValues,
-           *sv_end = singleValues + NS_ARRAY_LENGTH(singleValues);
-       sv != sv_end; ++sv) {
-    if (ident->LowerCaseEqualsASCII(sv->str)) {
-      if (CheckEndProperty()) {
-        nsCSSValuePairList* dataHead = new nsCSSValuePairList();
-        if (!dataHead) {
-          mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
-          return PR_FALSE;
-        }
-        dataHead->mXValue = nsCSSValue(sv->unit);
-        *aResult = dataHead;
-        mTempData.SetPropertyBit(aPropID);
-        return PR_TRUE;
-      }
+CSSParserImpl::ParseCounterData(nsCSSProperty aPropID)
+{
+  nsCSSValue value;
+  if (!ParseVariant(value, VARIANT_INHERIT | VARIANT_NONE, nsnull)) {
+    if (!GetToken(PR_TRUE) || mToken.mType != eCSSToken_Ident) {
       return PR_FALSE;
     }
-  }
-  UngetToken(); // undo NextIdent
-
-  nsCSSValuePairList* dataHead = nsnull;
-  nsCSSValuePairList **next = &dataHead;
-  for (;;) {
-    if (!GetToken(PR_TRUE) || mToken.mType != eCSSToken_Ident) {
-      break;
-    }
-    nsCSSValuePairList *data = *next = new nsCSSValuePairList();
-    if (!data) {
-      mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
-      break;
-    }
-    next = &data->mNext;
-    data->mXValue.SetStringValue(mToken.mIdent, eCSSUnit_Ident);
-    if (GetToken(PR_TRUE)) {
-      if (eCSSToken_Number == mToken.mType && mToken.mIntegerValid) {
-        data->mYValue.SetIntValue(mToken.mInteger, eCSSUnit_Integer);
+
+    nsCSSValuePairList *cur = value.SetPairListValue();
+    for (;;) {
+      cur->mXValue.SetStringValue(mToken.mIdent, eCSSUnit_Ident);
+      if (!GetToken(PR_TRUE)) {
+        break;
+      }
+      if (mToken.mType == eCSSToken_Number && mToken.mIntegerValid) {
+        cur->mYValue.SetIntValue(mToken.mInteger, eCSSUnit_Integer);
       } else {
         UngetToken();
       }
-    }
-    if (ExpectEndProperty()) {
-      mTempData.SetPropertyBit(aPropID);
-      *aResult = dataHead;
-      return PR_TRUE;
-    }
-  }
-  delete dataHead;
-  return PR_FALSE;
+      if (CheckEndProperty()) {
+        break;
+      }
+      if (!GetToken(PR_TRUE) || mToken.mType != eCSSToken_Ident) {
+        return PR_FALSE;
+      }
+      cur->mNext = new nsCSSValuePairList;
+      cur = cur->mNext;
+    }
+  }
+  AppendValue(aPropID, value);
+  return PR_TRUE;
 }
 
 PRBool
 CSSParserImpl::ParseCue()
 {
   nsCSSValue before;
   if (ParseSingleValueProperty(before, eCSSProperty_cue_before)) {
     if (eCSSUnit_Inherit != before.GetUnit() &&
@@ -7619,62 +7456,57 @@ CSSParserImpl::ParseCue()
     }
   }
   return PR_FALSE;
 }
 
 PRBool
 CSSParserImpl::ParseCursor()
 {
-  nsCSSValueList *list = nsnull;
-  for (nsCSSValueList **curp = &list, *cur; ; curp = &cur->mNext) {
-    cur = *curp = new nsCSSValueList();
-    if (!cur) {
-      mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
-      break;
-    }
-    if (!ParseVariant(cur->mValue,
-                      (cur == list) ? VARIANT_HUK : VARIANT_UK,
-                      nsCSSProps::kCursorKTable)) {
-      break;
-    }
-    if (cur->mValue.GetUnit() != eCSSUnit_URL) {
-      if (!ExpectEndProperty()) {
-        break;
-      }
-      // Only success case here, since having the failure case at the
-      // end allows more sharing of code.
-      mTempData.SetPropertyBit(eCSSProperty_cursor);
-      mTempData.mUserInterface.mCursor = list;
-      return PR_TRUE;
-    }
-    // We have a URL, so make a value array with three values.
-    nsRefPtr<nsCSSValue::Array> val = nsCSSValue::Array::Create(3);
-    if (!val) {
-      mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
-      break;
-    }
-    val->Item(0) = cur->mValue;
-    cur->mValue.SetArrayValue(val, eCSSUnit_Array);
-
-    // Parse optional x and y position of cursor hotspot (css3-ui).
-    if (ParseVariant(val->Item(1), VARIANT_NUMBER, nsnull)) {
-      // If we have one number, we must have two.
-      if (!ParseVariant(val->Item(2), VARIANT_NUMBER, nsnull)) {
-        break;
-      }
-    }
-
-    if (!ExpectSymbol(',', PR_TRUE)) {
-      break;
-    }
-  }
-  // Have failure case at the end so we can |break| to get to it.
-  delete list;
-  return PR_FALSE;
+  nsCSSValue value;
+  if (ParseVariant(value, VARIANT_INHERIT, nsnull)) {
+    // 'inherit' and 'initial' must be alone
+    if (!ExpectEndProperty()) {
+      return PR_FALSE;
+    }
+  } else {
+    nsCSSValueList* cur = value.SetListValue();
+    for (;;) {
+      if (!ParseVariant(cur->mValue, VARIANT_UK, nsCSSProps::kCursorKTable)) {
+        return PR_FALSE;
+      }
+      if (cur->mValue.GetUnit() != eCSSUnit_URL) { // keyword must be last
+        if (ExpectEndProperty()) {
+          break;
+        }
+        return PR_FALSE;
+      }
+
+      // We have a URL, so make a value array with three values.
+      nsRefPtr<nsCSSValue::Array> val = nsCSSValue::Array::Create(3);
+      val->Item(0) = cur->mValue;
+
+      // Parse optional x and y position of cursor hotspot (css3-ui).
+      if (ParseVariant(val->Item(1), VARIANT_NUMBER, nsnull)) {
+        // If we have one number, we must have two.
+        if (!ParseVariant(val->Item(2), VARIANT_NUMBER, nsnull)) {
+          return PR_FALSE;
+        }
+      }
+      cur->mValue.SetArrayValue(val, eCSSUnit_Array);
+
+      if (!ExpectSymbol(',', PR_TRUE)) { // url must not be last
+        return PR_FALSE;
+      }
+      cur->mNext = new nsCSSValueList;
+      cur = cur->mNext;
+    }
+  }
+  AppendValue(eCSSProperty_cursor, value);
+  return PR_TRUE;
 }
 
 
 PRBool
 CSSParserImpl::ParseFont()
 {
   static const nsCSSProperty fontIDs[] = {
     eCSSProperty_font_style,
@@ -8078,139 +7910,87 @@ static PRBool GetFunctionParseInformatio
                "Invalid aMaxElems for this variant mask.");
 #endif
 
   // Convert the index into a mask.
   aVariantMask = kVariantMasks[variantIndex];
 
   return PR_TRUE;
 }
-                                          
 
 /* Reads a single transform function from the tokenizer stream, reporting an
  * error if something goes wrong.
  */
-PRBool CSSParserImpl::ReadSingleTransform(nsCSSValueList **& aTail)
-{
-  typedef nsTArray<nsCSSValue>::size_type arrlen_t;
-
+PRBool
+CSSParserImpl::ParseSingleTransform(nsCSSValue& aValue)
+{
   if (!GetToken(PR_TRUE))
     return PR_FALSE;
-  
-  /* Check to make sure that we've read a function. */
+
   if (mToken.mType != eCSSToken_Function) {
     UngetToken();
     return PR_FALSE;
   }
 
-  /* Load up the variant mask information for ParseFunction.  If we can't,
-   * abort.
-   */
   const PRInt32* variantMask;
   PRUint16 minElems, maxElems;
   if (!GetFunctionParseInformation(nsCSSKeywords::LookupKeyword(mToken.mIdent),
                                    minElems, maxElems, variantMask))
     return PR_FALSE;
 
-  /* Create a cell to populate, fail if we're out of memory. */
-  nsAutoPtr<nsCSSValue> newCell(new nsCSSValue);
-  if (!newCell) {
-    mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
-    return PR_FALSE;
-  }
-
-  /* Try reading things in, failing if we can't */
-  if (!ParseFunction(mToken.mIdent, variantMask, minElems, maxElems, *newCell))
-    return PR_FALSE;
-
-  /* Wrap up our result in an nsCSSValueList cell. */
-  nsAutoPtr<nsCSSValueList> toAppend(new nsCSSValueList);
-  if (!toAppend)
-    return PR_FALSE;
-
-  toAppend->mValue = *newCell;
-  
-  /* Chain the element to the end of the transform list, then update the
-   * list.
-   */
-  *aTail = toAppend.forget();
-  aTail = &(*aTail)->mNext;
-  
-  /* It worked!  Return true. */
-  return PR_TRUE;
+  return ParseFunction(mToken.mIdent, variantMask, minElems, maxElems, aValue);
 }
 
 /* Parses a -moz-transform property list by continuously reading in properties
  * and constructing a matrix from it.
  */
 PRBool CSSParserImpl::ParseMozTransform()
 {
-  mTempData.mDisplay.mTransform = nsnull;