Merge mozilla-central to tabcandy-central.
authorEdward Lee <edilee@mozilla.com>
Thu, 12 Aug 2010 03:55:08 -0700
changeset 50342 7e54fcbcd2afccec273d2db1ac9843af2ed61ce7
parent 50341 7e005ace1fb88ac6108f73ca448a691fe780ba6c (current diff)
parent 49686 cdfff833edf962ceb2025de491aea29438e27df2 (diff)
child 50343 874090a047df65424fecb72ddba91a9b119f158f
push idunknown
push userunknown
push dateunknown
milestone2.0b4pre
Merge mozilla-central to tabcandy-central.
browser/base/content/browser-places.js
browser/base/content/browser-sets.inc
browser/base/content/browser.js
browser/base/content/browser.xul
browser/base/content/tabbrowser.xml
browser/base/content/test/Makefile.in
browser/base/content/test/browser_visibleTabs.js
browser/components/sessionstore/src/nsSessionStore.js
browser/locales/en-US/chrome/browser/browser.dtd
browser/themes/gnomestripe/browser/browser.css
browser/themes/pinstripe/browser/browser.css
browser/themes/winstripe/browser/browser.css
toolkit/content/Geometry.jsm
toolkit/content/Makefile.in
toolkit/content/tests/browser/Makefile.in
toolkit/content/tests/browser/browser_Geometry.js
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/chrome.manifest
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/chrome.manifest
@@ -1,14 +1,16 @@
 resource testpilot ./
 content testpilot content/
 skin testpilot skin skin/all/
 skin testpilot-os skin skin/linux/ os=Linux
 skin testpilot-os skin skin/mac/ os=Darwin
 skin testpilot-os skin skin/win/ os=WINNT
+overlay chrome://browser/content/macBrowserOverlay.xul chrome://testpilot/content/tp-browser.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} appversion<4.0b1pre
+overlay chrome://browser/content/macBrowserOverlay.xul chrome://testpilot/content/feedback-browser.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} appversion>=4.0b1pre
 overlay chrome://browser/content/browser.xul chrome://testpilot/content/tp-browser.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} appversion<=3.6.*
 overlay chrome://browser/content/browser.xul chrome://testpilot/content/feedback-browser.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} appversion>3.7a1pre
 # For the menubar on Mac
 overlay chrome://testpilot/content/all-studies-window.xul chrome://browser/content/macBrowserOverlay.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} os=Darwin
 
 component {e6e5e58f-7977-485a-b076-2f74bee2677b} components/TestPilot.js
 contract @mozilla.org/testpilot/service;1 {e6e5e58f-7977-485a-b076-2f74bee2677b}
 category profile-after-change testpilot @mozilla.org/testpilot/service;1
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/all-studies-window.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/all-studies-window.js
@@ -281,21 +281,19 @@ var TestPilotXulWindow = {
       this.addThumbnail(newRow, task.thumbnail);
 
       let textVbox = document.createElement("vbox");
       newRow.appendChild(textVbox);
 
       let openInTab = (task.taskType == TaskConstants.TYPE_LEGACY);
 
       this.addDescription(textVbox, task.title, task.summary);
-      if (task.showMoreInfoLink) {
-        this.addXulLink(
-          textVbox, this._stringBundle.getString("testpilot.moreInfo"),
-          task.defaultUrl, openInTab);
-      }
+      this.addXulLink(
+        textVbox, this._stringBundle.getString("testpilot.moreInfo"),
+        task.defaultUrl, openInTab);
 
       // Create the rightmost status area, depending on status:
       let statusVbox = document.createElement("vbox");
       if (task.status == TaskConstants.STATUS_FINISHED) {
         this.addLabel(
           statusVbox,
           this._stringBundle.getFormattedString(
             "testpilot.studiesWindow.finishedOn",
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/browser.css
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/browser.css
@@ -2,18 +2,20 @@
 
 #feedback-menu-button {
   -moz-box-orient: horizontal;
 }
 
 #feedback-menu-button .toolbarbutton-text {
   display: -moz-box;
   margin: 0;
+  color: -moz-dialogtext;
+  text-shadow: none;
 }
- 
+
 #feedback-menu-button .toolbarbutton-icon {
   display: none;
 }
 
 #feedback-menu-button .toolbarbutton-menu-dropmarker {
   -moz-padding-start: 5px;
 }
 
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/tasks.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/tasks.js
@@ -161,20 +161,16 @@ var TestPilotTask = {
     return this.infoPageUrl;
   },
 
   get uploadUrl() {
     let url = Application.prefs.getValue(DATA_UPLOAD_PREF, "");
     return url + this._id;
   },
 
-  get showMoreInfoLink() {
-    return true;
-  },
-
   // event handlers:
 
   onExperimentStartup: function TestPilotTask_onExperimentStartup() {
   },
 
   onExperimentShutdown: function TestPilotTask_onExperimentShutdown() {
   },
 
@@ -1016,20 +1012,16 @@ TestPilotWebSurvey.prototype = {
   get taskType() {
     return TaskConstants.TYPE_SURVEY;
   },
 
   get defaultUrl() {
     return this.infoPageUrl;
   },
 
-  get showMoreInfoLink() {
-    return false;
-  },
-
   onDetailPageOpened: function TPWS_onDetailPageOpened() {
     /* Once you view the URL of the survey, we'll assume you've taken it.
      * There's no reliable way to tell whether you have or not, so let's
      * default to not bugging the user about it again.
      */
     if (this._status < TaskConstants.STATUS_SUBMITTED) {
       this.changeStatus( TaskConstants.STATUS_SUBMITTED, true );
     }
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -6772,36 +6772,34 @@ var gBookmarkAllTabsHandler = {
     this._command = document.getElementById("Browser:BookmarkAllTabs");
     gBrowser.tabContainer.addEventListener("TabOpen", this, true);
     gBrowser.tabContainer.addEventListener("TabClose", this, true);
     gBrowser.tabContainer.addEventListener("TabSelect", this, true);
     gBrowser.tabContainer.addEventListener("TabMove", this, true);
     this._updateCommandState();
   },
 
-  _updateCommandState: function BATH__updateCommandState(aTabClose) {
-    let numTabs = gBrowser.visibleTabs.length;
-
-    // The TabClose event is fired before the tab is removed from the DOM
-    if (aTabClose)
-      numTabs--;
-
-    if (numTabs > 1)
+  _updateCommandState: function BATH__updateCommandState() {
+    let remainingTabs = gBrowser.visibleTabs.filter(function(tab) {
+      return gBrowser._removingTabs.indexOf(tab) == -1;
+    });
+
+    if (remainingTabs.length > 1)
       this._command.removeAttribute("disabled");
     else
       this._command.setAttribute("disabled", "true");
   },
 
   doCommand: function BATH_doCommand() {
     PlacesCommandHook.bookmarkCurrentPages();
   },
 
   // nsIDOMEventListener
   handleEvent: function(aEvent) {
-    this._updateCommandState(aEvent.type == "TabClose");
+    this._updateCommandState();
   }
 };
 
 /**
  * Utility object to handle manipulations of the identity indicators in the UI
  */
 var gIdentityHandler = {
   // Mode strings used to control CSS display
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1020,29 +1020,30 @@
           // the next of many URLs opened) or if the pref to have UI links opened in
           // the background is set (i.e. the link is not being opened modally)
           //
           // i.e.
           //    Number of URLs    Load UI Links in BG       Focus Last Viewed?
           //    == 1              false                     YES
           //    == 1              true                      NO
           //    > 1               false/true                NO
-          var owner = (aURIs.length > 1) || aLoadInBackground ? null : this.selectedTab;
+          var multiple = aURIs.length > 1;
+          var owner = multiple || aLoadInBackground ? null : this.selectedTab;
           var firstTabAdded = null;
 
           if (aReplace) {
             try {
               this.loadURI(aURIs[0], null, null);
             } catch (e) {
               // Ignore failure in case a URI is wrong, so we can continue
               // opening the next ones.
             }
           }
           else
-            firstTabAdded = this.addTab(aURIs[0], {ownerTab: owner, skipAnimation: true});
+            firstTabAdded = this.addTab(aURIs[0], {ownerTab: owner, skipAnimation: multiple});
 
           var tabNum = this.tabContainer.selectedIndex;
           for (let i = 1; i < aURIs.length; ++i) {
             let tab = this.addTab(aURIs[i], {skipAnimation: true});
             if (aReplace)
               this.moveTabTo(tab, ++tabNum);
           }
 
@@ -1328,20 +1329,29 @@
         []
       </field>
 
       <method name="removeTab">
         <parameter name="aTab"/>
         <parameter name="aParams"/>
         <body>
           <![CDATA[
-            var isLastTab = (this.tabs.length - this._removingTabs.length == 1);
             if (aParams)
               var animate = aParams.animate;
 
+            // Handle requests for synchronously removing an already
+            // asynchronously closing tab.
+            if (!animate &&
+                this._removingTabs.indexOf(aTab) > -1) {
+              this._endRemoveTab(aTab);
+              return;
+            }
+
+            var isLastTab = (this.tabs.length - this._removingTabs.length == 1);
+
             if (!this._beginRemoveTab(aTab, false, null, true))
               return;
 
             /* Don't animate if:
                 - the caller didn't opt in
                 - this is the last tab in the window
                 - this is a pinned tab
                 - a bunch of other tabs are already closing (arbitrary threshold)
@@ -1571,31 +1581,41 @@
             if (aTab.owner &&
                 this._removingTabs.indexOf(aTab.owner) == -1 &&
                 Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose")) {
               this.selectedTab = aTab.owner;
               return;
             }
 
             let removing = this._removingTabs;
-            let ignoreRemoving = function(tab) removing.indexOf(tab) == -1;
+            function keepRemaining(tab) {
+              // A tab remains only if it's not being removed nor blurred
+              return removing.indexOf(tab) == -1 && tab != aTab;
+            }
 
             // Switch to a visible tab unless there aren't any remaining
-            let remainingTabs = this.visibleTabs.filter(ignoreRemoving);
+            let remainingTabs = this.visibleTabs.filter(keepRemaining);
             if (remainingTabs.length == 0)
-              remainingTabs = Array.filter(this.tabs, ignoreRemoving);
+              remainingTabs = Array.filter(this.tabs, keepRemaining);
 
             // Try to find a remaining tab that comes after the given tab
             var tab = aTab;
             do {
               tab = tab.nextSibling;
             } while (tab && remainingTabs.indexOf(tab) == -1);
 
-            // If no tab was found, give the end of the remaining tabs
-            this.selectedTab = tab ? tab : remainingTabs.pop();
+            if (!tab) {
+              tab = aTab;
+
+              do {
+                tab = tab.previousSibling;
+              } while (tab && remainingTabs.indexOf(tab) == -1);
+            }
+
+            this.selectedTab = tab;
           ]]>
         </body>
       </method>
 
       <method name="swapBrowsersAndCloseOther">
         <parameter name="aOurTab"/>
         <parameter name="aOtherTab"/>
         <body>
@@ -1781,21 +1801,18 @@
         <body>
         <![CDATA[
           let tabs = this.visibleTabs;
 
           // count backwards for aIndex < 0
           if (aIndex < 0)
             aIndex += tabs.length;
 
-          if (aIndex >= 0 && aIndex < tabs.length) {
-            let nextTab = tabs[aIndex];
-            if (nextTab != this.selectedTab)
-              this.selectedTab = nextTab;
-          }
+          if (aIndex >= 0 && aIndex < tabs.length)
+            this.selectedTab = tabs[aIndex];
 
           if (aEvent) {
             aEvent.preventDefault();
             aEvent.stopPropagation();
           }
         ]]>
         </body>
       </method>
@@ -2412,31 +2429,31 @@
       <method name="_getScrollableElements">
         <body><![CDATA[
           return Array.filter(document.getBindingParent(this).childNodes,
                               this._canScrollToElement, this);
         ]]></body>
       </method>
       <method name="_canScrollToElement">
         <parameter name="tab"/>
-        <body>
-          return !tab.pinned;
-        </body>
+        <body><![CDATA[
+          return !tab.pinned && !tab.hidden;
+        ]]></body>
       </method>
     </implementation>
 
     <handlers>
       <handler event="underflow"><![CDATA[
          if (event.detail == 0)
            return; // Ignore vertical events
 
          var tabs = document.getBindingParent(this);
          tabs.removeAttribute("overflow");
 
-         tabs.tabbrowser._removingTabs.forEach(tabs.tabbrowser._endRemoveTab,
+         tabs.tabbrowser._removingTabs.forEach(tabs.tabbrowser.removeTab,
                                                tabs.tabbrowser);
 
          tabs._positionPinnedTabs();
       ]]></handler>
       <handler event="overflow"><![CDATA[
          if (event.detail == 0)
            return; // Ignore vertical events
 
@@ -2591,19 +2608,18 @@
               this.setAttribute("closebuttons", "noclose");
             else
               this.setAttribute("closebuttons", "activetab");
             break;
           case 1:
             if (this.childNodes.length == 1 && this._closeWindowWithLastTab)
               this.setAttribute("closebuttons", "noclose");
             else {
-              let tab = this.childNodes.item(this.tabbrowser._numPinnedTabs);
-              if (tab && tab.hidden)
-                tab = this.tabbrowser.visibleTabs[0];
+              // Grab the last tab for size comparison
+              let tab = this.tabbrowser.visibleTabs.pop();
               if (tab && tab.getBoundingClientRect().width > this.mTabClipWidth)
                 this.setAttribute("closebuttons", "alltabs");
               else
                 this.setAttribute("closebuttons", "activetab");
             }
             break;
           case 2:
           case 3:
--- a/browser/base/content/test/browser_bug380960.js
+++ b/browser/base/content/test/browser_bug380960.js
@@ -1,15 +1,20 @@
 function test() {
   gBrowser.tabContainer.addEventListener("TabOpen", tabAdded, false);
 
   var tab = gBrowser.addTab("about:blank", { skipAnimation: true });
   gBrowser.removeTab(tab);
   is(tab.parentNode, null, "tab removed immediately");
 
+  tab = gBrowser.addTab("about:blank", { skipAnimation: true });
+  gBrowser.removeTab(tab, { animate: true });
+  gBrowser.removeTab(tab);
+  is(tab.parentNode, null, "tab removed immediately when calling removeTab again after the animation was kicked off");
+
   waitForExplicitFinish();
 
   Services.prefs.setBoolPref("browser.tabs.animate", true);
   nextAsyncText();
 }
 
 function tabAdded() {
   info("tab added");
--- a/browser/base/content/test/browser_visibleTabs.js
+++ b/browser/base/content/test/browser_visibleTabs.js
@@ -14,17 +14,17 @@
  * The Original Code is tabbrowser visibleTabs test.
  *
  * The Initial Developer of the Original Code is
  * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2010
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
- *   Edward Lee <edilee@mozilla.com>
+ * Edward Lee <edilee@mozilla.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
--- a/browser/components/sessionstore/test/browser/Makefile.in
+++ b/browser/components/sessionstore/test/browser/Makefile.in
@@ -110,12 +110,13 @@ include $(topsrcdir)/config/rules.mk
 	browser_493467.js \
 	browser_495495.js \
 	browser_500328.js \
 	browser_514751.js \
 	browser_522545.js \
 	browser_524745.js \
 	browser_528776.js \
 	browser_579879.js \
+	browser_586147.js \
 	$(NULL)
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser/browser_586147.js
@@ -0,0 +1,84 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is sessionstore test code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Edward Lee <edilee@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+function observeOneRestore(callback) {
+  let topic = "sessionstore-browser-state-restored";
+  Services.obs.addObserver(function() {
+    Services.obs.removeObserver(arguments.callee, topic, false);
+    callback();
+  }, topic, false);
+};
+
+function test() {
+  let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
+  waitForExplicitFinish();
+
+  // There should be one tab when we start the test
+  let [origTab] = gBrowser.visibleTabs;
+  let hiddenTab = gBrowser.addTab();
+
+  is(gBrowser.visibleTabs.length, 2, "should have 2 tabs before hiding");
+  gBrowser.showOnlyTheseTabs([origTab]);
+  is(gBrowser.visibleTabs.length, 1, "only 1 after hiding");
+  ok(hiddenTab.hidden, "sanity check that it's hidden");
+
+  let extraTab = gBrowser.addTab();
+  let state = ss.getBrowserState();
+  let stateObj = JSON.parse(state);
+  let tabs = stateObj.windows[0].tabs;
+  is(tabs.length, 3, "just checking that browser state is correct");
+  ok(!tabs[0].hidden, "first tab is visible");
+  ok(tabs[1].hidden, "second is hidden");
+  ok(!tabs[2].hidden, "third is visible");
+
+  // Make the third tab hidden and then restore the modified state object
+  tabs[2].hidden = true;
+
+  observeOneRestore(function() {
+    let testWindow = Services.wm.getEnumerator("navigator:browser").getNext();
+    is(testWindow.gBrowser.visibleTabs.length, 1, "only restored 1 visible tab");
+    let tabs = testWindow.gBrowser.tabs;
+    ok(!tabs[0].hidden, "first is still visible");
+    ok(tabs[1].hidden, "second tab is still hidden");
+    ok(tabs[2].hidden, "third tab is now hidden");
+
+    // Restore the original state and clean up now that we're done
+    gBrowser.removeTab(hiddenTab);
+    gBrowser.removeTab(extraTab);
+    finish();
+  });
+  ss.setBrowserState(JSON.stringify(stateObj));
+}
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -6,34 +6,38 @@
 .autoreg
 @DLL_PREFIX@jsj@DLL_SUFFIX@
 @DLL_PREFIX@sqlite3@DLL_SUFFIX@
 @DLL_PREFIX@xpcom_compat@DLL_SUFFIX@
 @DLL_PREFIX@xpistub@DLL_SUFFIX@
 @DLL_PREFIX@zlib@DLL_SUFFIX@
 LICENSE
 browserconfig.properties
-chrome.manifest
 chrome/US.jar
 chrome/app-chrome.manifest
+chrome/browser.manifest
 chrome/chrome.rdf
 chrome/chromelist.txt
 chrome/classic.jar
 chrome/classic.manifest
 chrome/comm.jar
 chrome/comm.manifest
 chrome/en-win.jar
+chrome/en-US.manifest
 chrome/help.jar
 chrome/installed-chrome.txt
 chrome/m3ffxtbr.jar
 chrome/m3ffxtbr.manifest
 chrome/overlayinfo/
+chrome/pippki.manifest
 chrome/reporter.jar
 chrome/reporter.manifest
+chrome/toolkit.manifest
 component.reg
+components/browser.manifest
 components/components.list
 components/@DLL_PREFIX@browserdirprovider@DLL_SUFFIX@
 components/@DLL_PREFIX@brwsrdir@DLL_SUFFIX@
 components/@DLL_PREFIX@myspell@DLL_SUFFIX@
 components/@DLL_PREFIX@spellchecker@DLL_SUFFIX@
 components/@DLL_PREFIX@spellchk@DLL_SUFFIX@
 components/aboutCertError.js
 components/aboutPrivateBrowsing.js
--- a/browser/themes/gnomestripe/browser/browser.css
+++ b/browser/themes/gnomestripe/browser/browser.css
@@ -877,17 +877,17 @@ toolbar[iconsize="small"] #fullscreen-bu
   color: -moz-dialogtext;
   -moz-border-end: 1px solid ThreeDShadow;
 }
 
 #identity-box:-moz-locale-dir(rtl) {
   -moz-border-start: 1px solid ThreeDShadow;
 }
 
-#identity-box:focus {
+#identity-box:-moz-focusring {
   outline: 1px dotted -moz-DialogText;
 }
 
 #identity-box:hover {
   background-image: -moz-linear-gradient(rgba(255,255,255,.5), rgba(50%,50%,50%,.2), rgba(0,0,0,.15));
 }
 
 #identity-box:hover:active,
--- a/browser/themes/pinstripe/browser/browser.css
+++ b/browser/themes/pinstripe/browser/browser.css
@@ -700,17 +700,17 @@ toolbar[iconsize="small"][mode="icons"] 
   margin: 1px;
   -moz-border-radius: 2px;
   padding: 1px;
   -moz-box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
   text-shadow: 0 1px rgba(255, 255, 255, 0.2);
 }
 
 
-#identity-box:focus:not(:active):not([open="true"]) {
+#identity-box:-moz-focusring {
   -moz-box-shadow: 0 0 3px 1px -moz-mac-focusring inset,
                    0 0 3px 2px -moz-mac-focusring;
 }
 
 #identity-box {
   color: white;
   text-shadow: 0 1px 1px rgba(0, 0, 0, 0.7);
   -moz-margin-end: 3px;
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -55,38 +55,39 @@
 }
 
 #main-menubar {
   -moz-box-flex: 1; /* make menu items expand to fill toolbar height */
 }
 
 #navigator-toolbox {
   -moz-appearance: none;
+  background-color: transparent;
   border-top: none;
-  background-color: transparent;
-}
-
-#navigator-toolbox[tabsontop="true"] {
   border-bottom: 1px solid ThreeDShadow;
 }
 
 #navigator-toolbox > toolbar:not(:-moz-lwtheme) {
   -moz-appearance: none;
   border-style: none;
   background-color: -moz-Dialog;
 }
 
 #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar)[iconsize="small"],
 #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar)[defaulticonsize="small"]:not([iconsize]) {
   padding-top: 1px;
   padding-bottom: 1px;
 }
 
 #nav-bar:not(:-moz-lwtheme),
-#navigator-toolbox[tabsontop="true"] > #nav-bar {
+#nav-bar[collapsed="true"] + toolbar:not(:-moz-lwtheme),
+#nav-bar[collapsed="true"] + #customToolbars + #PersonalToolbar:not(:-moz-lwtheme),
+#navigator-toolbox[tabsontop="true"] > #nav-bar,
+#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + toolbar,
+#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + #customToolbars + #PersonalToolbar {
   background-image: -moz-linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
 }
 
 #navigator-toolbox[tabsontop="false"] > #toolbar-menubar:not(:-moz-lwtheme) {
   background-image: -moz-linear-gradient(@toolbarHighlight@, @toolbarHighlight@);
 }
 
 #personal-bookmarks {
@@ -845,23 +846,23 @@ toolbar:not([iconsize="small"])[mode="ic
 #identity-box.verifiedDomain {
   background-color: hsl(219,45%,60%);
 }
 
 #identity-box.verifiedIdentity {
   background-color: hsl(92,45%,52%);
 }
 
-#identity-box:focus {
+#identity-box:-moz-focusring {
   outline: 1px dotted -moz-DialogText;
   outline-offset: -3px;
 }
 
-#identity-box.verifiedDomain:focus ,
-#identity-box.verifiedIdentity:focus {
+#identity-box.verifiedDomain:-moz-focusring,
+#identity-box.verifiedIdentity:-moz-focusring {
   outline-color: white;
 }
 
 #identity-icon-labels {
   -moz-margin-start: 1px;
   -moz-margin-end: 3px;
   -moz-transform: translate(0, -1px);
 }
@@ -1116,20 +1117,16 @@ richlistitem[type="action"][actiontype="
   background-image: -moz-linear-gradient(transparent, transparent 50%,
                                          rgba(0,0,0,.05) 90%, rgba(0,0,0,.1));
 }
 
 #TabsToolbar[tabsontop="true"]:not(:-moz-lwtheme) {
   -moz-box-shadow: 0 -1px ThreeDShadow inset;
 }
 
-#TabsToolbar[tabsontop="false"] {
-  border-bottom: 1px solid ThreeDShadow !important;
-}
-
 .tabbrowser-tabs:-moz-system-metric(touch-enabled) {
   min-height: .73cm;
 }
 
 .tabbrowser-tabs:not([overflow="true"]) {
   -moz-margin-start: 3px;
 }
 
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -432,17 +432,17 @@ public:
    * shared among multiple presentation shells). The caller of this
    * method is responsible for calling BeginObservingDocument() on the
    * presshell if the presshell should observe document mutations.
    */
   virtual nsresult CreateShell(nsPresContext* aContext,
                                nsIViewManager* aViewManager,
                                nsStyleSet* aStyleSet,
                                nsIPresShell** aInstancePtrResult) = 0;
-  void DeleteShell() { mPresShell = nsnull; }
+  virtual void DeleteShell() = 0;
 
   nsIPresShell* GetShell() const
   {
     return mShellIsHidden ? nsnull : mPresShell;
   }
 
   void SetShellHidden(PRBool aHide) { mShellIsHidden = aHide; }
   PRBool ShellIsHidden() const { return mShellIsHidden; }
--- a/content/base/src/nsAttrValue.cpp
+++ b/content/base/src/nsAttrValue.cpp
@@ -244,17 +244,17 @@ nsAttrValue::SetTo(const nsAttrValue& aO
     case eCSSStyleRule:
     {
       NS_ADDREF(cont->mCSSStyleRule = otherCont->mCSSStyleRule);
       break;
     }
     case eAtomArray:
     {
       if (!EnsureEmptyAtomArray() ||
-          !GetAtomArrayValue()->AppendObjects(*otherCont->mAtomArray)) {
+          !GetAtomArrayValue()->AppendElements(*otherCont->mAtomArray)) {
         Reset();
         return;
       }
       break;
     }
 #ifdef MOZ_SVG
     case eSVGValue:
     {
@@ -498,27 +498,27 @@ nsAttrValue::GetEnumString(nsAString& aR
       return;
     }
     table++;
   }
 
   NS_NOTREACHED("couldn't find value in EnumTable");
 }
 
-PRInt32
+PRUint32
 nsAttrValue::GetAtomCount() const
 {
   ValueType type = Type();
 
   if (type == eAtom) {
     return 1;
   }
 
   if (type == eAtomArray) {
-    return GetAtomArrayValue()->Count();
+    return GetAtomArrayValue()->Length();
   }
 
   return 0;
 }
 
 nsIAtom*
 nsAttrValue::AtomAt(PRInt32 aIndex) const
 {
@@ -526,17 +526,17 @@ nsAttrValue::AtomAt(PRInt32 aIndex) cons
   NS_PRECONDITION(GetAtomCount() > aIndex, "aIndex out of range");
   
   if (BaseType() == eAtomBase) {
     return GetAtomValue();
   }
 
   NS_ASSERTION(Type() == eAtomArray, "GetAtomCount must be confused");
   
-  return GetAtomArrayValue()->ObjectAt(aIndex);
+  return GetAtomArrayValue()->ElementAt(aIndex);
 }
 
 PRUint32
 nsAttrValue::HashValue() const
 {
   switch(BaseType()) {
     case eStringBase:
     {
@@ -587,19 +587,21 @@ nsAttrValue::HashValue() const
     }
     case eCSSStyleRule:
     {
       return NS_PTR_TO_INT32(cont->mCSSStyleRule);
     }
     case eAtomArray:
     {
       PRUint32 retval = 0;
-      PRInt32 i, count = cont->mAtomArray->Count();
-      for (i = 0; i < count; ++i) {
-        retval ^= NS_PTR_TO_INT32(cont->mAtomArray->ObjectAt(i));
+      PRUint32 count = cont->mAtomArray->Length();
+      for (nsCOMPtr<nsIAtom> *cur = cont->mAtomArray->Elements(),
+                             *end = cur + count;
+           cur != end; ++cur) {
+        retval ^= NS_PTR_TO_INT32(cur->get());
       }
       return retval;
     }
 #ifdef MOZ_SVG
     case eSVGValue:
     {
       return NS_PTR_TO_INT32(cont->mSVGValue);
     }
@@ -685,28 +687,20 @@ nsAttrValue::Equals(const nsAttrValue& a
     {
       return thisCont->mCSSStyleRule == otherCont->mCSSStyleRule;
     }
     case eAtomArray:
     {
       // For classlists we could be insensitive to order, however
       // classlists are never mapped attributes so they are never compared.
 
-      PRInt32 count = thisCont->mAtomArray->Count();
-      if (count != otherCont->mAtomArray->Count()) {
+      if (!(*thisCont->mAtomArray == *otherCont->mAtomArray)) {
         return PR_FALSE;
       }
 
-      PRInt32 i;
-      for (i = 0; i < count; ++i) {
-        if (thisCont->mAtomArray->ObjectAt(i) !=
-            otherCont->mAtomArray->ObjectAt(i)) {
-          return PR_FALSE;
-        }
-      }
       needsStringComparison = PR_TRUE;
       break;
     }
 #ifdef MOZ_SVG
     case eSVGValue:
     {
       return thisCont->mSVGValue == otherCont->mSVGValue;
     }
@@ -822,29 +816,31 @@ nsAttrValue::Contains(nsIAtom* aValue, n
       // string comparison. This is only used for quirks mode anyway.
       return
         nsContentUtils::EqualsIgnoreASCIICase(nsDependentAtomString(aValue),
                                               nsDependentAtomString(atom));
     }
     default:
     {
       if (Type() == eAtomArray) {
-        nsCOMArray<nsIAtom>* array = GetAtomArrayValue();
+        AtomArray* array = GetAtomArrayValue();
         if (aCaseSensitive == eCaseMatters) {
-          return array->IndexOf(aValue) >= 0;
+          return array->IndexOf(aValue) != AtomArray::NoIndex;
         }
 
         nsDependentAtomString val1(aValue);
 
-        for (PRInt32 i = 0, count = array->Count(); i < count; ++i) {
+        for (nsCOMPtr<nsIAtom> *cur = array->Elements(),
+                               *end = cur + array->Length();
+             cur != end; ++cur) {
           // For performance reasons, don't do a full on unicode case
           // insensitive string comparison. This is only used for quirks mode
           // anyway.
           if (nsContentUtils::EqualsIgnoreASCIICase(val1,
-                nsDependentAtomString(array->ObjectAt(i)))) {
+                nsDependentAtomString(*cur))) {
             return PR_TRUE;
           }
         }
       }
     }
   }
 
   return PR_FALSE;
@@ -908,34 +904,34 @@ nsAttrValue::ParseAtomArray(const nsAStr
     SetPtrValueAndType(atom, eAtomBase);
     return;
   }
 
   if (!EnsureEmptyAtomArray()) {
     return;
   }
 
-  nsCOMArray<nsIAtom>* array = GetAtomArrayValue();
+  AtomArray* array = GetAtomArrayValue();
   
-  if (!array->AppendObject(classAtom)) {
+  if (!array->AppendElement(classAtom)) {
     Reset();
     return;
   }
 
   // parse the rest of the classnames
   while (iter != end) {
     start = iter;
 
     do {
       ++iter;
     } while (iter != end && !nsContentUtils::IsHTMLWhitespace(*iter));
 
     classAtom = do_GetAtom(Substring(start, iter));
 
-    if (!array->AppendObject(classAtom)) {
+    if (!array->AppendElement(classAtom)) {
       Reset();
       return;
     }
 
     // skip whitespace
     while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
       ++iter;
     }
@@ -1357,17 +1353,17 @@ nsAttrValue::EnsureEmptyAtomArray()
     return PR_TRUE;
   }
 
   if (!EnsureEmptyMiscContainer()) {
     // should already be reset
     return PR_FALSE;
   }
 
-  nsCOMArray<nsIAtom>* array = new nsCOMArray<nsIAtom>;
+  AtomArray* array = new AtomArray;
   if (!array) {
     Reset();
     return PR_FALSE;
   }
 
   MiscContainer* cont = GetMiscContainer();
   cont->mAtomArray = array;
   cont->mType = eAtomArray;
--- a/content/base/src/nsAttrValue.h
+++ b/content/base/src/nsAttrValue.h
@@ -45,24 +45,25 @@
 #define nsAttrValue_h___
 
 #include "nscore.h"
 #include "nsString.h"
 #include "nsStringBuffer.h"
 #include "nsColor.h"
 #include "nsCaseTreatment.h"
 #include "nsMargin.h"
+#include "nsCOMPtr.h"
 
 typedef PRUptrdiff PtrBits;
 class nsAString;
 class nsIAtom;
 class nsICSSStyleRule;
 class nsISVGValue;
 class nsIDocument;
-template<class E> class nsCOMArray;
+template<class E> class nsTArray;
 template<class E> class nsTPtrArray;
 
 #define NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM 12
 
 #define NS_ATTRVALUE_BASETYPE_MASK (PtrBits(3))
 #define NS_ATTRVALUE_POINTERVALUE_MASK (~NS_ATTRVALUE_BASETYPE_MASK)
 
 #define NS_ATTRVALUE_INTEGERTYPE_BITS 4
@@ -87,16 +88,18 @@ public:
   {
     if (aBuf)
       aBuf->ToString(aBuf->StorageSize()/2 - 1, *this);
   }
 };
 
 class nsAttrValue {
 public:
+  typedef nsTArray< nsCOMPtr<nsIAtom> > AtomArray;
+
   nsAttrValue();
   nsAttrValue(const nsAttrValue& aOther);
   explicit nsAttrValue(const nsAString& aValue);
   explicit nsAttrValue(nsICSSStyleRule* aValue);
 #ifdef MOZ_SVG
   explicit nsAttrValue(nsISVGValue* aValue);
 #endif
   explicit nsAttrValue(const nsIntMargin& aValue);
@@ -146,17 +149,17 @@ public:
   // to retrieve the datatype that this nsAttrValue has.
   inline PRBool IsEmptyString() const;
   const nsCheapString GetStringValue() const;
   inline nsIAtom* GetAtomValue() const;
   inline PRInt32 GetIntegerValue() const;
   PRBool GetColorValue(nscolor& aColor) const;
   inline PRInt16 GetEnumValue() const;
   inline float GetPercentValue() const;
-  inline nsCOMArray<nsIAtom>* GetAtomArrayValue() const;
+  inline AtomArray* GetAtomArrayValue() const;
   inline nsICSSStyleRule* GetCSSStyleRuleValue() const;
 #ifdef MOZ_SVG
   inline nsISVGValue* GetSVGValue() const;
 #endif
   inline float GetFloatValue() const;
   PRBool GetIntMarginValue(nsIntMargin& aMargin) const;
 
   /**
@@ -165,17 +168,17 @@ public:
    * @param aResult   the string representing the enum tag
    * @param aRealTag  wheter we want to have the real tag or the saved one
    */
   void GetEnumString(nsAString& aResult, PRBool aRealTag) const;
 
   // Methods to get access to atoms we may have
   // Returns the number of atoms we have; 0 if we have none.  It's OK
   // to call this without checking the type first; it handles that.
-  PRInt32 GetAtomCount() const;
+  PRUint32 GetAtomCount() const;
   // Returns the atom at aIndex (0-based).  Do not call this with
   // aIndex >= GetAtomCount().
   nsIAtom* AtomAt(PRInt32 aIndex) const;
 
   PRUint32 HashValue() const;
   PRBool Equals(const nsAttrValue& aOther) const;
   PRBool Equals(const nsAString& aValue, nsCaseTreatment aCaseSensitive) const;
   PRBool Equals(nsIAtom* aValue, nsCaseTreatment aCaseSensitive) const;
@@ -328,17 +331,17 @@ private:
     // mStringBits.
     PtrBits mStringBits;
     union {
       PRInt32 mInteger;
       nscolor mColor;
       PRUint32 mEnumValue;
       PRInt32 mPercent;
       nsICSSStyleRule* mCSSStyleRule;
-      nsCOMArray<nsIAtom>* mAtomArray;
+      AtomArray* mAtomArray;
 #ifdef MOZ_SVG
       nsISVGValue* mSVGValue;
 #endif
       float mFloatValue;
       nsIntMargin* mIntMargin;
     };
   };
 
@@ -421,17 +424,17 @@ nsAttrValue::GetPercentValue() const
 {
   NS_PRECONDITION(Type() == ePercent, "wrong type");
   return ((BaseType() == eIntegerBase)
           ? GetIntInternal()
           : GetMiscContainer()->mPercent)
             / 100.0f;
 }
 
-inline nsCOMArray<nsIAtom>*
+inline nsAttrValue::AtomArray*
 nsAttrValue::GetAtomArrayValue() const
 {
   NS_PRECONDITION(Type() == eAtomArray, "wrong type");
   return GetMiscContainer()->mAtomArray;
 }
 
 inline nsICSSStyleRule*
 nsAttrValue::GetCSSStyleRuleValue() const
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -5999,40 +5999,40 @@ nsContentUtils::ReparentClonedObjectToSc
       objectData.AppendElement(ReparentObjectData(cx, JSVAL_TO_OBJECT(prop)));
     }
   }
 
   return NS_OK;
 }
 
 struct ClassMatchingInfo {
-  nsCOMArray<nsIAtom> mClasses;
+  nsAttrValue::AtomArray mClasses;
   nsCaseTreatment mCaseTreatment;
 };
 
 static PRBool
 MatchClassNames(nsIContent* aContent, PRInt32 aNamespaceID, nsIAtom* aAtom,
                 void* aData)
 {
   // We can't match if there are no class names
   const nsAttrValue* classAttr = aContent->GetClasses();
   if (!classAttr) {
     return PR_FALSE;
   }
   
   // need to match *all* of the classes
   ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
-  PRInt32 length = info->mClasses.Count();
+  PRUint32 length = info->mClasses.Length();
   if (!length) {
     // If we actually had no classes, don't match.
     return PR_FALSE;
   }
-  PRInt32 i;
+  PRUint32 i;
   for (i = 0; i < length; ++i) {
-    if (!classAttr->Contains(info->mClasses.ObjectAt(i),
+    if (!classAttr->Contains(info->mClasses[i],
                              info->mCaseTreatment)) {
       return PR_FALSE;
     }
   }
   
   return PR_TRUE;
 }
 
@@ -6049,19 +6049,19 @@ AllocClassMatchingInfo(nsINode* aRootNod
 {
   nsAttrValue attrValue;
   attrValue.ParseAtomArray(*aClasses);
   // nsAttrValue::Equals is sensitive to order, so we'll send an array
   ClassMatchingInfo* info = new ClassMatchingInfo;
   NS_ENSURE_TRUE(info, nsnull);
 
   if (attrValue.Type() == nsAttrValue::eAtomArray) {
-    info->mClasses.AppendObjects(*(attrValue.GetAtomArrayValue()));
+    info->mClasses.SwapElements(*(attrValue.GetAtomArrayValue()));
   } else if (attrValue.Type() == nsAttrValue::eAtom) {
-    info->mClasses.AppendObject(attrValue.GetAtomValue());
+    info->mClasses.AppendElement(attrValue.GetAtomValue());
   }
 
   info->mCaseTreatment =
     aRootNode->GetOwnerDoc() &&
     aRootNode->GetOwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks ?
     eIgnoreCase : eCaseMatters;
   return info;
 }
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -778,16 +778,46 @@ ExternalResourceTraverser(nsIURI* aKey,
 void
 nsExternalResourceMap::Traverse(nsCycleCollectionTraversalCallback* aCallback) const
 {
   // mPendingLoads will get cleared out as the requests complete, so
   // no need to worry about those here.
   mMap.EnumerateRead(ExternalResourceTraverser, aCallback);
 }
 
+static PLDHashOperator
+ExternalResourceHider(nsIURI* aKey,
+                      nsExternalResourceMap::ExternalResource* aData,
+                      void* aClosure)
+{
+  aData->mViewer->Hide();
+  return PL_DHASH_NEXT;
+}
+
+void
+nsExternalResourceMap::HideViewers()
+{
+  mMap.EnumerateRead(ExternalResourceHider, nsnull);
+}
+
+static PLDHashOperator
+ExternalResourceShower(nsIURI* aKey,
+                       nsExternalResourceMap::ExternalResource* aData,
+                       void* aClosure)
+{
+  aData->mViewer->Show();
+  return PL_DHASH_NEXT;
+}
+
+void
+nsExternalResourceMap::ShowViewers()
+{
+  mMap.EnumerateRead(ExternalResourceShower, nsnull);
+}
+
 nsresult
 nsExternalResourceMap::AddExternalResource(nsIURI* aURI,
                                            nsIDocumentViewer* aViewer,
                                            nsILoadGroup* aLoadGroup,
                                            nsIDocument* aDisplayDocument)
 {
   NS_PRECONDITION(aURI, "Unexpected call");
   NS_PRECONDITION((aViewer && aLoadGroup) || (!aViewer && !aLoadGroup),
@@ -806,16 +836,19 @@ nsExternalResourceMap::AddExternalResour
 
     nsCOMPtr<nsIXULDocument> xulDoc = do_QueryInterface(doc);
     if (xulDoc) {
       // We don't handle XUL stuff here yet.
       rv = NS_ERROR_NOT_AVAILABLE;
     } else {
       doc->SetDisplayDocument(aDisplayDocument);
 
+      // Make sure that hiding our viewer will tear down its presentation.
+      aViewer->SetSticky(PR_FALSE);
+
       rv = aViewer->Init(nsnull, nsIntRect(0, 0, 0, 0));
       if (NS_SUCCEEDED(rv)) {
         rv = aViewer->Open(nsnull, nsnull);
       }
     }
     
     if (NS_FAILED(rv)) {
       doc = nsnull;
@@ -3034,21 +3067,30 @@ nsDocument::doCreateShell(nsPresContext*
   }
 
   rv = shell->Init(this, aContext, aViewManager, aStyleSet, aCompatMode);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Note: we don't hold a ref to the shell (it holds a ref to us)
   mPresShell = shell;
 
+  mExternalResourceMap.ShowViewers();
+
   shell.swap(*aInstancePtrResult);
 
   return NS_OK;
 }
 
+void
+nsDocument::DeleteShell()
+{
+  mExternalResourceMap.HideViewers();
+  mPresShell = nsnull;
+}
+
 static void
 SubDocClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
 {
   SubDocMapEntry *e = static_cast<SubDocMapEntry *>(entry);
 
   NS_RELEASE(e->mKey);
   if (e->mSubDocument) {
     e->mSubDocument->SetParentDocument(nsnull);
@@ -7810,9 +7852,8 @@ nsIDocument::CreateStaticClone(nsISuppor
           }
         }
       }
     }
   }
   mCreatingStaticClone = PR_FALSE;
   return clonedDoc.forget();
 }
-
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -370,16 +370,22 @@ public:
   struct ExternalResource
   {
     ~ExternalResource();
     nsCOMPtr<nsIDocument> mDocument;
     nsCOMPtr<nsIContentViewer> mViewer;
     nsCOMPtr<nsILoadGroup> mLoadGroup;
   };
 
+  // Hide all our viewers
+  void HideViewers();
+
+  // Show all our viewers
+  void ShowViewers();
+
 protected:
   class PendingLoad : public ExternalResourceLoad,
                       public nsIStreamListener
   {
   public:
     PendingLoad(nsDocument* aDisplayDocument) :
       mDisplayDocument(aDisplayDocument)
     {}
@@ -583,16 +589,17 @@ public:
    * Create a new presentation shell that will use aContext for
    * its presentation context (presentation context's <b>must not</b> be
    * shared among multiple presentation shell's).
    */
   virtual nsresult CreateShell(nsPresContext* aContext,
                                nsIViewManager* aViewManager,
                                nsStyleSet* aStyleSet,
                                nsIPresShell** aInstancePtrResult);
+  virtual void DeleteShell();
 
   virtual nsresult SetSubDocumentFor(nsIContent *aContent,
                                      nsIDocument* aSubDoc);
   virtual nsIDocument* GetSubDocumentFor(nsIContent *aContent) const;
   virtual nsIContent* FindContentForSubDocument(nsIDocument *aDocument) const;
   virtual Element* GetRootElementInternal() const;
 
   /**
--- a/content/html/document/src/nsHTMLFragmentContentSink.cpp
+++ b/content/html/document/src/nsHTMLFragmentContentSink.cpp
@@ -1095,16 +1095,20 @@ nsHTMLParanoidFragmentSink::OpenContaine
   return nsHTMLFragmentContentSink::OpenContainer(aNode);
 }
 
 NS_IMETHODIMP
 nsHTMLParanoidFragmentSink::CloseContainer(const nsHTMLTag aTag)
 {
   nsresult rv = NS_OK;
 
+  if (mIgnoreNextCloseHead && aTag == eHTMLTag_head) {
+    mIgnoreNextCloseHead = PR_FALSE;
+    return NS_OK;
+  }
   if (mSkip) {
     mSkip = PR_FALSE;
     return rv;
   }
 
   nsCOMPtr<nsIAtom> name;
   rv = NameFromType(aTag, getter_AddRefs(name));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -1224,17 +1228,20 @@ nsHTMLParanoidFragmentSink::SanitizeStyl
 
 NS_IMETHODIMP
 nsHTMLParanoidFragmentSink::AddLeaf(const nsIParserNode& aNode)
 {
   NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_NOT_INITIALIZED);
   
   nsresult rv = NS_OK;
 
-  if (mSkip) {
+  // We need to explicitly skip adding leaf nodes in the paranoid sink,
+  // otherwise things like the textnode under <title> get appended to
+  // the fragment itself, and won't be popped off in CloseContainer.
+  if (mSkip || mIgnoreNextCloseHead) {
     return rv;
   }
   
   if (aNode.GetTokenType() == eToken_start) {
     nsCOMPtr<nsIAtom> name;
     rv = NameFromNode(aNode, getter_AddRefs(name));
     NS_ENSURE_SUCCESS(rv, rv);
 
--- a/editor/libeditor/html/tests/test_bug520189.html
+++ b/editor/libeditor/html/tests/test_bug520189.html
@@ -47,16 +47,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <iframe id="ee" src="about:blank"></iframe>
   <div id="ff" contenteditable="true"></div>
   <iframe id="gg" src="about:blank"></iframe>
   <div id="hh" contenteditable="true"></div>
   <iframe id="ii" src="about:blank"></iframe>
   <div id="jj" contenteditable="true"></div>
   <iframe id="kk" src="about:blank"></iframe>
   <div id="ll" contenteditable="true"></div>
+  <iframe id="mm" src="about:blank"></iframe>
+  <div id="nn" contenteditable="true"></div>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 520182 **/
 
 const dataPayload = "foo<iframe src=\"data:text/html,bar\"></iframe>baz";
 const jsPayload = "foo<iframe src=\"javascript:void('bar');\"></iframe>baz";
@@ -68,16 +70,17 @@ const validStyle2Payload = "foo<span sty
 const validStyle3Payload = "foo<style>@font-face{font-family:xxx;src:'xxx.ttf';}</style>baz";
 const validStyle4Payload = "foo<style>@namespace xxx url(http://example.com/);</style>baz";
 const invalidStyle1Payload = "foo<style>#bar{-moz-binding:url('data:text/xml,<?xml version=\"1.0\"><binding xmlns=\"http://www.mozilla.org/xbl\"/>');}</style>baz";
 const invalidStyle2Payload = "foo<span style=\"-moz-binding:url('data:text/xml,<?xml version=&quot;1.0&quot;><binding xmlns=&quot;http://www.mozilla.org/xbl&quot;/>');\">bar</span>baz";
 const invalidStyle3Payload = "foo<style>@import 'xxx.css';</style>baz";
 const invalidStyle4Payload = "foo<span style=\"@import 'xxx.css';\">bar</span>baz";
 const invalidStyle5Payload = "foo<span style=\"@font-face{font-family:xxx;src:'xxx.ttf';}\">bar</span>baz";
 const invalidStyle6Payload = "foo<span style=\"@namespace xxx url(http://example.com/);\">bar</span>baz";
+const invalidStyle7Payload = "<html><head><title>xxx</title></head><body>foo</body></html>";
 const nestedStylePayload = "foo<style>#bar1{-moz-binding:url('data:text/xml,<?xml version=&quot;1.0&quot;><binding xmlns=&quot;http://www.mozilla.org/xbl&quot; id=&quot;binding-1&quot;/>');<style></style>#bar2{-moz-binding:url('data:text/xml,<?xml version=&quot;1.0&quot;><binding xmlns=&quot;http://www.mozilla.org/xbl&quot; id=&quot;binding-2&quot;/>');</style>baz";
 const validImgSrc1Payload = "foo<img src=\"data:image/png,bar\">baz";
 const validImgSrc2Payload = "foo<img src=\"javascript:void('bar');\">baz";
 const validImgSrc3Payload = "foo<img src=\"file:///bar.png\">baz";
 
 var tests = [
   {
     id: "a",
@@ -328,16 +331,37 @@ var tests = [
     rootElement: function() document.getElementById("kk").contentDocument.documentElement,
     checkResult: function(html) isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image")
   },
   {
     id: "ll",
     payload: invalidStyle6Payload,
     rootElement: function() document.getElementById("ll"),
     checkResult: function(html) isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image")
+  },
+  {
+    id: "mm",
+    isIFrame: true,
+    insertHTML: true,
+    payload: invalidStyle7Payload,
+    rootElement: function() document.getElementById("mm").contentDocument.documentElement,
+    checkResult: function(html) {
+      is(html.indexOf("xxx"), -1, "Should not have retained the title text");
+      isnot(html.indexOf("foo"), -1, "Should have retained the body text");
+    }
+  },
+  {
+    id: "nn",
+    insertHTML: true,
+    payload: invalidStyle7Payload,
+    rootElement: function() document.getElementById("nn"),
+    checkResult: function(html) {
+      is(html.indexOf("xxx"), -1, "Should not have retained the title text");
+      isnot(html.indexOf("foo"), -1, "Should have retained the body text");
+    }
   }
 ];
 
 function doNextTest() {
   if (typeof testCounter == "undefined")
     testCounter = 0;
   else if (++testCounter == tests.length) {
     SimpleTest.finish();
@@ -352,38 +376,47 @@ function doNextTest() {
 function runTest(test) {
   var elem = document.getElementById(test.id);
   if ("isIFrame" in test) {
     elem.contentDocument.designMode = "on";
     elem.contentWindow.focus();
   } else
     elem.focus();
 
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  if ("insertHTML" in test) {
+    if ("isIFrame" in test) {
+      elem.contentDocument.execCommand("inserthtml", false, test.payload);
+    } else {
+      getSelection().collapse(elem, 0);
+      document.execCommand("inserthtml", false, test.payload);
+    }
+  } else {
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 
-  var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
-                            .getService(Components.interfaces.nsIClipboard);
+    var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
+                              .getService(Components.interfaces.nsIClipboard);
 
-  var trans = Components.classes["@mozilla.org/widget/transferable;1"]
-                        .createInstance(Components.interfaces.nsITransferable);
-  var data = Components.classes["@mozilla.org/supports-string;1"]
-                       .createInstance(Components.interfaces.nsISupportsString);
-  data.data = test.payload;
-  trans.addDataFlavor("text/html");
-  trans.setTransferData("text/html", data, data.data.length * 2);
-  clipboard.setData(trans, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
+    var trans = Components.classes["@mozilla.org/widget/transferable;1"]
+                          .createInstance(Components.interfaces.nsITransferable);
+    var data = Components.classes["@mozilla.org/supports-string;1"]
+                         .createInstance(Components.interfaces.nsISupportsString);
+    data.data = test.payload;
+    trans.addDataFlavor("text/html");
+    trans.setTransferData("text/html", data, data.data.length * 2);
+    clipboard.setData(trans, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
 
-  var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-                         .getInterface(Components.interfaces.nsIWebNavigation)
-                         .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
-                         .rootTreeItem
-                         .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-                         .getInterface(Components.interfaces.nsIDOMWindow);
+    var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+                           .getInterface(Components.interfaces.nsIWebNavigation)
+                           .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
+                           .rootTreeItem
+                           .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+                           .getInterface(Components.interfaces.nsIDOMWindow);
 
-  mainWindow.goDoCommand("cmd_paste");
+    mainWindow.goDoCommand("cmd_paste");
+  }
 
   if ("checkResult" in test) {
     if ("isIFrame" in test) {
       test.checkResult(elem.contentDocument.documentElement.innerHTML,
         elem.contentDocument.documentElement.textContent);
     } else {
       test.checkResult(elem.innerHTML, elem.textContent);
     }
--- a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
+++ b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
@@ -209,28 +209,28 @@ cairo_d2d_create_device()
 	D3D10_DRIVER_TYPE_HARDWARE,
 	NULL,
 	D3D10_CREATE_DEVICE_BGRA_SUPPORT |
 	D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
 	D3D10_FEATURE_LEVEL_10_1,
 	D3D10_1_SDK_VERSION,
 	&device->mD3D10Device);
     if (FAILED(hr)) {
-	HRESULT hr = createD3DDevice(
+	hr = createD3DDevice(
 	    NULL, 
 	    D3D10_DRIVER_TYPE_HARDWARE,
 	    NULL,
 	    D3D10_CREATE_DEVICE_BGRA_SUPPORT |
 	    D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
 	    D3D10_FEATURE_LEVEL_10_0,
 	    D3D10_1_SDK_VERSION,
 	    &device->mD3D10Device);
 	if (FAILED(hr)) {
 	    /* This is not guaranteed to be too fast! */
-	    HRESULT hr = createD3DDevice(
+	    hr = createD3DDevice(
 		NULL, 
 		D3D10_DRIVER_TYPE_HARDWARE,
 		NULL,
 		D3D10_CREATE_DEVICE_BGRA_SUPPORT |
 		D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
 		D3D10_FEATURE_LEVEL_9_3,
 		D3D10_1_SDK_VERSION,
 		&device->mD3D10Device);
--- a/js/src/xpconnect/src/xpcquickstubs.cpp
+++ b/js/src/xpconnect/src/xpcquickstubs.cpp
@@ -1110,22 +1110,22 @@ xpc_qsStringToJsstring(JSContext *cx, ns
 }
 
 JSBool
 xpc_qsXPCOMObjectToJsval(XPCLazyCallContext &lccx, qsObjectHelper* aHelper,
                          nsWrapperCache *cache,
                          const nsIID *iid, XPCNativeInterface **iface,
                          jsval *rval)
 {
+    NS_PRECONDITION(iface, "Who did that and why?");
+
     // From the T_INTERFACE case in XPCConvert::NativeData2JS.
     // This is one of the slowest things quick stubs do.
 
     JSContext *cx = lccx.GetJSContext();
-    if(!iface)
-        return xpc_qsThrow(cx, NS_ERROR_XPC_BAD_CONVERT_NATIVE);
 
     // XXX The OBJ_IS_NOT_GLOBAL here is not really right. In
     // fact, this code is depending on the fact that the
     // global object will not have been collected, and
     // therefore this NativeInterface2JSObject will not end up
     // creating a new XPCNativeScriptableShared.
 
     nsresult rv;
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -855,17 +855,19 @@ DocumentViewerImpl::InitInternal(nsIWidg
     nsresult rv = CreateDeviceContext(containerView);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // XXXbz this is a nasty hack to do with the fact that we create
     // presentations both in Init() and in Show()...  Ideally we would only do
     // it in one place (Show()) and require that callers call init(), open(),
     // show() in that order or something.
     if (!mPresContext &&
-        (aParentWidget || containerView || mDocument->GetDisplayDocument())) {
+        (aParentWidget || containerView ||
+         (mDocument->GetDisplayDocument() &&
+          mDocument->GetDisplayDocument()->GetShell()))) {
       // Create presentation context
       if (mIsPageMode) {
         //Presentation context already created in SetPageMode which is calling this method
       } else {
         mPresContext = CreatePresContext(mDocument,
             nsPresContext::eContext_Galley, containerView);
       }
       NS_ENSURE_TRUE(mPresContext, NS_ERROR_OUT_OF_MEMORY);
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -104,16 +104,17 @@
 #endif
 
 #ifdef MOZ_XUL
 #include "nsXULPopupManager.h"
 #endif
 
 using namespace mozilla::layers;
 using namespace mozilla::dom;
+namespace css = mozilla::css;
 
 /**
  * A namespace class for static layout utilities.
  */
 
 nsIFrame*
 nsLayoutUtils::GetLastContinuationWithChild(nsIFrame* aFrame)
 {
@@ -1747,16 +1748,25 @@ static nscoord AddPercents(nsLayoutUtils
     else
       result = NSToCoordRound(float(result) / (1.0f - aPercent));
   }
   return result;
 }
 
 static PRBool GetAbsoluteCoord(const nsStyleCoord& aStyle, nscoord& aResult)
 {
+  if (aStyle.IsCalcUnit()) {
+    if (aStyle.CalcHasPercent()) {
+      return PR_FALSE;
+    }
+    // If it has no percents, we can pass 0 for the percentage basis.
+    aResult = nsRuleNode::ComputeComputedCalc(aStyle, 0);
+    return PR_TRUE;
+  }
+
   if (eStyleUnit_Coord != aStyle.GetUnit())
     return PR_FALSE;
 
   aResult = aStyle.GetCoordValue();
   return PR_TRUE;
 }
 
 static PRBool
@@ -2031,22 +2041,31 @@ nsLayoutUtils::IntrinsicForContainer(nsI
   pctTotal += pctOutsideWidth;
 
   nscoord w;
   if (GetAbsoluteCoord(styleWidth, w) ||
       GetIntrinsicCoord(styleWidth, aRenderingContext, aFrame,
                         PROP_WIDTH, w)) {
     result = AddPercents(aType, w + coordOutsideWidth, pctOutsideWidth);
   }
-  else if (aType == MIN_WIDTH && eStyleUnit_Percent == styleWidth.GetUnit() &&
+  else if (aType == MIN_WIDTH &&
+           // The only cases of coord-percent-calc() units that
+           // GetAbsoluteCoord didn't handle are percent and calc()s
+           // containing percent.
+           styleWidth.IsCoordPercentCalcUnit() &&
            aFrame->IsFrameOfType(nsIFrame::eReplaced)) {
     // A percentage width on replaced elements means they can shrink to 0.
     result = 0; // let |min| handle padding/border/margin
   }
   else {
+    // NOTE: We could really do a lot better for percents and for some
+    // cases of calc() containing percent (certainly including any where
+    // the coefficient on the percent is positive and there are no max()
+    // expressions).  However, doing better for percents wouldn't be
+    // backwards compatible.
     result = AddPercents(aType, result, pctTotal);
   }
 
   nscoord maxw;
   if (GetAbsoluteCoord(styleMaxWidth, maxw) ||
       GetIntrinsicCoord(styleMaxWidth, aRenderingContext, aFrame,
                         PROP_MAX_WIDTH, maxw)) {
     maxw = AddPercents(aType, maxw + coordOutsideWidth, pctOutsideWidth);
@@ -2133,25 +2152,22 @@ nsLayoutUtils::ComputeWidthValue(
   NS_WARN_IF_FALSE(aContainingBlockWidth != NS_UNCONSTRAINEDSIZE,
                    "have unconstrained width; this should only result from "
                    "very large sizes, not attempts at intrinsic width "
                    "calculation");
   NS_PRECONDITION(aContainingBlockWidth >= 0,
                   "width less than zero");
 
   nscoord result;
-  if (eStyleUnit_Coord == aCoord.GetUnit()) {
-    result = aCoord.GetCoordValue();
-    NS_ASSERTION(result >= 0, "width less than zero");
+  if (aCoord.IsCoordPercentCalcUnit()) {
+    result = nsRuleNode::ComputeCoordPercentCalc(aCoord, aContainingBlockWidth);
+    // The result of a calc() expression might be less than 0; we
+    // should clamp at runtime (below).  (Percentages and coords that
+    // are less than 0 have already been dropped by the parser.)
     result -= aContentEdgeToBoxSizing;
-  } else if (eStyleUnit_Percent == aCoord.GetUnit()) {
-    NS_ASSERTION(aCoord.GetPercentValue() >= 0.0f, "width less than zero");
-    result = NSToCoordFloorClamped(aContainingBlockWidth *
-                                   aCoord.GetPercentValue()) -
-             aContentEdgeToBoxSizing;
   } else if (eStyleUnit_Enumerated == aCoord.GetUnit()) {
     PRInt32 val = aCoord.GetIntValue();
     switch (val) {
       case NS_STYLE_WIDTH_MAX_CONTENT:
         result = aFrame->GetPrefWidth(aRenderingContext);
         NS_ASSERTION(result >= 0, "width less than zero");
         break;
       case NS_STYLE_WIDTH_MIN_CONTENT:
--- a/layout/generic/nsAbsoluteContainingBlock.cpp
+++ b/layout/generic/nsAbsoluteContainingBlock.cpp
@@ -221,39 +221,19 @@ nsAbsoluteContainingBlock::Reflow(nsCont
 }
 
 static inline PRBool IsFixedPaddingSize(nsStyleUnit aUnit) {
   return aUnit == eStyleUnit_Coord;
 }
 static inline PRBool IsFixedMarginSize(nsStyleUnit aUnit) {
   return aUnit == eStyleUnit_Coord;
 }
-static inline PRBool IsFixedMaxSize(nsStyleUnit aUnit) {
-  return aUnit == eStyleUnit_None || aUnit == eStyleUnit_Coord;
-}
 static inline PRBool IsFixedOffset(nsStyleUnit aUnit) {
   return aUnit == eStyleUnit_Coord;
 }
-static inline PRBool IsFixedHeight(nsStyleUnit aUnit) {
-  return aUnit == eStyleUnit_Coord;
-}
-
-static inline PRBool IsFixedWidth(const nsStyleCoord& aCoord)
-{
-  return aCoord.GetUnit() == eStyleUnit_Coord ||
-         (aCoord.GetUnit() == eStyleUnit_Enumerated &&
-          (aCoord.GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT ||
-           aCoord.GetIntValue() == NS_STYLE_WIDTH_MIN_CONTENT));
-}
-
-static inline PRBool IsFixedMaxWidth(const nsStyleCoord& aCoord)
-{
-  return aCoord.GetUnit() == eStyleUnit_None ||
-         IsFixedWidth(aCoord);
-}
 
 PRBool
 nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f,
                                                    PRBool aCBWidthChanged,
                                                    PRBool aCBHeightChanged)
 {
   const nsStylePosition* pos = f->GetStylePosition();
   // See if f's position might have changed because it depends on a
@@ -281,19 +261,19 @@ nsAbsoluteContainingBlock::FrameDependsO
   const nsStyleMargin* margin = f->GetStyleMargin();
   if (aCBWidthChanged) {
     // See if f's width might have changed.
     // If border-left, border-right, padding-left, padding-right,
     // width, min-width, and max-width are all lengths, 'none', or enumerated,
     // then our frame width does not depend on the parent width.
     // Note that borders never depend on the parent width
     // XXX All of the enumerated values except -moz-available are ok too.
-    if (!IsFixedWidth(pos->mWidth) ||
-        !IsFixedWidth(pos->mMinWidth) ||
-        !IsFixedMaxWidth(pos->mMaxWidth) ||
+    if (pos->WidthDependsOnContainer() ||
+        pos->MinWidthDependsOnContainer() ||
+        pos->MaxWidthDependsOnContainer() ||
         !IsFixedPaddingSize(padding->mPadding.GetLeftUnit()) ||
         !IsFixedPaddingSize(padding->mPadding.GetRightUnit())) {
       return PR_TRUE;
     }
 
     // See if f's position might have changed. If we're RTL then the
     // rules are slightly different. We'll assume percentage or auto
     // margins will always induce a dependency on the size
@@ -320,22 +300,22 @@ nsAbsoluteContainingBlock::FrameDependsO
   }
   if (aCBHeightChanged) {
     // See if f's height might have changed.
     // If border-top, border-bottom, padding-top, padding-bottom,
     // min-height, and max-height are all lengths or 'none',
     // and height is a length or height and bottom are auto and top is not auto,
     // then our frame height does not depend on the parent height.
     // Note that borders never depend on the parent height
-    if (!(IsFixedHeight(pos->mHeight.GetUnit()) ||
-          (pos->mHeight.GetUnit() == eStyleUnit_Auto &&
+    if ((pos->HeightDependsOnContainer() &&
+         !(pos->mHeight.GetUnit() == eStyleUnit_Auto &&
            pos->mOffset.GetBottomUnit() == eStyleUnit_Auto &&
            pos->mOffset.GetTopUnit() != eStyleUnit_Auto)) ||
-        !IsFixedHeight(pos->mMinHeight.GetUnit()) ||
-        !IsFixedMaxSize(pos->mMaxHeight.GetUnit()) ||
+        pos->MinHeightDependsOnContainer() ||
+        pos->MaxHeightDependsOnContainer() ||
         !IsFixedPaddingSize(padding->mPadding.GetTopUnit()) ||
         !IsFixedPaddingSize(padding->mPadding.GetBottomUnit())) { 
       return PR_TRUE;
     }
       
     // See if f's position might have changed.
     if (!IsFixedMarginSize(margin->mMargin.GetTopUnit()) ||
         !IsFixedMarginSize(margin->mMargin.GetBottomUnit())) {
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -3481,18 +3481,17 @@ nsBlockFrame::DoReflowInlineFrames(nsBlo
   // are impacted by floats.
   if (aFloatAvailableSpace.mHasFloats)
     aLine->SetLineIsImpactedByFloat(PR_TRUE);
 #ifdef REALLY_NOISY_REFLOW
   printf("nsBlockFrame::DoReflowInlineFrames %p impacted = %d\n",
          this, aFloatAvailableSpace.mHasFloats);
 #endif
 
-  const nsMargin& borderPadding = aState.BorderPadding();
-  nscoord x = aFloatAvailableSpace.mRect.x + borderPadding.left;
+  nscoord x = aFloatAvailableSpace.mRect.x;
   nscoord availWidth = aFloatAvailableSpace.mRect.width;
   nscoord availHeight;
   if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
     availHeight = NS_UNCONSTRAINEDSIZE;
   }
   else {
     /* XXX get the height right! */
     availHeight = aFloatAvailableSpace.mRect.height;
@@ -5552,35 +5551,33 @@ nsBlockFrame::AdjustFloatAvailableSpace(
   else {
     // This quirk matches the one in nsBlockReflowState::FlowAndPlaceFloat
     // give tables only the available space
     // if they can shrink we may not be constrained to place
     // them in the next line
     availWidth = aFloatAvailableSpace.width;
   }
 
-  // aState.mY is relative to the border-top, make it relative to the content-top
-  nscoord contentYOffset = aState.mY - aState.BorderPadding().top;
   nscoord availHeight = NS_UNCONSTRAINEDSIZE == aState.mContentArea.height
                         ? NS_UNCONSTRAINEDSIZE
-                        : NS_MAX(0, aState.mContentArea.height - contentYOffset);
+                        : NS_MAX(0, aState.mContentArea.YMost() - aState.mY);
 
 #ifdef DISABLE_FLOAT_BREAKING_IN_COLUMNS
   if (availHeight != NS_UNCONSTRAINEDSIZE &&
       nsLayoutUtils::GetClosestFrameOfType(this, nsGkAtoms::columnSetFrame)) {
     // Tell the float it has unrestricted height, so it won't break.
     // If the float doesn't actually fit in the column it will fail to be
     // placed, and either move to the top of the next column or just
     // overflow.
     availHeight = NS_UNCONSTRAINEDSIZE;
   }
 #endif
 
-  return nsRect(aState.BorderPadding().left,
-                aState.BorderPadding().top,
+  return nsRect(aState.mContentArea.x,
+                aState.mContentArea.y,
                 availWidth, availHeight);
 }
 
 nscoord
 nsBlockFrame::ComputeFloatWidth(nsBlockReflowState& aState,
                                 const nsRect&       aFloatAvailableSpace,
                                 nsIFrame*           aFloat)
 {
@@ -6605,17 +6602,17 @@ nsBlockFrame::ReflowBullet(nsBlockReflow
                            nsHTMLReflowMetrics& aMetrics,
                            nscoord aLineTop)
 {
   const nsHTMLReflowState &rs = aState.mReflowState;
 
   // Reflow the bullet now
   nsSize availSize;
   // Make up a width since it doesn't really matter (XXX).
-  availSize.width = rs.ComputedWidth();
+  availSize.width = aState.mContentArea.width;
   availSize.height = NS_UNCONSTRAINEDSIZE;
 
   // Get the reason right.
   // XXXwaterson Should this look just like the logic in
   // nsBlockReflowContext::ReflowBlock and nsLineLayout::ReflowFrame?
   nsHTMLReflowState reflowState(aState.mPresContext, rs,
                                 mBullet, availSize);
   nsReflowStatus  status;
@@ -6639,36 +6636,32 @@ nsBlockFrame::ReflowBullet(nsBlockReflow
   // the bullet frame as separation).  However, if a line box would be
   // displaced by floats that are *outside* the associated block, we
   // want to displace it by the same amount.  That is, we act as though
   // the edge of the floats is the content-edge of the block, and place
   // the bullet at a position offset from there by the block's padding,
   // the block's border, and the bullet frame's margin.
   nscoord x;
   if (rs.mStyleVisibility->mDirection == NS_STYLE_DIRECTION_LTR) {
-    // Note: floatAvailSpace.x is relative to the content box and never
-    // less than zero.  Converting to frame coordinates and subtracting
-    // the padding and border cancel each other out, and the NS_MAX()
-    // with 0 (or with the left border+padding) is even implied in the
-    // right place.
-    x = floatAvailSpace.x - reflowState.mComputedMargin.right - aMetrics.width;
+    // The floatAvailSpace.x gives us the content/float edge. Then we
+    // subtract out the left border/padding and the bullet's width and
+    // margin to offset the position.
+    x = floatAvailSpace.x - rs.mComputedBorderPadding.left
+        - reflowState.mComputedMargin.right - aMetrics.width;
   } else {
-    // The XMost() of the available space and the computed width both
-    // give us offsets from the left content edge.  Then we add the left
-    // border/padding to get into frame coordinates, and the right
-    // border/padding and the bullet's margin to offset the position.
-    x = NS_MIN(rs.ComputedWidth(), floatAvailSpace.XMost())
-        + rs.mComputedBorderPadding.LeftRight()
+    // The XMost() of the available space give us offsets from the left
+    // border edge.  Then we add the right border/padding and the
+    // bullet's margin to offset the position.
+    x = floatAvailSpace.XMost() + rs.mComputedBorderPadding.right
         + reflowState.mComputedMargin.left;
   }
 
   // Approximate the bullets position; vertical alignment will provide
   // the final vertical location.
-  const nsMargin& bp = aState.BorderPadding();
-  nscoord y = bp.top;
+  nscoord y = aState.mContentArea.y;
   mBullet->SetRect(nsRect(x, y, aMetrics.width, aMetrics.height));
   mBullet->DidReflow(aState.mPresContext, &aState.mReflowState, NS_FRAME_REFLOW_FINISHED);
 }
 
 // This is used to scan frames for any float placeholders, add their
 // floats to the list represented by aList, and remove the
 // floats from whatever list they might be in. We don't search descendants
 // that are float containing blocks. The floats must be children of 'this'.
--- a/layout/generic/nsBlockReflowContext.cpp
+++ b/layout/generic/nsBlockReflowContext.cpp
@@ -273,34 +273,21 @@ nsBlockReflowContext::ReflowBlock(const 
   // them. Floats are guaranteed to have their own float manager, so tx and ty
   // don't matter.  mX and mY don't matter becacuse they are only used in
   // PlaceBlock, which is not used for floats.
   if (aLine) {
     // Compute x/y coordinate where reflow will begin. Use the rules
     // from 10.3.3 to determine what to apply. At this point in the
     // reflow auto left/right margins will have a zero value.
 
-    nscoord x = mSpace.x + aFrameRS.mComputedMargin.left;
-    nscoord y = mSpace.y + mTopMargin.get() + aClearance;
+    mX = tx = mSpace.x + aFrameRS.mComputedMargin.left;
+    mY = ty = mSpace.y + mTopMargin.get() + aClearance;
 
     if ((mFrame->GetStateBits() & NS_BLOCK_FLOAT_MGR) == 0)
-      aFrameRS.mBlockDelta = mOuterReflowState.mBlockDelta + y - aLine->mBounds.y;
-
-    mX = x;
-    mY = y;
-
-    // Compute the translation to be used for adjusting the spacemanagager
-    // coordinate system for the frame.  The spacemanager coordinates are
-    // <b>inside</b> the callers border+padding, but the x/y coordinates
-    // are not (recall that frame coordinates are relative to the parents
-    // origin and that the parents border/padding is <b>inside</b> the
-    // parent frame. Therefore we have to subtract out the parents
-    // border+padding before translating.
-    tx = x - mOuterReflowState.mComputedBorderPadding.left;
-    ty = y - mOuterReflowState.mComputedBorderPadding.top;
+      aFrameRS.mBlockDelta = mOuterReflowState.mBlockDelta + ty - aLine->mBounds.y;
   }
 
   // Let frame know that we are reflowing it
   mFrame->WillReflow(mPresContext);
 
 #ifdef DEBUG
   mMetrics.width = nscoord(0xdeadbeef);
   mMetrics.height = nscoord(0xdeadbeef);
--- a/layout/generic/nsBlockReflowState.cpp
+++ b/layout/generic/nsBlockReflowState.cpp
@@ -97,19 +97,17 @@ nsBlockReflowState::nsBlockReflowState(c
     SetFlag(BRS_FLOAT_MGR, PR_TRUE);
   }
   
   mFloatManager = aReflowState.mFloatManager;
 
   NS_ASSERTION(mFloatManager,
                "FloatManager should be set in nsBlockReflowState" );
   if (mFloatManager) {
-    // Translate into our content area and then save the 
-    // coordinate system origin for later.
-    mFloatManager->Translate(borderPadding.left, borderPadding.top);
+    // Save the coordinate system origin for later.
     mFloatManager->GetTranslation(mFloatManagerX, mFloatManagerY);
     mFloatManager->PushState(&mFloatManagerStateBefore); // never popped
   }
 
   mReflowStatus = NS_FRAME_COMPLETE;
 
   mPresContext = aPresContext;
   mNextInFlow = static_cast<nsBlockFrame*>(mBlock->GetNextInFlow());
@@ -134,35 +132,25 @@ nsBlockReflowState::nsBlockReflowState(c
     mContentArea.height = NS_MAX(0, mBottomEdge - borderPadding.top);
   }
   else {
     // When we are not in a paginated situation then we always use
     // an constrained height.
     SetFlag(BRS_UNCONSTRAINEDHEIGHT, PR_TRUE);
     mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
   }
-
-  mY = borderPadding.top;
+  mContentArea.x = borderPadding.left;
+  mY = mContentArea.y = borderPadding.top;
 
   mPrevChild = nsnull;
   mCurrentLine = aFrame->end_lines();
 
   mMinLineHeight = aReflowState.CalcLineHeight();
 }
 
-nsBlockReflowState::~nsBlockReflowState()
-{
-  // Restore the coordinate system, unless the float manager is null,
-  // which means it was just destroyed.
-  if (mFloatManager) {
-    const nsMargin& borderPadding = BorderPadding();
-    mFloatManager->Translate(-borderPadding.left, -borderPadding.top);
-  }
-}
-
 nsLineBox*
 nsBlockReflowState::NewLineBox(nsIFrame* aFrame,
                                PRInt32 aCount,
                                PRBool aIsBlock)
 {
   return NS_NewLineBox(mPresContext->PresShell(), aFrame, aCount, aIsBlock);
 }
 
@@ -182,19 +170,19 @@ nsBlockReflowState::ComputeReplacedBlock
                                                          nsBlockFrame::
                                                       ReplacedElementWidthToClear
                                                                  *aReplacedWidth)
 {
   // The frame is clueless about the float manager and therefore we
   // only give it free space. An example is a table frame - the
   // tables do not flow around floats.
   // However, we can let its margins intersect floats.
-  NS_ASSERTION(aFloatAvailableSpace.x >= 0, "bad avail space rect x");
+  NS_ASSERTION(aFloatAvailableSpace.x >= mContentArea.x, "bad avail space rect x");
   NS_ASSERTION(aFloatAvailableSpace.width == 0 ||
-               aFloatAvailableSpace.XMost() <= mContentArea.width,
+               aFloatAvailableSpace.XMost() <= mContentArea.XMost(),
                "bad avail space rect width");
 
   nscoord leftOffset, rightOffset;
   if (aFloatAvailableSpace.width == mContentArea.width) {
     // We don't need to compute margins when there are no floats around.
     leftOffset = 0;
     rightOffset = 0;
   } else {
@@ -205,23 +193,23 @@ nsBlockReflowState::ComputeReplacedBlock
     // to place.
     nsCSSOffsetState os(aFrame, mReflowState.rendContext, mContentArea.width);
     NS_ASSERTION(!aReplacedWidth ||
                  aFrame->GetType() == nsGkAtoms::tableOuterFrame ||
                  (aReplacedWidth->marginLeft  == os.mComputedMargin.left &&
                   aReplacedWidth->marginRight == os.mComputedMargin.right),
                  "unexpected aReplacedWidth");
 
-    nscoord leftFloatXOffset = aFloatAvailableSpace.x;
+    nscoord leftFloatXOffset = aFloatAvailableSpace.x - mContentArea.x;
     leftOffset = NS_MAX(leftFloatXOffset, os.mComputedMargin.left) -
                  (aReplacedWidth ? aReplacedWidth->marginLeft
                                  : os.mComputedMargin.left);
     leftOffset = NS_MAX(leftOffset, 0); // in case of negative margin
     nscoord rightFloatXOffset =
-      mContentArea.width - aFloatAvailableSpace.XMost();
+      mContentArea.XMost() - aFloatAvailableSpace.XMost();
     rightOffset = NS_MAX(rightFloatXOffset, os.mComputedMargin.right) -
                   (aReplacedWidth ? aReplacedWidth->marginRight
                                   : os.mComputedMargin.right);
     rightOffset = NS_MAX(rightOffset, 0); // in case of negative margin
   }
   aLeftResult = leftOffset;
   aRightResult = rightOffset;
 }
@@ -243,18 +231,16 @@ nsBlockReflowState::ComputeBlockAvailSpa
   aResult.y = mY;
   aResult.height = GetFlag(BRS_UNCONSTRAINEDHEIGHT)
     ? NS_UNCONSTRAINEDSIZE
     : mReflowState.availableHeight - mY;
   // mY might be greater than mBottomEdge if the block's top margin pushes
   // it off the page/column. Negative available height can confuse other code
   // and is nonsense in principle.
 
-  const nsMargin& borderPadding = BorderPadding();
-
   // XXX Do we really want this condition to be this restrictive (i.e.,
   // more restrictive than it used to be)?  The |else| here is allowed
   // by the CSS spec, but only out of desperation given implementations,
   // and the behavior it leads to is quite undesirable (it can cause
   // things to become extremely narrow when they'd fit quite well a
   // little bit lower).  Should the else be a quirk or something that
   // applies to a specific set of frame classes and no new ones?
   // If we did that, then for those frames where the condition below is
@@ -270,34 +256,34 @@ nsBlockReflowState::ComputeBlockAvailSpa
       // Use the float-edge property to determine how the child block
       // will interact with the float.
       const nsStyleBorder* borderStyle = aFrame->GetStyleBorder();
       switch (borderStyle->mFloatEdge) {
         default:
         case NS_STYLE_FLOAT_EDGE_CONTENT:  // content and only content does runaround of floats
           // The child block will flow around the float. Therefore
           // give it all of the available space.
-          aResult.x = borderPadding.left;
+          aResult.x = mContentArea.x;
           aResult.width = mContentArea.width;
           break;
         case NS_STYLE_FLOAT_EDGE_MARGIN:
           {
             // The child block's margins should be placed adjacent to,
             // but not overlap the float.
-            aResult.x = aFloatAvailableSpace.mRect.x + borderPadding.left;
+            aResult.x = aFloatAvailableSpace.mRect.x;
             aResult.width = aFloatAvailableSpace.mRect.width;
           }
           break;
       }
     }
     else {
       // Since there are no floats present the float-edge property
       // doesn't matter therefore give the block element all of the
       // available space since it will flow around the float itself.
-      aResult.x = borderPadding.left;
+      aResult.x = mContentArea.x;
       aResult.width = mContentArea.width;
     }
   }
   else {
     nsBlockFrame::ReplacedElementWidthToClear replacedWidthStruct;
     nsBlockFrame::ReplacedElementWidthToClear *replacedWidth = nsnull;
     if (aFrame->GetType() == nsGkAtoms::tableOuterFrame) {
       replacedWidth = &replacedWidthStruct;
@@ -305,17 +291,17 @@ nsBlockReflowState::ComputeBlockAvailSpa
         nsBlockFrame::WidthToClearPastFloats(*this, aFloatAvailableSpace.mRect,
                                              aFrame);
     }
 
     nscoord leftOffset, rightOffset;
     ComputeReplacedBlockOffsetsForFloats(aFrame, aFloatAvailableSpace.mRect,
                                          leftOffset, rightOffset,
                                          replacedWidth);
-    aResult.x = borderPadding.left + leftOffset;
+    aResult.x = mContentArea.x + leftOffset;
     aResult.width = mContentArea.width - leftOffset - rightOffset;
   }
 
 #ifdef REALLY_NOISY_REFLOW
   printf("  CBAS: result %d %d %d %d\n", aResult.x, aResult.y, aResult.width, aResult.height);
 #endif
 }
 
@@ -327,22 +313,21 @@ nsBlockReflowState::GetFloatAvailableSpa
 #ifdef DEBUG
   // Verify that the caller setup the coordinate system properly
   nscoord wx, wy;
   mFloatManager->GetTranslation(wx, wy);
   NS_ASSERTION((wx == mFloatManagerX) && (wy == mFloatManagerY),
                "bad coord system");
 #endif
 
-  nscoord y = aY - BorderPadding().top;
   nscoord height = (mContentArea.height == nscoord_MAX)
-                     ? nscoord_MAX : NS_MAX(mContentArea.height - y, 0);
+                     ? nscoord_MAX : NS_MAX(mContentArea.YMost() - aY, 0);
   nsFlowAreaRect result =
-    mFloatManager->GetFlowArea(y, nsFloatManager::BAND_FROM_POINT,
-                               height, mContentArea.width, aState);
+    mFloatManager->GetFlowArea(aY, nsFloatManager::BAND_FROM_POINT,
+                               height, mContentArea, aState);
   // Keep the width >= 0 for compatibility with nsSpaceManager.
   if (result.mRect.width < 0)
     result.mRect.width = 0;
 
 #ifdef DEBUG
   if (nsBlockFrame::gNoisyReflow) {
     nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
     printf("GetAvailableSpace: band=%d,%d,%d,%d hasfloats=%d\n",
@@ -362,19 +347,18 @@ nsBlockReflowState::GetFloatAvailableSpa
   // Verify that the caller setup the coordinate system properly
   nscoord wx, wy;
   mFloatManager->GetTranslation(wx, wy);
   NS_ASSERTION((wx == mFloatManagerX) && (wy == mFloatManagerY),
                "bad coord system");
 #endif
 
   nsFlowAreaRect result =
-    mFloatManager->GetFlowArea(aY - BorderPadding().top, 
-                               nsFloatManager::WIDTH_WITHIN_HEIGHT,
-                               aHeight, mContentArea.width, aState);
+    mFloatManager->GetFlowArea(aY, nsFloatManager::WIDTH_WITHIN_HEIGHT,
+                               aHeight, mContentArea, aState);
   // Keep the width >= 0 for compatibility with nsSpaceManager.
   if (result.mRect.width < 0)
     result.mRect.width = 0;
 
 #ifdef DEBUG
   if (nsBlockFrame::gNoisyReflow) {
     nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
     printf("GetAvailableSpaceForHeight: space=%d,%d,%d,%d hasfloats=%d\n",
@@ -505,31 +489,23 @@ void
 nsBlockReflowState::RecoverStateFrom(nsLineList::iterator aLine,
                                      nscoord aDeltaY)
 {
   // Make the line being recovered the current line
   mCurrentLine = aLine;
 
   // Place floats for this line into the float manager
   if (aLine->HasFloats() || aLine->IsBlock()) {
-    // Undo border/padding translation since the nsFloatCache's
-    // coordinates are relative to the frame not relative to the
-    // border/padding.
-    const nsMargin& bp = BorderPadding();
-    mFloatManager->Translate(-bp.left, -bp.top);
-
     RecoverFloats(aLine, aDeltaY);
 
 #ifdef DEBUG
     if (nsBlockFrame::gNoisyReflow || nsBlockFrame::gNoisyFloatManager) {
       mFloatManager->List(stdout);
     }
 #endif
-    // And then put the translation back again
-    mFloatManager->Translate(bp.left, bp.top);
   }
 }
 
 // This is called by the line layout's AddFloat method when a
 // place-holder frame is reflowed in a line. If the float is a
 // left-most child (it's x coordinate is at the line's left margin)
 // then the float is place immediately, otherwise the float
 // placement is deferred until the line has been reflowed.
@@ -595,18 +571,17 @@ nsBlockReflowState::AddFloat(nsLineLayou
       (aLineLayout->LineIsEmpty() ||
        mBlock->ComputeFloatWidth(*this, floatAvailableSpace, aFloat)
        <= aAvailableWidth)) {
     // And then place it
     placed = FlowAndPlaceFloat(aFloat);
     if (placed) {
       // Pass on updated available space to the current inline reflow engine
       nsFlowAreaRect floatAvailSpace = GetFloatAvailableSpace(mY);
-      nsRect availSpace(nsPoint(floatAvailSpace.mRect.x + BorderPadding().left,
-                                mY),
+      nsRect availSpace(nsPoint(floatAvailSpace.mRect.x, mY),
                         floatAvailSpace.mRect.Size());
       aLineLayout->UpdateBand(availSpace, aFloat);
       // Record this float in the current-line list
       mCurrentLineFloats.Append(mFloatCacheFreeList.Alloc(aFloat));
     } else {
       (*aLineLayout->GetLine())->SetHadFloatPushed();
     }
   }
@@ -676,17 +651,17 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
   // Grab the float's display information
   const nsStyleDisplay* floatDisplay = aFloat->GetStyleDisplay();
 
   // The float's old region, so we can propagate damage.
   nsRect oldRegion = nsFloatManager::GetRegionFor(aFloat);
 
   // Enforce CSS2 9.5.1 rule [2], i.e., make sure that a float isn't
   // ``above'' another float that preceded it in the flow.
-  mY = NS_MAX(mFloatManager->GetLowestFloatTop() + BorderPadding().top, mY);
+  mY = NS_MAX(mFloatManager->GetLowestFloatTop(), mY);
 
   // See if the float should clear any preceding floats...
   // XXX We need to mark this float somehow so that it gets reflowed
   // when floats are inserted before it.
   if (NS_STYLE_CLEAR_NONE != floatDisplay->mBreakType) {
     // XXXldb Does this handle vertical margins correctly?
     mY = ClearFloats(mY, floatDisplay->mBreakType);
   }
@@ -786,45 +761,38 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
     }
   }
 
   // If the float is continued, it will get the same absolute x value as its prev-in-flow
 
   // We don't worry about the geometry of the prev in flow, let the continuation
   // place and size itself as required.
 
-  // Assign an x and y coordinate to the float. Note that the x,y
-  // coordinates are computed <b>relative to the translation in the
-  // spacemanager</b> which means that the impacted region will be
-  // <b>inside</b> the border/padding area.
+  // Assign an x and y coordinate to the float.
   nscoord floatX, floatY;
   if (NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) {
     floatX = floatAvailableSpace.mRect.x;
   }
   else {
     if (!keepFloatOnSameLine) {
       floatX = floatAvailableSpace.mRect.XMost() - floatMarginWidth;
     } 
     else {
       // this is the IE quirk (see few lines above)
       // the table is kept in the same line: don't let it overlap the
       // previous float 
       floatX = floatAvailableSpace.mRect.x;
     }
   }
-  const nsMargin& borderPadding = BorderPadding();
-  floatY = mY - borderPadding.top;
-  if (floatY < 0) {
-    // CSS2 spec, 9.5.1 rule [4]: "A floating box's outer top may not
-    // be higher than the top of its containing block."  (Since the
-    // containing block is the content edge of the block box, this
-    // means the margin edge of the float can't be higher than the
-    // content edge of the block that contains it.)
-    floatY = 0;
-  }
+  // CSS2 spec, 9.5.1 rule [4]: "A floating box's outer top may not
+  // be higher than the top of its containing block."  (Since the
+  // containing block is the content edge of the block box, this
+  // means the margin edge of the float can't be higher than the
+  // content edge of the block that contains it.)
+  floatY = NS_MAX(mY, mContentArea.y);
 
   // Reflow the float after computing its vertical position so it knows
   // where to break.
   nsMargin floatMargin; // computed margin
   PRBool pushedDown = mY != saveY;
   nsReflowStatus reflowStatus;
   mBlock->ReflowFloat(*this, adjustedAvailableSpace, aFloat,
                       floatMargin, pushedDown, reflowStatus);
@@ -840,29 +808,28 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
   // Likewise, if none of the float fit, and it needs to be pushed in
   // its entirety to the next page (NS_FRAME_IS_TRUNCATED), we need to
   // do the same.
   if ((mContentArea.height != NS_UNCONSTRAINEDSIZE &&
        adjustedAvailableSpace.height == NS_UNCONSTRAINEDSIZE &&
        (!mReflowState.mFlags.mIsTopOfPage || !IsAdjacentWithTop() ||
         pushedDown) &&
        aFloat->GetSize().height + floatMargin.TopBottom() >
-         mContentArea.height - floatY) ||
+         mContentArea.YMost() - floatY) ||
       NS_FRAME_IS_TRUNCATED(reflowStatus)) {
 
     PushFloatPastBreak(aFloat);
     return PR_FALSE;
   }
 
   // Calculate the actual origin of the float frame's border rect
-  // relative to the parent block; floatX/Y must be converted from space-manager
-  // coordinates to parent coordinates, and the margin must be added in
+  // relative to the parent block; the margin must be added in
   // to get the border rect
-  nsPoint origin(borderPadding.left + floatMargin.left + floatX,
-                 borderPadding.top + floatMargin.top + floatY);
+  nsPoint origin(floatMargin.left + floatX,
+                 floatMargin.top + floatY);
 
   // If float is relatively positioned, factor that in as well
   origin += aFloat->GetRelativeOffset(floatDisplay);
 
   // Position the float and make sure and views are properly
   // positioned. We need to explicitly position its child views as
   // well, since we're moving the float after flowing it.
   aFloat->SetPosition(origin);
@@ -879,33 +846,31 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
   // calculate region
   nsRect region = nsFloatManager::CalculateRegionFor(aFloat, floatMargin);
   // if the float split, then take up all of the vertical height
   if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus) &&
       (NS_UNCONSTRAINEDSIZE != mContentArea.height)) {
     region.height = NS_MAX(region.height, mContentArea.height - floatY);
   }
   nsresult rv =
-  // spacemanager translation is inset by the border+padding.
-  mFloatManager->AddFloat(aFloat,
-                          region - nsPoint(borderPadding.left, borderPadding.top));
+  mFloatManager->AddFloat(aFloat, region);
   NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "bad float placement");
   // store region
   rv = nsFloatManager::StoreRegionFor(aFloat, region);
   NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "float region storage failed");
 
   // If the float's dimensions have changed, note the damage in the
   // float manager.
   if (region != oldRegion) {
     // XXXwaterson conservative: we could probably get away with noting
     // less damage; e.g., if only height has changed, then only note the
     // area into which the float has grown or from which the float has
     // shrunk.
-    nscoord top = NS_MIN(region.y, oldRegion.y) - borderPadding.top;
-    nscoord bottom = NS_MAX(region.YMost(), oldRegion.YMost()) - borderPadding.top;
+    nscoord top = NS_MIN(region.y, oldRegion.y);
+    nscoord bottom = NS_MAX(region.YMost(), oldRegion.YMost());
     mFloatManager->IncludeInDamage(top, bottom);
   }
 
   if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus)) {
     mBlock->SplitFloat(*this, aFloat, reflowStatus);
   }
 
 #ifdef NOISY_FLOATMANAGER
@@ -988,47 +953,43 @@ nsBlockReflowState::PlaceBelowCurrentLin
 nscoord
 nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
                                 nsIFrame *aReplacedBlock,
                                 PRUint32 aFlags)
 {
 #ifdef DEBUG
   if (nsBlockFrame::gNoisyReflow) {
     nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
-    printf("clear floats: in: aY=%d(%d)\n",
-           aY, aY - BorderPadding().top);
+    printf("clear floats: in: aY=%d\n", aY);
   }
 #endif
 
 #ifdef NOISY_FLOAT_CLEARING
   printf("nsBlockReflowState::ClearFloats: aY=%d breakType=%d\n",
          aY, aBreakType);
   mFloatManager->List(stdout);
 #endif
   
-  const nsMargin& bp = BorderPadding();
   nscoord newY = aY;
 
   if (aBreakType != NS_STYLE_CLEAR_NONE) {
-    newY = bp.top +
-           mFloatManager->ClearFloats(newY - bp.top, aBreakType, aFlags);
+    newY = mFloatManager->ClearFloats(newY, aBreakType, aFlags);
   }
 
   if (aReplacedBlock) {
     for (;;) {
       nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(newY);
       nsBlockFrame::ReplacedElementWidthToClear replacedWidth =
         nsBlockFrame::WidthToClearPastFloats(*this, floatAvailableSpace.mRect,
                                              aReplacedBlock);
       if (!floatAvailableSpace.mHasFloats ||
-          NS_MAX(floatAvailableSpace.mRect.x, replacedWidth.marginLeft) +
+          NS_MAX(floatAvailableSpace.mRect.x - mContentArea.x,
+                 replacedWidth.marginLeft) +
             replacedWidth.borderBoxWidth +
-            NS_MAX(mContentArea.width -
-                     NS_MIN(mContentArea.width,
-                            floatAvailableSpace.mRect.XMost()),
+            NS_MAX(mContentArea.XMost() - floatAvailableSpace.mRect.XMost(),
                    replacedWidth.marginRight) <=
           mContentArea.width) {
         break;
       }
       // See the analogous code for inlines in nsBlockFrame::DoReflowInlineFrames
       if (floatAvailableSpace.mRect.height > 0) {
         // See if there's room in the next band.
         newY += floatAvailableSpace.mRect.height;
@@ -1042,15 +1003,15 @@ nsBlockReflowState::ClearFloats(nscoord 
         newY += 1;
       }
     }
   }
 
 #ifdef DEBUG
   if (nsBlockFrame::gNoisyReflow) {
     nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
-    printf("clear floats: out: y=%d(%d)\n", newY, newY - bp.top);
+    printf("clear floats: out: y=%d\n", newY);
   }
 #endif
 
   return newY;
 }
 
--- a/layout/generic/nsBlockReflowState.h
+++ b/layout/generic/nsBlockReflowState.h
@@ -70,18 +70,16 @@ class nsBlockReflowState {
 public:
   nsBlockReflowState(const nsHTMLReflowState& aReflowState,
                      nsPresContext* aPresContext,
                      nsBlockFrame* aFrame,
                      const nsHTMLReflowMetrics& aMetrics,
                      PRBool aTopMarginRoot, PRBool aBottomMarginRoot,
                      PRBool aBlockNeedsFloatManager);
 
-  ~nsBlockReflowState();
-
   /**
    * Get the available reflow space (the area not occupied by floats)
    * for the current y coordinate. The available space is relative to
    * our coordinate system, which is the content box, with (0, 0) in the
    * upper left.
    *
    * Returns whether there are floats present at the given vertical
    * coordinate and within the width of the content rect.
@@ -215,22 +213,25 @@ public:
   // The float manager state as it was before the contents of this
   // block.  This is needed for positioning bullets, since we only want
   // to move the bullet to flow around floats that were before this
   // block, not floats inside of it.
   nsFloatManager::SavedState mFloatManagerStateBefore;
 
   nscoord mBottomEdge;
 
-  // The content area to reflow child frames within. The x/y
-  // coordinates are known to be mBorderPadding.left and
-  // mBorderPadding.top. The width/height may be NS_UNCONSTRAINEDSIZE
-  // if the container reflowing this frame has given the frame an
-  // unconstrained area.
-  nsSize mContentArea;
+  // The content area to reflow child frames within.  This is within
+  // this frame's coordinate system, which means mContentArea.x ==
+  // BorderPadding().left and mContentArea.y == BorderPadding().top.
+  // The height may be NS_UNCONSTRAINEDSIZE, which indicates that there
+  // is no page/column boundary below (the common case).
+  // mContentArea.YMost() should only be called after checking that
+  // mContentArea.height is not NS_UNCONSTRAINEDSIZE; otherwise
+  // coordinate overflow may occur.
+  nsRect mContentArea;
 
   // Continuation out-of-flow float frames that need to move to our
   // next in flow are placed here during reflow.  It's a pointer to
   // a frame list stored in the block's property table.
   nsFrameList *mPushedFloats;
   // This method makes sure pushed floats are accessible to
   // StealFrame. Call it before adding any frames to mPushedFloats.
   void SetupPushedFloatList();
--- a/layout/generic/nsFloatManager.cpp
+++ b/layout/generic/nsFloatManager.cpp
@@ -139,21 +139,21 @@ void nsFloatManager::Shutdown()
   }
 
   // Disable further caching.
   sCachedFloatManagerCount = -1;
 }
 
 nsFlowAreaRect
 nsFloatManager::GetFlowArea(nscoord aYOffset, BandInfoType aInfoType,
-                            nscoord aHeight, nscoord aContentAreaWidth,
+                            nscoord aHeight, nsRect aContentArea,
                             SavedState* aState) const
 {
   NS_ASSERTION(aHeight >= 0, "unexpected max height");
-  NS_ASSERTION(aContentAreaWidth >= 0, "unexpected content area width");
+  NS_ASSERTION(aContentArea.width >= 0, "unexpected content area width");
 
   nscoord top = aYOffset + mY;
   if (top < nscoord_MIN) {
     NS_WARNING("bad value");
     top = nscoord_MIN;
   }
 
   // Determine the last float that we should consider.
@@ -167,35 +167,36 @@ nsFloatManager::GetFlowArea(nscoord aYOf
     floatCount = mFloats.Length();
   }
 
   // If there are no floats at all, or we're below the last one, return
   // quickly.
   if (floatCount == 0 ||
       (mFloats[floatCount-1].mLeftYMost <= top &&
        mFloats[floatCount-1].mRightYMost <= top)) {
-    return nsFlowAreaRect(0, aYOffset, aContentAreaWidth, aHeight, PR_FALSE);
+    return nsFlowAreaRect(aContentArea.x, aYOffset, aContentArea.width,
+                          aHeight, PR_FALSE);
   }
 
   nscoord bottom;
   if (aHeight == nscoord_MAX) {
     // This warning (and the two below) are possible to hit on pages
     // with really large objects.
     NS_WARN_IF_FALSE(aInfoType == BAND_FROM_POINT,
                      "bad height");
     bottom = nscoord_MAX;
   } else {
     bottom = top + aHeight;
     if (bottom < top || bottom > nscoord_MAX) {
       NS_WARNING("bad value");
       bottom = nscoord_MAX;
     }
   }
-  nscoord left = mX;
-  nscoord right = aContentAreaWidth + mX;
+  nscoord left = mX + aContentArea.x;
+  nscoord right = mX + aContentArea.XMost();
   if (right < left) {
     NS_WARNING("bad value");
     right = left;
   }
 
   // Walk backwards through the floats until we either hit the front of
   // the list or we're above |top|.
   PRBool haveFloats = PR_FALSE;
--- a/layout/generic/nsFloatManager.h
+++ b/layout/generic/nsFloatManager.h
@@ -151,34 +151,33 @@ public:
    *     boxes *throughout* that space.  (It is possible that more
    *     horizontal space could be used in part of the space if a float
    *     begins or ends in it.)  The width of the resulting rectangle
    *     can be negative.
    *
    * @param aY [in] vertical coordinate for top of available space
    *           desired
    * @param aHeight [in] see above
-   * @param aContentAreaWidth [in] the width of the content area (whose left
-   *                          edge must be zero in the current translation)
+   * @param aContentArea [in] an nsRect representing the content area
    * @param aState [in] If null, use the current state, otherwise, do
    *                    computation based only on floats present in the given
    *                    saved state.
    * @return An nsFlowAreaRect whose:
-   *           mRect is the resulting rectangle for line boxes.  It will not go
-   *             left of 0, nor right of aContentAreaWidth, but will be
+   *           mRect is the resulting rectangle for line boxes.  It will not
+   *             extend beyond aContentArea's horizontal bounds, but may be
    *             narrower when floats are present.
    *          mBandHasFloats is whether there are floats at the sides of the
    *            return value including those that do not reduce the line box
    *            width at all (because they are entirely in the margins)
    *
    * aY and aAvailSpace are positioned relative to the current translation
    */
   enum BandInfoType { BAND_FROM_POINT, WIDTH_WITHIN_HEIGHT };
   nsFlowAreaRect GetFlowArea(nscoord aY, BandInfoType aInfoType,
-                             nscoord aHeight, nscoord aContentAreaWidth,
+                             nscoord aHeight, nsRect aContentArea,
                              SavedState* aState) const;
 
   /**
    * Add a float that comes after all floats previously added.  Its top
    * must be even with or below the top of all previous floats.
    *
    * aMarginRect is relative to the current translation.  The caller
    * must ensure aMarginRect.height >= 0 and aMarginRect.width >= 0.
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -1152,39 +1152,16 @@ nsXULScrollFrame::GetMaxSize(nsBoxLayout
   nsSize maxSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
 
   AddBorderAndPadding(maxSize);
   PRBool widthSet, heightSet;
   nsIBox::AddCSSMaxSize(this, maxSize, widthSet, heightSet);
   return maxSize;
 }
 
-#if 0 // XXXldb I don't think this is even needed
-/* virtual */ nscoord
-nsXULScrollFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
-{
-  nsStyleUnit widthUnit = GetStylePosition()->mWidth.GetUnit();
-  if (widthUnit == eStyleUnit_Percent || widthUnit == eStyleUnit_Auto) {
-    nsMargin border = aReflowState.mComputedBorderPadding;
-    aDesiredSize.mMaxElementWidth = border.right + border.left;
-    mMaxElementWidth = aDesiredSize.mMaxElementWidth;
-  } else {
-    NS_NOTYETIMPLEMENTED("Use the info from the scrolled frame");
-#if 0
-    // if not set then use the cached size. If set then set it.
-    if (aDesiredSize.mMaxElementWidth == -1)
-      aDesiredSize.mMaxElementWidth = mMaxElementWidth;
-    else
-      mMaxElementWidth = aDesiredSize.mMaxElementWidth;
-#endif
-  }
-  return 0;
-}
-#endif
-
 #ifdef NS_DEBUG
 NS_IMETHODIMP
 nsXULScrollFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("XULScroll"), aResult);
 }
 #endif
 
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -120,42 +120,41 @@ nsImageFrame::IconLoad* nsImageFrame::gI
 nsIIOService* nsImageFrame::sIOService;
 
 // test if the width and height are fixed, looking at the style data
 static PRBool HaveFixedSize(const nsStylePosition* aStylePosition)
 {
   // check the width and height values in the reflow state's style struct
   // - if width and height are specified as either coord or percentage, then
   //   the size of the image frame is constrained
-  nsStyleUnit widthUnit = aStylePosition->mWidth.GetUnit();
-  nsStyleUnit heightUnit = aStylePosition->mHeight.GetUnit();
-
-  return ((widthUnit  == eStyleUnit_Coord ||
-           widthUnit  == eStyleUnit_Percent) &&
-          (heightUnit == eStyleUnit_Coord ||
-           heightUnit == eStyleUnit_Percent));
+  return aStylePosition->mWidth.IsCoordPercentCalcUnit() &&
+         aStylePosition->mHeight.IsCoordPercentCalcUnit();
 }
 // use the data in the reflow state to decide if the image has a constrained size
 // (i.e. width and height that are based on the containing block size and not the image size) 
 // so we can avoid animated GIF related reflows
 inline PRBool HaveFixedSize(const nsHTMLReflowState& aReflowState)
 { 
   NS_ASSERTION(aReflowState.mStylePosition, "crappy reflowState - null stylePosition");
   // when an image has percent css style height or width, but ComputedHeight() 
   // or ComputedWidth() of reflow state is  NS_UNCONSTRAINEDSIZE  
   // it needs to return PR_FALSE to cause an incremental reflow later
   // if an image is inside table like bug 156731 simple testcase III, 
   // during pass 1 reflow, ComputedWidth() is NS_UNCONSTRAINEDSIZE
   // in pass 2 reflow, ComputedWidth() is 0, it also needs to return PR_FALSE
   // see bug 156731
-  nsStyleUnit heightUnit = (*(aReflowState.mStylePosition)).mHeight.GetUnit();
-  nsStyleUnit widthUnit = (*(aReflowState.mStylePosition)).mWidth.GetUnit();
-  return ((eStyleUnit_Percent == heightUnit && NS_UNCONSTRAINEDSIZE == aReflowState.ComputedHeight()) ||
-          (eStyleUnit_Percent == widthUnit && (NS_UNCONSTRAINEDSIZE == aReflowState.ComputedWidth() ||
-           0 == aReflowState.ComputedWidth())))
+  const nsStyleCoord &height = aReflowState.mStylePosition->mHeight;
+  const nsStyleCoord &width = aReflowState.mStylePosition->mWidth;
+  return (((eStyleUnit_Percent == height.GetUnit() ||
+            (height.IsCalcUnit() && height.CalcHasPercent())) &&
+           NS_UNCONSTRAINEDSIZE == aReflowState.ComputedHeight()) ||
+          ((eStyleUnit_Percent == width.GetUnit() ||
+            (width.IsCalcUnit() && width.CalcHasPercent())) &&
+           (NS_UNCONSTRAINEDSIZE == aReflowState.ComputedWidth() ||
+            0 == aReflowState.ComputedWidth())))
           ? PR_FALSE
           : HaveFixedSize(aReflowState.mStylePosition); 
 }
 
 nsIFrame*
 NS_NewImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsImageFrame(aContext);
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -648,26 +648,16 @@ HasPercentageUnitSide(const nsStyleSides
 {
   NS_FOR_CSS_SIDES(side) {
     if (eStyleUnit_Percent == aSides.GetUnit(side))
       return PR_TRUE;
   }
   return PR_FALSE;
 }
 
-inline PRBool
-WidthDependsOnContainer(const nsStyleCoord& aCoord)
-{
-  return aCoord.GetUnit() == eStyleUnit_Percent ||
-         (aCoord.GetUnit() == eStyleUnit_Enumerated &&
-          (aCoord.GetIntValue() == NS_STYLE_WIDTH_AVAILABLE ||
-           aCoord.GetIntValue() == NS_STYLE_WIDTH_FIT_CONTENT));
-
-}
-
 static PRBool
 IsPercentageAware(const nsIFrame* aFrame)
 {
   NS_ASSERTION(aFrame, "null frame is not allowed");
 
   nsIAtom *fType = aFrame->GetType();
   if (fType == nsGkAtoms::textFrame) {
     // None of these things can ever be true for text frames.
@@ -689,19 +679,20 @@ IsPercentageAware(const nsIFrame* aFrame
   if (HasPercentageUnitSide(padding->mPadding)) {
     return PR_TRUE;
   }
 
   // Note that borders can't be aware of percentages
 
   const nsStylePosition* pos = aFrame->GetStylePosition();
 
-  if (WidthDependsOnContainer(pos->mWidth) ||
-      WidthDependsOnContainer(pos->mMaxWidth) ||
-      WidthDependsOnContainer(pos->mMinWidth) ||
+  if ((pos->WidthDependsOnContainer() &&
+       pos->mWidth.GetUnit() != eStyleUnit_Auto) ||
+      pos->MaxWidthDependsOnContainer() ||
+      pos->MinWidthDependsOnContainer() ||
       eStyleUnit_Percent == pos->mOffset.GetRightUnit() ||
       eStyleUnit_Percent == pos->mOffset.GetLeftUnit()) {
     return PR_TRUE;
   }
 
   if (eStyleUnit_Auto == pos->mWidth.GetUnit()) {
     // We need to check for frames that shrink-wrap when they're auto
     // width.
@@ -817,35 +808,26 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
   
   // Apply start margins (as appropriate) to the frame computing the
   // new starting x,y coordinates for the frame.
   ApplyStartMargin(pfd, reflowState);
 
   // Let frame know that are reflowing it. Note that we don't bother
   // positioning the frame yet, because we're probably going to end up
   // moving it when we do the vertical alignment
-  nscoord x = pfd->mBounds.x;
-  nscoord y = pfd->mBounds.y;
-
   aFrame->WillReflow(mPresContext);
 
-  // Adjust spacemanager coordinate system for the frame. The
-  // spacemanager coordinates are <b>inside</b> the current spans
-  // border+padding, but the x/y coordinates are not (recall that
-  // frame coordinates are relative to the parents origin and that the
-  // parents border/padding is <b>inside</b> the parent
-  // frame. Therefore we have to subtract out the parents
-  // border+padding before translating.
+  // Adjust spacemanager coordinate system for the frame.
   nsHTMLReflowMetrics metrics;
 #ifdef DEBUG
   metrics.width = nscoord(0xdeadbeef);
   metrics.height = nscoord(0xdeadbeef);
 #endif
-  nscoord tx = x - psd->mReflowState->mComputedBorderPadding.left;
-  nscoord ty = y - psd->mReflowState->mComputedBorderPadding.top;
+  nscoord tx = pfd->mBounds.x;
+  nscoord ty = pfd->mBounds.y;
   mFloatManager->Translate(tx, ty);
 
   nsIAtom* frameType = aFrame->GetType();
   PRInt32 savedOptionalBreakOffset;
   gfxBreakPriority savedOptionalBreakPriority;
   nsIContent* savedOptionalBreakContent =
     GetLastOptionalBreakPosition(&savedOptionalBreakOffset,
                                  &savedOptionalBreakPriority);
--- a/layout/generic/nsSpacerFrame.cpp
+++ b/layout/generic/nsSpacerFrame.cpp
@@ -167,16 +167,17 @@ SpacerFrame::GetDesiredSize(nsHTMLReflow
     if (eStyleUnit_Coord == unit) {
       aMetrics.width = position->mWidth.GetCoordValue();
     }
     else if (eStyleUnit_Percent == unit) 
     {
       float factor = position->mWidth.GetPercentValue();
       aMetrics.width = NSToCoordRound(factor * aPercentBase.width);
     }
+    // else treat enumerated values and calc() like 'auto'
 
     // height
     unit = position->mHeight.GetUnit();
     if (eStyleUnit_Coord == unit) {
       aMetrics.height = position->mHeight.GetCoordValue();
     }
     else if (eStyleUnit_Percent == unit) 
     {
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-calc/reftest.list
@@ -0,0 +1,4 @@
+== width-block-1.html width-block-1-ref.html
+== width-block-intrinsic-1.html width-block-intrinsic-1-ref.html
+== width-table-auto-1.html width-table-auto-1-ref.html
+== width-table-fixed-1.html width-table-fixed-1-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-calc/width-block-1-ref.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<title>width: calc() on blocks</title>
+<style>
+
+body { width: 500px }
+p { background: green; color: white; margin: 1px 0; font-size: 10px }
+
+</style>
+
+<p style="width: 247px">50% - 3px</p>
+<p style="width: 247px">25% - 3px + 25%</p>
+<p style="width: 247px">25% - 3px + 12.5% * 2</p>
+<p style="width: 247px">25% - 3px + 12.5%*2</p>
+<p style="width: 247px">25% - 3px + 2*12.5%</p>
+<p style="width: 247px">25% - 3px + 2 * 12.5%</p>
+<p style="width: 125px">min(25%, 150px)</p>
+<p style="width: 100px">min(25%, 100px)</p>
+<p style="width: 150px">max(25%, 150px)</p>
+<p style="width: 125px">max(25%, 100px)</p>
+<p style="width: 150px">min(25%, 150px) + 5%</p>
+<p style="width: 125px">min(25%, 100px) + 5%</p>
+<p style="width: 175px">max(25%, 150px) + 5%</p>
+<p style="width: 150px">max(25%, 100px) + 5%</p>
+<p style="width: 105px">min(25%, 150px) - 2em</p>
+<p style="width: 80px">min(25%, 100px) - 2em</p>
+<p style="width: 130px">max(25%, 150px) - 2em</p>
+<p style="width: 105px">max(25%, 100px) - 2em</p>
+<p style="width: 250px">30% + 20%</p>
+<p style="width: 250px">30% + max(20%, 1px)</p>
+<p style="width: 250px">max(25%, 50%)</p>
+<p style="width: 125px">max(25%, 50%)</p>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-calc/width-block-1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<title>width: calc() on blocks</title>
+<style>
+
+body { width: 500px }
+p { background: green; color: white; margin: 1px 0; font-size: 10px }
+
+</style>
+
+<p style="width: -moz-calc(50% - 3px)">50% - 3px</p>
+<p style="width: -moz-calc(25% - 3px + 25%)">25% - 3px + 25%</p>
+<p style="width: -moz-calc(25% - 3px + 12.5% * 2)">25% - 3px + 12.5% * 2</p>
+<p style="width: -moz-calc(25% - 3px + 12.5%*2)">25% - 3px + 12.5%*2</p>
+<p style="width: -moz-calc(25% - 3px + 2*12.5%)">25% - 3px + 2*12.5%</p>
+<p style="width: -moz-calc(25% - 3px + 2 * 12.5%)">25% - 3px + 2 * 12.5%</p>
+<p style="width: -moz-min(25%, 150px)">min(25%, 150px)</p>
+<p style="width: -moz-calc(min(25%, 100px))">min(25%, 100px)</p>
+<p style="width: -moz-calc(max(25%, 150px))">max(25%, 150px)</p>
+<p style="width: -moz-max(25%, 100px)">max(25%, 100px)</p>
+<p style="width: -moz-calc(min(25%, 150px) + 5%)">min(25%, 150px) + 5%</p>
+<p style="width: -moz-calc(min(25%, 100px) + 5%)">min(25%, 100px) + 5%</p>
+<p style="width: -moz-calc(max(25%, 150px) + 5%)">max(25%, 150px) + 5%</p>
+<p style="width: -moz-calc(max(25%, 100px) + 5%)">max(25%, 100px) + 5%</p>
+<p style="width: -moz-calc(min(25%, 150px) - 2em)">min(25%, 150px) - 2em</p>
+<p style="width: -moz-calc(min(25%, 100px) - 2em)">min(25%, 100px) - 2em</p>
+<p style="width: -moz-calc(max(25%, 150px) - 2em)">max(25%, 150px) - 2em</p>
+<p style="width: -moz-calc(max(25%, 100px) - 2em)">max(25%, 100px) - 2em</p>
+<p style="width: -moz-calc(30% + 20%)">30% + 20%</p>
+<p style="width: -moz-calc(30% + max(20%, 1px))">30% + max(20%, 1px)</p>
+<p style="width: -moz-calc(max(25%, 50%))">max(25%, 50%)</p>
+<p style="width: -moz-calc(min(25%, 50%))">max(25%, 50%)</p>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-calc/width-block-intrinsic-1-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<title>intrinsic width of width: calc() on blocks</title>
+<style>
+
+body > div { margin: 0 0 1px 0; background: blue; color: white; height: 5px }
+
+</style>
+
+<div style="width: 200px"></div>
+<div style="width: 47px"></div>
+<div style="width: 47px"></div>
+<div style="width: 200px"></div>
+<div style="width: 200px"></div>
+<div style="width: 50px"></div>
+<div style="width: 200px"></div>
+<div style="width: 200px"></div>
+<div style="width: 50px"></div>
+<div style="width: 200px"></div>
+<div style="width: 200px"></div>
+<div style="width: 200px"></div>
+<div style="width: 200px"></div>
+<div style="width: 200px"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-calc/width-block-intrinsic-1.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<title>intrinsic width of width: calc() on blocks</title>
+<style>
+
+body { font-size: 10px }
+body > div { float: left; clear: left;
+             margin: 0 0 1px 0; background: blue; color: white; height: 5px }
+body > div > div > div { width: 200px }
+
+</style>
+
+<div><div style="width: -moz-calc(50% - 3px)"><div></div></div></div>
+<div><div style="width: -moz-calc(5em - 3px)"><div></div></div></div>
+<div><div style="width: -moz-calc(max(5em, 0) - 3px)"><div></div></div></div>
+<div><div style="width: -moz-calc(max(5em, 0%) - 3px)"><div></div></div></div>
+<div><div style="width: -moz-calc(5em - min(3px, 0%))"><div></div></div></div>
+<div><div style="width: -moz-calc(5em - min(3px, 0))"><div></div></div></div>
+<div><div style="width: -moz-calc(5em - 0%)"><div></div></div></div>
+<div><div style="width: -moz-calc(50%)"><div></div></div></div>
+<div><div style="width: -moz-calc(50px)"><div></div></div></div>
+<div><div style="width: -moz-calc(25% + 25%)"><div></div></div></div>
+<div><div style="width: -moz-calc(min(25%, 50%))"><div></div></div></div>
+<div><div style="width: -moz-calc(max(25%, 50%))"><div></div></div></div>
+<div><div style="width: -moz-calc(min(25%, 100px))"><div></div></div></div>
+<div><div style="width: -moz-calc(max(25%, 100px))"><div></div></div></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-calc/width-table-auto-1-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<title>width: calc() on table-layout: auto tables</title>
+<table border>
+  <tr>
+    <td>x</td>
+    <td style="width: 100px">y</td>
+</table>
+<table border>
+  <tr>
+    <td>x</td>
+    <td style="width: 100px">y</td>
+</table>
+<table border>
+  <tr>
+    <td>x</td>
+    <td style="width: 100px">y</td>
+</table>
+<table border>
+  <tr>
+    <td>x</td>
+    <td style="width: 100px">y</td>
+</table>
+<table border>
+  <tr>
+    <td>x</td>
+    <td style="width: 100px">y</td>
+</table>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-calc/width-table-auto-1.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<title>width: calc() on table-layout: auto tables</title>
+<table border>
+  <tr>
+    <td style="width: -moz-calc(500px)">x</td>
+    <td style="width: 100px">y</td>
+</table>
+<table border>
+  <tr>
+    <td style="width: -moz-calc(50%)">x</td>
+    <td style="width: 100px">y</td>
+</table>
+<table border>
+  <tr>
+    <td style="width: -moz-calc(min(50%, 500px))">x</td>
+    <td style="width: 100px">y</td>
+</table>
+<table border>
+  <tr>
+    <td style="width: -moz-calc(max(50%, 500px))">x</td>
+    <td style="width: 100px">y</td>
+</table>
+<table border>
+  <tr>
+    <td style="width: -moz-calc(2 * 10% + 0.5 * 500px)">x</td>
+    <td style="width: 100px">y</td>
+</table>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-calc/width-table-fixed-1-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<title>width: calc() on table-layout: auto tables</title>
+<style>
+table { table-layout: fixed; width: 500px; border-spacing: 0 }
+</style>
+<table border>
+  <tr>
+    <td>x</td>
+    <td style="width: 100px">y</td>
+</table>
+<table border>
+  <tr>
+    <td>x</td>
+    <td style="width: 100px">y</td>
+</table>
+<table border>
+  <tr>
+    <td>x</td>
+    <td style="width: 100px">y</td>
+</table>
+<table border>
+  <tr>
+    <td>x</td>
+    <td style="width: 100px">y</td>
+</table>
+<table border>
+  <tr>
+    <td>x</td>
+    <td style="width: 100px">y</td>
+</table>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-calc/width-table-fixed-1.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<title>width: calc() on table-layout: auto tables</title>
+<style>
+table { table-layout: fixed; width: 500px; border-spacing: 0 }
+</style>
+<table border>
+  <tr>
+    <td style="width: -moz-calc(500px)">x</td>
+    <td style="width: 100px">y</td>
+</table>
+<table border>
+  <tr>
+    <td style="width: -moz-calc(50%)">x</td>
+    <td style="width: 100px">y</td>
+</table>
+<table border>
+  <tr>
+    <td style="width: -moz-calc(min(50%, 500px))">x</td>
+    <td style="width: 100px">y</td>
+</table>
+<table border>
+  <tr>
+    <td style="width: -moz-calc(max(50%, 500px))">x</td>
+    <td style="width: 100px">y</td>
+</table>
+<table border>
+  <tr>
+    <td style="width: -moz-calc(2 * 10% + 0.5 * 500px)">x</td>
+    <td style="width: 100px">y</td>
+</table>
--- a/layout/reftests/reftest.list
+++ b/layout/reftests/reftest.list
@@ -36,25 +36,28 @@ include box-properties/reftest.list
 include box-shadow/reftest.list
 
 # bugs/
 include bugs/reftest.list
 
 # canvas 2D
 include canvas/reftest.list
 
+# css calc() tests
+include css-calc/reftest.list
+
+# css character encoding tests
+include css-charset/reftest.list
+
 # css default pseudo class tests
 include css-default/reftest.list
 
 # css @import tests
 include css-import/reftest.list
 
-# css character encoding tests
-include css-charset/reftest.list
-
 # css gradients
 include css-gradients/reftest.list
 
 # css media queries (tests for print mode)
 include css-mediaqueries/reftest.list
 
 # css namespaces
 include css-namespace/reftest.list
--- a/layout/style/CSSCalc.h
+++ b/layout/style/CSSCalc.h
@@ -33,16 +33,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef CSSCalc_h_
 #define CSSCalc_h_
 
 #include "nsCSSValue.h"
+#include "nsStyleCoord.h"
 #include <math.h>
 
 namespace mozilla {
 
 namespace css {
 
 /**
  * ComputeCalc computes the result of a calc() expression tree.
@@ -147,32 +148,88 @@ ComputeCalc(const typename CalcOps::inpu
       return result;
     }
     default: {
       return aOps.ComputeLeafValue(aValue);
     }
   }
 }
 
+#define CHECK_UNIT(u_)                                                        \
+  PR_STATIC_ASSERT(int(eCSSUnit_##u_) + 14 == int(eStyleUnit_##u_));          \
+  PR_STATIC_ASSERT(eCSSUnit_##u_ >= eCSSUnit_Calc);                           \
+  PR_STATIC_ASSERT(eCSSUnit_##u_ <= eCSSUnit_Calc_Maximum);
+
+CHECK_UNIT(Calc)
+CHECK_UNIT(Calc_Plus)
+CHECK_UNIT(Calc_Minus)
+CHECK_UNIT(Calc_Times_L)
+CHECK_UNIT(Calc_Times_R)
+CHECK_UNIT(Calc_Divided)
+CHECK_UNIT(Calc_Minimum)
+CHECK_UNIT(Calc_Maximum)
+
+#undef CHECK_UNIT
+
+inline nsStyleUnit
+ConvertCalcUnit(nsCSSUnit aUnit)
+{
+  NS_ABORT_IF_FALSE(eCSSUnit_Calc <= aUnit &&
+                    aUnit <= eCSSUnit_Calc_Maximum, "out of range");
+  return nsStyleUnit(aUnit + 14);
+}
+
+inline nsCSSUnit
+ConvertCalcUnit(nsStyleUnit aUnit)
+{
+  NS_ABORT_IF_FALSE(eStyleUnit_Calc <= aUnit &&
+                    aUnit <= eStyleUnit_Calc_Maximum, "out of range");
+  return nsCSSUnit(aUnit - 14);
+}
+
 /**
  * The input unit operation for input_type being nsCSSValue.
  */
 struct CSSValueInputCalcOps
 {
   typedef nsCSSValue input_type;
   typedef nsCSSValue::Array input_array_type;
 
   static nsCSSUnit GetUnit(const nsCSSValue& aValue)
   {
     return aValue.GetUnit();
   }
 
 };
 
 /**
+ * The input unit operation for input_type being nsStyleCoord
+ */
+struct StyleCoordInputCalcOps
+{
+  typedef nsStyleCoord input_type;
+  typedef nsStyleCoord::Array input_array_type;
+
+  static nsCSSUnit GetUnit(const nsStyleCoord& aValue)
+  {
+    if (aValue.IsCalcUnit()) {
+      return css::ConvertCalcUnit(aValue.GetUnit());
+    }
+    return eCSSUnit_Null;
+  }
+
+  float ComputeNumber(const nsStyleCoord& aValue)
+  {
+    NS_ABORT_IF_FALSE(PR_FALSE, "SpecifiedToComputedCalcOps should not "
+                                "leave numbers in structure");
+    return 0.0f;
+  }
+};
+
+/**
  * Basic*CalcOps provide a partial implementation of the CalcOps
  * template parameter to ComputeCalc, for those callers whose merging
  * just consists of mathematics (rather than tree construction).
  */
 
 struct BasicCoordCalcOps
 {
   typedef nscoord result_type;
@@ -270,47 +327,16 @@ struct NumbersAlreadyNormalizedOps : pub
 {
   float ComputeNumber(const nsCSSValue& aValue)
   {
     NS_ABORT_IF_FALSE(aValue.GetUnit() == eCSSUnit_Number, "unexpected unit");
     return aValue.GetFloatValue();
   }
 };
 
-#define CHECK_UNIT(u_)                                                        \
-  PR_STATIC_ASSERT(int(eCSSUnit_Calc_##u_) + 14 == int(eStyleUnit_Calc_##u_));\
-  PR_STATIC_ASSERT(eCSSUnit_Calc_##u_ >= eCSSUnit_Calc_Plus);                 \
-  PR_STATIC_ASSERT(eCSSUnit_Calc_##u_ <= eCSSUnit_Calc_Maximum);
-
-CHECK_UNIT(Plus)
-CHECK_UNIT(Minus)
-CHECK_UNIT(Times_L)
-CHECK_UNIT(Times_R)
-CHECK_UNIT(Divided)
-CHECK_UNIT(Minimum)
-CHECK_UNIT(Maximum)
-
-#undef CHECK_UNIT
-
-inline nsStyleUnit
-ConvertCalcUnit(nsCSSUnit aUnit)
-{
-  NS_ABORT_IF_FALSE(eCSSUnit_Calc_Plus <= aUnit &&
-                    aUnit <= eCSSUnit_Calc_Maximum, "out of range");
-  return nsStyleUnit(aUnit + 14);
-}
-
-inline nsCSSUnit
-ConvertCalcUnit(nsStyleUnit aUnit)
-{
-  NS_ABORT_IF_FALSE(eStyleUnit_Calc_Plus <= aUnit &&
-                    aUnit <= eStyleUnit_Calc_Maximum, "out of range");
-  return nsCSSUnit(aUnit - 14);
-}
-
 /**
  * SerializeCalc appends the serialization of aValue to a string.
  *
  * It is templatized over a CalcOps class that is expected to provide:
  *
  *   // input_type and input_array_type have a bunch of very specific
  *   // expectations (which happen to be met by two classes (nsCSSValue
  *   // and nsStyleCoord).  There must be methods (roughly):
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -507,17 +507,19 @@ protected:
   nsCSSValueList* ParseCSSShadowList(PRBool aIsBoxShadow);
   PRBool ParseTextShadow();
   PRBool ParseBoxShadow();
   PRBool ParseTransitionTime(nsCSSProperty aPropID);
   PRBool ParseTransitionProperty();
   PRBool ParseTransition();
   PRBool ParseTransitionTimingFunction();
   PRBool ParseTransitionTimingFunctionValues(nsCSSValue& aValue);
-  PRBool ParseTransitionTimingFunctionValueComponent(float& aComponent, char aStop);
+  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 ParseDasharray();
   PRBool ParseMarker();
@@ -1302,16 +1304,17 @@ CSSParserImpl::GetToken(PRBool aSkipWS)
 }
 
 PRBool
 CSSParserImpl::GetURLInParens(nsString& aURL)
 {
   NS_ASSERTION(!mHavePushBack, "mustn't have pushback at this point");
   do {
     if (! mScanner.NextURL(mToken)) {
+      // EOF
       return PR_FALSE;
     }
   } while (eCSSToken_WhiteSpace == mToken.mType);
 
   aURL = mToken.mIdent;
 
   if ((eCSSToken_String != mToken.mType && eCSSToken_URL != mToken.mType) ||
       !ExpectSymbol(')', PR_TRUE)) {
@@ -3608,53 +3611,57 @@ CSSParserImpl::ParseColor(nsCSSValue& aV
         PRUint8 r, g, b;
         PRInt32 type = COLOR_TYPE_UNKNOWN;
         if (ParseColorComponent(r, type, ',') &&
             ParseColorComponent(g, type, ',') &&
             ParseColorComponent(b, type, ')')) {
           aValue.SetColorValue(NS_RGB(r,g,b));
           return PR_TRUE;
         }
-        return PR_FALSE;  // already pushed back
+        SkipUntil(')');
+        return PR_FALSE;
       }
       else if (mToken.mIdent.LowerCaseEqualsLiteral("-moz-rgba") ||
                mToken.mIdent.LowerCaseEqualsLiteral("rgba")) {
         // rgba ( component , component , component , opacity )
         PRUint8 r, g, b, a;
         PRInt32 type = COLOR_TYPE_UNKNOWN;
         if (ParseColorComponent(r, type, ',') &&
             ParseColorComponent(g, type, ',') &&
             ParseColorComponent(b, type, ',') &&
             ParseColorOpacity(a)) {
           aValue.SetColorValue(NS_RGBA(r, g, b, a));
           return PR_TRUE;
         }
-        return PR_FALSE;  // already pushed back
+        SkipUntil(')');
+        return PR_FALSE;
       }
       else if (mToken.mIdent.LowerCaseEqualsLiteral("hsl")) {
         // hsl ( hue , saturation , lightness )
         // "hue" is a number, "saturation" and "lightness" are percentages.
         if (ParseHSLColor(rgba, ')')) {
           aValue.SetColorValue(rgba);
           return PR_TRUE;
         }
+        SkipUntil(')');
         return PR_FALSE;
       }
       else if (mToken.mIdent.LowerCaseEqualsLiteral("-moz-hsla") ||
                mToken.mIdent.LowerCaseEqualsLiteral("hsla")) {
         // hsla ( hue , saturation , lightness , opacity )
         // "hue" is a number, "saturation" and "lightness" are percentages,
         // "opacity" is a number.
         PRUint8 a;
         if (ParseHSLColor(rgba, ',') &&
             ParseColorOpacity(a)) {
           aValue.SetColorValue(NS_RGBA(NS_GET_R(rgba), NS_GET_G(rgba),
                                        NS_GET_B(rgba), a));
           return PR_TRUE;
         }
+        SkipUntil(')');
         return PR_FALSE;
       }
       break;
     default:
       break;
   }
 
   // try 'xxyyzz' without '#' prefix for compatibility with IE and Nav4x (bug 23236 and 45804)
@@ -4467,22 +4474,30 @@ CSSParserImpl::ParseVariant(nsCSSValue& 
       (eCSSToken_Function == tk->mType) &&
       (tk->mIdent.LowerCaseEqualsLiteral("counter") ||
        tk->mIdent.LowerCaseEqualsLiteral("counters"))) {
     return ParseCounter(aValue);
   }
   if (((aVariantMask & VARIANT_ATTR) != 0) &&
       (eCSSToken_Function == tk->mType) &&
       tk->mIdent.LowerCaseEqualsLiteral("attr")) {
-    return ParseAttr(aValue);
+    if (!ParseAttr(aValue)) {
+      SkipUntil(')');
+      return PR_FALSE;
+    }
+    return PR_TRUE;
   }
   if (((aVariantMask & VARIANT_CUBIC_BEZIER) != 0) &&
       (eCSSToken_Function == tk->mType)) {
      if (tk->mIdent.LowerCaseEqualsLiteral("cubic-bezier")) {
-      return ParseTransitionTimingFunctionValues(aValue);
+      if (!ParseTransitionTimingFunctionValues(aValue)) {
+        SkipUntil(')');
+        return PR_FALSE;
+      }
+      return PR_TRUE;
     }
   }
   if ((aVariantMask & VARIANT_CALC) &&
       (eCSSToken_Function == tk->mType) &&
       (tk->mIdent.LowerCaseEqualsLiteral("-moz-calc") ||
        tk->mIdent.LowerCaseEqualsLiteral("-moz-min") ||
        tk->mIdent.LowerCaseEqualsLiteral("-moz-max"))) {
     // calc() currently allows only lengths and percents inside it.
@@ -5724,17 +5739,17 @@ CSSParserImpl::ParseSingleValueProperty(
                         nsCSSProps::kTextRenderingKTable);
 #endif
   case eCSSProperty_box_sizing:
     return ParseVariant(aValue, VARIANT_HK,
                         nsCSSProps::kBoxSizingKTable);
   case eCSSProperty_height:
     return ParseNonNegativeVariant(aValue, VARIANT_AHLP, nsnull);
   case eCSSProperty_width:
-    return ParseNonNegativeVariant(aValue, VARIANT_AHKLP,
+    return ParseNonNegativeVariant(aValue, VARIANT_AHKLP | VARIANT_CALC,
                                    nsCSSProps::kWidthKTable);
   case eCSSProperty_force_broken_image_icon:
     return ParseNonNegativeVariant(aValue, VARIANT_HI, nsnull);
   case eCSSProperty_caption_side:
     return ParseVariant(aValue, VARIANT_HK,
                         nsCSSProps::kCaptionSideKTable);
   case eCSSProperty_clear:
     return ParseVariant(aValue, VARIANT_HK,
@@ -8854,43 +8869,48 @@ CSSParserImpl::ParseTransitionTimingFunc
 
   nsRefPtr<nsCSSValue::Array> val = nsCSSValue::Array::Create(4);
   if (!val) {
     mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
     return PR_FALSE;
   }
 
   float x1, x2, y1, y2;
-  if (!ParseTransitionTimingFunctionValueComponent(x1, ',') ||
-      !ParseTransitionTimingFunctionValueComponent(y1, ',') ||
-      !ParseTransitionTimingFunctionValueComponent(x2, ',') ||
-      !ParseTransitionTimingFunctionValueComponent(y2, ')')) {
+  if (!ParseTransitionTimingFunctionValueComponent(x1, ',', PR_TRUE) ||
+      !ParseTransitionTimingFunctionValueComponent(y1, ',', PR_FALSE) ||
+      !ParseTransitionTimingFunctionValueComponent(x2, ',', PR_TRUE) ||
+      !ParseTransitionTimingFunctionValueComponent(y2, ')', PR_FALSE)) {
     return PR_FALSE;
   }
 
   val->Item(0).SetFloatValue(x1, eCSSUnit_Number);
   val->Item(1).SetFloatValue(y1, eCSSUnit_Number);
   val->Item(2).SetFloatValue(x2, eCSSUnit_Number);
   val->Item(3).SetFloatValue(y2, eCSSUnit_Number);
 
   aValue.SetArrayValue(val, eCSSUnit_Cubic_Bezier);
 
   return PR_TRUE;
 }
 
 PRBool
 CSSParserImpl::ParseTransitionTimingFunctionValueComponent(float& aComponent,
-                                                           char aStop)
+                                                           char aStop,
+                                                           PRBool aCheckRange)
 {
   if (!GetToken(PR_TRUE)) {
     return PR_FALSE;
   }
   nsCSSToken* tk = &mToken;
   if (tk->mType == eCSSToken_Number) {
-    aComponent = tk->mNumber;
+    float num = tk->mNumber;
+    if (aCheckRange && (num < 0.0 || num > 1.0)) {
+      return PR_FALSE;
+    }
+    aComponent = num;
     if (ExpectSymbol(aStop, PR_TRUE)) {
       return PR_TRUE;
     }
   }
   return PR_FALSE;
 }
 
 PRBool
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -505,31 +505,29 @@ struct SpecifiedToComputedCalcOps : publ
 static void
 SpecifiedCalcToComputedCalc(const nsCSSValue& aValue, nsStyleCoord& aCoord, 
                             nsStyleContext* aStyleContext,
                             PRBool& aCanStoreInRuleTree)
 {
   SpecifiedToComputedCalcOps ops(aStyleContext, aStyleContext->PresContext(),
                                  aCanStoreInRuleTree);
   aCoord = ComputeCalc(aValue, ops);
+  if (!aCoord.IsCalcUnit()) {
+    // Some callers distinguish between calc(50%) and 50%, or calc(50px)
+    // and 50px.
+    nsStyleCoord::Array *array =
+      nsStyleCoord::Array::Create(aStyleContext, aCanStoreInRuleTree, 1);
+    array->Item(0) = aCoord;
+    aCoord.SetArrayValue(array, eStyleUnit_Calc);
+  }
 }
 
-struct ComputeComputedCalcCalcOps : public css::BasicCoordCalcOps
+struct ComputeComputedCalcCalcOps : public css::StyleCoordInputCalcOps,
+                                    public css::BasicCoordCalcOps
 {
-  typedef nsStyleCoord input_type;
-  typedef nsStyleCoord::Array input_array_type;
-
-  static nsCSSUnit GetUnit(const nsStyleCoord& aValue)
-  {
-    if (aValue.IsCalcUnit()) {
-      return css::ConvertCalcUnit(aValue.GetUnit());
-    }
-    return eCSSUnit_Null;
-  }
-
   const nscoord mPercentageBasis;
 
   ComputeComputedCalcCalcOps(nscoord aPercentageBasis)
     : mPercentageBasis(aPercentageBasis)
   {
   }
 
   result_type ComputeLeafValue(const nsStyleCoord& aValue)
@@ -538,51 +536,28 @@ struct ComputeComputedCalcCalcOps : publ
     if (aValue.GetUnit() == eStyleUnit_Percent) {
       result = NSCoordSaturatingMultiply(mPercentageBasis,
                                          aValue.GetPercentValue());
     } else {
       result = aValue.GetCoordValue();
     }
     return result;
   }
-
-  float ComputeNumber(const nsStyleCoord& aValue)
-  {
-    NS_ABORT_IF_FALSE(PR_FALSE, "SpecifiedToComputedCalcOps should not "
-                                "leave numbers in structure");
-    return 0.0f;
-  }
 };
 
 // This is our public API for handling calc() expressions that involve
 // percentages.
 /* static */ nscoord
 nsRuleNode::ComputeComputedCalc(const nsStyleCoord& aValue,
                                 nscoord aPercentageBasis)
 {
   ComputeComputedCalcCalcOps ops(aPercentageBasis);
   return css::ComputeCalc(aValue, ops);
 }
 
-/* static */ nscoord
-nsRuleNode::ComputeCoordPercentCalc(const nsStyleCoord& aCoord,
-                                    nscoord aPercentageBasis)
-{
-  switch (aCoord.GetUnit()) {
-    case eStyleUnit_Coord:
-      return aCoord.GetCoordValue();
-    case eStyleUnit_Percent:
-      return NSCoordSaturatingMultiply(aPercentageBasis,
-                                       aCoord.GetPercentValue());
-    default:
-      NS_ABORT_IF_FALSE(aCoord.IsCalcUnit(), "unexpected unit");
-      return nsRuleNode::ComputeComputedCalc(aCoord, aPercentageBasis);
-  }
-}
-
 #define SETCOORD_NORMAL                 0x01   // N
 #define SETCOORD_AUTO                   0x02   // A
 #define SETCOORD_INHERIT                0x04   // H
 #define SETCOORD_PERCENT                0x08   // P
 #define SETCOORD_FACTOR                 0x10   // F
 #define SETCOORD_LENGTH                 0x20   // L
 #define SETCOORD_INTEGER                0x40   // I
 #define SETCOORD_ENUMERATED             0x80   // E
@@ -5551,18 +5526,18 @@ nsRuleNode::ComputePositionData(void* aS
     if (SetCoord(posData.mOffset.*(nsCSSRect::sides[side]),
                  coord, parentCoord, SETCOORD_LPAH | SETCOORD_INITIAL_AUTO,
                  aContext, mPresContext, canStoreInRuleTree)) {
       pos->mOffset.Set(side, coord);
     }
   }
 
   SetCoord(posData.mWidth, pos->mWidth, parentPos->mWidth,
-           SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO, aContext,
-           mPresContext, canStoreInRuleTree);
+           SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC,
+           aContext, mPresContext, canStoreInRuleTree);
   SetCoord(posData.mMinWidth, pos->mMinWidth, parentPos->mMinWidth,
            SETCOORD_LPEH | SETCOORD_INITIAL_ZERO, aContext,
            mPresContext, canStoreInRuleTree);
   SetCoord(posData.mMaxWidth, pos->mMaxWidth, parentPos->mMaxWidth,
            SETCOORD_LPOEH | SETCOORD_INITIAL_NONE, aContext,
            mPresContext, canStoreInRuleTree);
 
   SetCoord(posData.mHeight, pos->mHeight, parentPos->mHeight,
--- a/layout/style/nsRuleNode.h
+++ b/layout/style/nsRuleNode.h
@@ -762,17 +762,21 @@ public:
   // (Values that don't require aPercentageBasis should be handled
   // inside nsRuleNode rather than through this API.)
   static nscoord ComputeComputedCalc(const nsStyleCoord& aCoord,
                                      nscoord aPercentageBasis);
 
   // Compute the value of an nsStyleCoord that is either a coord, a
   // percent, or a calc expression.
   static nscoord ComputeCoordPercentCalc(const nsStyleCoord& aCoord,
-                                         nscoord aPercentageBasis);
+                                         nscoord aPercentageBasis)
+  {
+    // ComputeComputedCalc will handle coords and percents correctly
+    return ComputeComputedCalc(aCoord, aPercentageBasis);
+  }
 
   // Return whether the rule tree for which this node is the root has
   // cached data such that we need to do dynamic change handling for
   // changes that change the results of media queries or require
   // rebuilding all style data.
   PRBool TreeHasCachedData() const {
     NS_ASSERTION(IsRoot(), "should only be called on root of rule tree");
     return HaveChildren() || mStyleData.mInheritedData || mStyleData.mResetData;
--- a/layout/style/nsStyleAnimation.h
+++ b/layout/style/nsStyleAnimation.h
@@ -123,17 +123,16 @@ public:
    * @param [out] aResultValue The resulting interpolated value.
    * @return PR_TRUE on success, PR_FALSE on failure.
    */
   static PRBool Interpolate(nsCSSProperty aProperty,
                             const Value& aStartValue,
                             const Value& aEndValue,
                             double aPortion,
                             Value& aResultValue) {
-    NS_ABORT_IF_FALSE(0.0 <= aPortion && aPortion <= 1.0, "out of range");
     return AddWeighted(aProperty, 1.0 - aPortion, aStartValue,
                        aPortion, aEndValue, aResultValue);
   }
 
   /**
    * Does the calculation:
    *   aResultValue = aCoeff1 * aValue1 + aCoeff2 * aValue2
    *
--- a/layout/style/nsStyleCoord.cpp
+++ b/layout/style/nsStyleCoord.cpp
@@ -206,16 +206,34 @@ nsStyleCoord::GetAngleValueInRadians() c
   case eStyleUnit_Grad:   return angle * M_PI / 200.0;
 
   default:
     NS_NOTREACHED("unrecognized angular unit");
     return 0.0;
   }
 }
 
+PRBool
+nsStyleCoord::CalcHasPercent() const
+{
+  NS_ABORT_IF_FALSE(IsCalcUnit(), "caller should check IsCalcUnit()");
+  nsStyleCoord::Array *a = GetArrayValue();
+  for (size_t i = 0, i_end = a->Count(); i < i_end; ++i) {
+    const nsStyleCoord &v = a->Item(i);
+    if (v.GetUnit() == eStyleUnit_Percent) {
+      return PR_TRUE;
+    }
+    if (v.IsCalcUnit() && v.CalcHasPercent()) {
+      return PR_TRUE;
+    }
+  }
+  return PR_FALSE;
+}
+
+
 inline void*
 nsStyleCoord::Array::operator new(size_t aSelfSize,
                                   nsStyleContext *aAllocationContext,
                                   size_t aItemCount) CPP_THROW_NEW
 {
   NS_ABORT_IF_FALSE(aItemCount > 0, "cannot have 0 item count");
   return aAllocationContext->Alloc(
            aSelfSize + sizeof(nsStyleCoord) * (aItemCount - 1));
--- a/layout/style/nsStyleCoord.h
+++ b/layout/style/nsStyleCoord.h
@@ -55,22 +55,22 @@ enum nsStyleUnit {
   eStyleUnit_Percent      = 10,     // (float) 1.0 == 100%
   eStyleUnit_Factor       = 11,     // (float) a multiplier
   eStyleUnit_Degree       = 12,     // (float) angle in degrees
   eStyleUnit_Grad         = 13,     // (float) angle in grads
   eStyleUnit_Radian       = 14,     // (float) angle in radians
   eStyleUnit_Coord        = 20,     // (nscoord) value is twips
   eStyleUnit_Integer      = 30,     // (int) value is simple integer
   eStyleUnit_Enumerated   = 32,     // (int) value has enumerated meaning
-  // The following are all of the eCSSUnit_Calc_* types (but not
-  // eCSSUnit_Calc itself, since we don't need to distinguish
-  // calc(min()) from min() in compute dstyle).  They are all weak
+  // The following are all of the eCSSUnit_Calc_* types.  They are weak
   // pointers to a calc tree allocated by nsStyleContext::Alloc.
   // NOTE:  They are in the same order as the eCSSUnit_Calc_* values so
   // that converting between the two sets is just addition/subtraction.
+  eStyleUnit_Calc         = 39,     // (Array*) calc() toplevel, to
+                                    // distinguish 50% from calc(50%), etc.
   eStyleUnit_Calc_Plus    = 40,     // (Array*) + node within calc()
   eStyleUnit_Calc_Minus   = 41,     // (Array*) - within calc
   eStyleUnit_Calc_Times_L = 42,     // (Array*) num * val within calc
   eStyleUnit_Calc_Times_R = 43,     // (Array*) val * num within calc
   eStyleUnit_Calc_Divided = 44,     // (Array*) / within calc
   eStyleUnit_Calc_Minimum = 45,     // (Array*) min() within calc
   eStyleUnit_Calc_Maximum = 46      // (Array*) max() within calc
 };
@@ -116,19 +116,29 @@ public:
     return mUnit;
   }
 
   PRBool IsAngleValue() const {
     return eStyleUnit_Degree <= mUnit && mUnit <= eStyleUnit_Radian;
   }
 
   PRBool IsCalcUnit() const {
-    return eStyleUnit_Calc_Plus <= mUnit && mUnit <= eStyleUnit_Calc_Maximum;
+    return eStyleUnit_Calc <= mUnit && mUnit <= eStyleUnit_Calc_Maximum;
   }
 
+  PRBool IsCoordPercentCalcUnit() const {
+    return mUnit == eStyleUnit_Coord ||
+           mUnit == eStyleUnit_Percent ||
+           IsCalcUnit();
+  }
+
+  // Does this calc() expression have any percentages inside it?  Can be
+  // called only when IsCalcUnit() is true.
+  PRBool CalcHasPercent() const;
+
   PRBool IsArrayValue() const {
     return IsCalcUnit();
   }
 
   nscoord     GetCoordValue() const;
   PRInt32     GetIntValue() const;
   float       GetPercentValue() const;
   float       GetFactorValue() const;
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1141,16 +1141,27 @@ nsChangeHint nsStylePosition::CalcDiffer
 #ifdef DEBUG
 /* static */
 nsChangeHint nsStylePosition::MaxDifference()
 {
   return NS_STYLE_HINT_REFLOW;
 }
 #endif
 
+/* static */ PRBool
+nsStylePosition::WidthCoordDependsOnContainer(const nsStyleCoord &aCoord)
+{
+  return aCoord.GetUnit() == eStyleUnit_Auto ||
+         aCoord.GetUnit() == eStyleUnit_Percent ||
+         (aCoord.IsCalcUnit() && aCoord.CalcHasPercent()) ||
+         (aCoord.GetUnit() == eStyleUnit_Enumerated &&
+          (aCoord.GetIntValue() == NS_STYLE_WIDTH_FIT_CONTENT ||
+           aCoord.GetIntValue() == NS_STYLE_WIDTH_AVAILABLE));
+}
+
 // --------------------
 // nsStyleTable
 //
 
 nsStyleTable::nsStyleTable() 
 { 
   MOZ_COUNT_CTOR(nsStyleTable);
   // values not inherited
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1047,24 +1047,45 @@ struct nsStylePosition {
 
   nsChangeHint CalcDifference(const nsStylePosition& aOther) const;
 #ifdef DEBUG
   static nsChangeHint MaxDifference();
 #endif
   static PRBool ForceCompare() { return PR_TRUE; }
 
   nsStyleSides  mOffset;                // [reset] coord, percent, auto
-  nsStyleCoord  mWidth;                 // [reset] coord, percent, auto, enum
+  nsStyleCoord  mWidth;                 // [reset] coord, percent, enum, auto
   nsStyleCoord  mMinWidth;              // [reset] coord, percent, enum
-  nsStyleCoord  mMaxWidth;              // [reset] coord, percent, null, enum
+  nsStyleCoord  mMaxWidth;              // [reset] coord, percent, enum, none
   nsStyleCoord  mHeight;                // [reset] coord, percent, auto
   nsStyleCoord  mMinHeight;             // [reset] coord, percent
-  nsStyleCoord  mMaxHeight;             // [reset] coord, percent, null
+  nsStyleCoord  mMaxHeight;             // [reset] coord, percent, none
   PRUint8       mBoxSizing;             // [reset] see nsStyleConsts.h
   nsStyleCoord  mZIndex;                // [reset] integer, auto
+
+  PRBool WidthDependsOnContainer() const
+    { return WidthCoordDependsOnContainer(mWidth); }
+  PRBool MinWidthDependsOnContainer() const
+    { return WidthCoordDependsOnContainer(mMinWidth); }
+  PRBool MaxWidthDependsOnContainer() const
+    { return WidthCoordDependsOnContainer(mMaxWidth); }
+  PRBool HeightDependsOnContainer() const
+    { return HeightCoordDependsOnContainer(mHeight); }
+  PRBool MinHeightDependsOnContainer() const
+    { return HeightCoordDependsOnContainer(mMinHeight); }
+  PRBool MaxHeightDependsOnContainer() const
+    { return HeightCoordDependsOnContainer(mMaxHeight); }
+
+private:
+  static PRBool WidthCoordDependsOnContainer(const nsStyleCoord &aCoord);
+  static PRBool HeightCoordDependsOnContainer(const nsStyleCoord &aCoord)
+  {
+    return aCoord.GetUnit() == eStyleUnit_Auto || // CSS 2.1, 10.6.4, item (5)
+           aCoord.GetUnit() == eStyleUnit_Percent;
+  }
 };
 
 struct nsStyleTextReset {
   nsStyleTextReset(void);
   nsStyleTextReset(const nsStyleTextReset& aOther);
   ~nsStyleTextReset(void);
 
   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
--- a/layout/style/test/Makefile.in
+++ b/layout/style/test/Makefile.in
@@ -170,16 +170,17 @@ GARBAGE += css_properties.js
 		test_system_font_serialization.html \
 		test_transitions_computed_values.html \
 		test_transitions_computed_value_combinations.html \
 		test_transitions_events.html \
 		test_transitions.html \
 		test_transitions_per_property.html \
 		test_transitions_dynamic_changes.html \
 		test_transitions_bug537151.html \
+		test_unclosed_parentheses.html \
 		test_units_angle.html \
 		test_units_frequency.html \
 		test_units_length.html \
 		test_units_time.html \
 		test_value_cloning.html \
 		test_value_computation.html \
 		test_value_storage.html \
 		test_visited_image_loading.html \
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -1026,17 +1026,20 @@ var gCSSProperties = {
 		"-moz-repeating-radial-gradient(99deg, cover, red, blue)",
 		"-moz-repeating-radial-gradient(-1.2345rad, circle, red, blue)",
 		"-moz-repeating-radial-gradient(399grad, ellipse closest-corner, red, blue)",
 		"-moz-repeating-radial-gradient(399grad, farthest-side circle, red, blue)",
 
 		"-moz-repeating-radial-gradient(top left 99deg, cover, red, blue)",
 		"-moz-repeating-radial-gradient(15% 20% -1.2345rad, circle, red, blue)",
 		"-moz-repeating-radial-gradient(45px 399grad, ellipse closest-corner, red, blue)",
-		"-moz-repeating-radial-gradient(45px 399grad, farthest-side circle, red, blue)"
+		"-moz-repeating-radial-gradient(45px 399grad, farthest-side circle, red, blue)",
+		"-moz-image-rect(url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), 2, 10, 10, 2)",
+		"-moz-image-rect(url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), 10%, 50%, 30%, 0%)",
+		"-moz-image-rect(url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), 10, 50%, 30%, 0)",
 		],
 		invalid_values: [
 			/* Old syntax */
 			"-moz-linear-gradient(10px 10px, 20px, 30px 30px, 40px, from(blue), to(red))",
 			"-moz-radial-gradient(20px 20px, 10px 10px, from(green), to(#ff00ff))",
 			"-moz-radial-gradient(10px 10px, 20%, 40px 40px, 10px, from(green), to(#ff00ff))",
 			"-moz-linear-gradient(10px, 20px, 30px, 40px, color-stop(0.5, #00ccff))",
 			"-moz-linear-gradient(20px 20px, from(blue), to(red))",
@@ -2133,18 +2136,18 @@ var gCSSProperties = {
 		initial_values: [ "0" ],
 		other_values: [ "2em", "5%", "-10px" ],
 		invalid_values: []
 	},
 	"text-shadow": {
 		domProp: "textShadow",
 		inherited: true,
 		type: CSS_TYPE_LONGHAND,
+		prerequisites: { "color": "blue" },
 		initial_values: [ "none" ],
-		prerequisites: { "color": "blue" },
 		other_values: [ "2px 2px", "2px 2px 1px", "2px 2px green", "2px 2px 1px green", "green 2px 2px", "green 2px 2px 1px", "green 2px 2px, blue 1px 3px 4px", "currentColor 3px 3px", "blue 2px 2px, currentColor 1px 2px",
 			/* calc() values */
 			"2px 2px -moz-calc(-5px)", /* clamped */
 			"-moz-calc(3em - 2px) 2px green",
 			"green -moz-calc(3em - 2px) 2px",
 			"2px -moz-min(2px,0.2em)",
 			"blue 2px -moz-min(2px,0.2em)",
 			"2px -moz-min(2px,0.2em) blue",
@@ -2206,18 +2209,18 @@ var gCSSProperties = {
 		other_values: [ "none", "left", "top", "color", "width, height, opacity", "foobar", "auto", "\\32width", "-width", "-\\32width", "\\32 0width", "-\\32 0width", "\\2width", "-\\2width" ],
 		invalid_values: [ "none, none", "all, all", "color, none", "none, color", "all, color", "color, all", "inherit, color", "color, inherit", "initial, color", "color, initial", "none, color", "color, none", "all, color", "color, all" ]
 	},
 	"-moz-transition-timing-function": {
 		domProp: "MozTransitionTimingFunction",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "ease", "cubic-bezier(0.25, 0.1, 0.25, 1.0)" ],
-		other_values: [ "linear", "ease-in", "ease-out", "ease-in-out", "linear, ease-in, cubic-bezier(0.1, 0.2, 0.8, 0.9)" ],
-		invalid_values: [ "none", "auto" ]
+		other_values: [ "linear", "ease-in", "ease-out", "ease-in-out", "linear, ease-in, cubic-bezier(0.1, 0.2, 0.8, 0.9)", "cubic-bezier(0.5, 0.5, 0.5, 0.5)", "cubic-bezier(0.25, 1.5, 0.75, -0.5)" ],
+		invalid_values: [ "none", "auto", "cubic-bezier(0.25, 0.1, 0.25)", "cubic-bezier(0.25, 0.1, 0.25, 0.25, 1.0)", "cubic-bezier(-0.5, 0.5, 0.5, 0.5)", "cubic-bezier(1.5, 0.5, 0.5, 0.5)", "cubic-bezier(0.5, 0.5, -0.5, 0.5)", "cubic-bezier(0.5, 0.5, 1.5, 0.5)" ]
 	},
 	"unicode-bidi": {
 		domProp: "unicodeBidi",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "normal" ],
 		other_values: [ "embed", "bidi-override" ],
 		invalid_values: [ "auto", "none" ]
@@ -2273,20 +2276,77 @@ var gCSSProperties = {
 		initial_values: [ "2" ],
 		other_values: [ "1", "7" ],
 		invalid_values: [ "0", "-1", "0px", "3px" ]
 	},
 	"width": {
 		domProp: "width",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
+		/* computed value tests for width test more with display:block */
+		prerequisites: { "display": "block" },
 		initial_values: [ " auto" ],
 		/* XXX these have prerequisites */
-		other_values: [ "15px", "3em", "15%", "-moz-max-content", "-moz-min-content", "-moz-fit-content", "-moz-available" ],
-		invalid_values: [ "none", "-2px" ]
+		other_values: [ "15px", "3em", "15%", "-moz-max-content", "-moz-min-content", "-moz-fit-content", "-moz-available",
+			/* valid calc() values */
+			"-moz-calc(-2px)",
+			"-moz-calc(2px)",
+			"-moz-calc(50%)",
+			"-moz-calc(50% + 2px)",
+			"-moz-calc( 50% + 2px)",
+			"-moz-calc(50% + 2px )",
+			"-moz-calc( 50% + 2px )",
+			"-moz-calc(50% - -2px)",
+			"-moz-calc(2px - -50%)",
+			"-moz-calc(3*25px)",
+			"-moz-calc(3 *25px)",
+			"-moz-calc(3 * 25px)",
+			"-moz-calc(3* 25px)",
+			"-moz-calc(25px*3)",
+			"-moz-calc(25px *3)",
+			"-moz-calc(25px* 3)",
+			"-moz-calc(25px * 3)",
+			"-moz-calc(3*25px + 50%)",
+			"-moz-calc(50% - 3em + 2px)",
+			"-moz-calc(50% - (3em + 2px))",
+			"-moz-calc((50% - 3em) + 2px)",
+			"-moz-min(50%, 30em)",
+			"-moz-calc(min(50%, 30em))",
+			"-moz-max(30em, 2px + 50%)",
+			"-moz-calc(max(30em, 2px + 50%))",
+			"-moz-min(30%, 30em,200px, min(500px ,40em))",
+			"-moz-calc(min(30%, 30em,200px, min(500px ,40em)))",
+			"-moz-min(50%)",
+			"-moz-max(20px)",
+			"-moz-calc(min(2em))",
+			"-moz-calc(max(50%))",
+			"-moz-calc(50px/2)",
+			"-moz-calc(50px/(2 - 1))"
+		],
+		invalid_values: [ "none", "-2px",
+			/* invalid calc() values */
+			"-moz-calc(50%+ 2px)",
+			"-moz-calc(50% +2px)",
+			"-moz-calc(50%+2px)",
+			"-moz-min()",
+			"-moz-calc(min())",
+			"-moz-max()",
+			"-moz-calc(max())",
+			"-moz-calc(50px/(2 - 2))",
+			/* If we ever support division by values, which is
+			 * complicated for the reasons described in
+			 * http://lists.w3.org/Archives/Public/www-style/2010Jan/0007.html
+			 * , we should support all 4 of these as described in
+			 * http://lists.w3.org/Archives/Public/www-style/2009Dec/0296.html
+			 */
+			"-moz-calc((3em / 100%) * 3em)",
+			"-moz-calc(3em / 100% * 3em)",
+			"-moz-calc(3em * (3em / 100%))",
+			"-moz-calc(3em * 3em / 100%)"
+		]
 	},
 	"word-spacing": {
 		domProp: "wordSpacing",
 		inherited: true,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "normal", "0", "0px", "-0em",
 			"-moz-calc(-0px)", "-moz-calc(0em)"
 		],
--- a/layout/style/test/test_initial_computation.html
+++ b/layout/style/test/test_initial_computation.html
@@ -3,16 +3,20 @@
 <!--
 -->
 <head>
   <title>Test for computation of CSS '-moz-initial'</title>
   <script type="text/javascript" src="/MochiKit/packed.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="property_database.js"></script>
   <style type="text/css" id="stylesheet"></style>
+  <style type="text/css">
+  /* For 'width', 'height', etc., need a constant size container. */
+  #display { width: 500px; height: 200px }
+  </style>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <script type="text/javascript">
   SimpleTest.waitForExplicitFinish();
 
   var load_count = 0;
   function load_done() {
     if (++load_count == 3)
       run_tests();
@@ -53,16 +57,19 @@ var gInitialValuesF;
 var gInitialPrereqsRuleN;
 var gInitialPrereqsRuleF;
 
 function setup_initial_values(id, ivalprop, prereqprop) {
   var iframe = document.getElementById(id);
   window[ivalprop] = iframe.contentWindow.getComputedStyle(
                        iframe.contentDocument.documentElement.firstChild, "");
   var sheet = iframe.contentDocument.styleSheets[0];
+  // For 'width', 'height', etc., need a constant size container.
+  sheet.insertRule(":root { height: 200px; width: 500px }", sheet.cssRules.length);
+
   window[prereqprop] = sheet.cssRules[sheet.insertRule(":root > * {}", sheet.cssRules.length)];
 }
 
 function test_property(property)
 {
   var info = gCSSProperties[property];
   if (info.backend_only)
     return;
new file mode 100644
--- /dev/null
+++ b/layout/style/test/test_unclosed_parentheses.html
@@ -0,0 +1,158 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=575672
+-->
+<head>
+  <title>Test for Bug 575672</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <style type="text/css" id="style"></style>
+  <style type="text/css">
+    #display { position: relative }
+  </style>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=575672">Mozilla Bug 575672</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for unclosed parentheses in CSS values. **/
+
+// Each of the following declarations should have a single missing ')'
+// in the value.
+var declarations = [
+  "content: url(",
+  "content: url( ",
+  "content: url(http://www.foo.com",
+  "content: url('http://www.foo.com'",
+  "background-image: -moz-linear-gradient(",
+  "background-image: -moz-linear-gradient( ",
+  "background-image: -moz-linear-gradient(red, blue",
+  "background-image: -moz-linear-gradient(red, yellow, blue",
+  "background-image: -moz-linear-gradient(red 1px, yellow 5px, blue 10px",
+  "background-image: -moz-linear-gradient(red, yellow, rgb(0, 0, 255)",
+  "background-image: -moz-repeating-linear-gradient(top left, red, blue",
+  "background-image: -moz-linear-gradient(top left, red, yellow, blue",
+  "background-image: -moz-linear-gradient(top left, red 1px, yellow 5px, blue 10px",
+  "background-image: -moz-linear-gradient(top left, red, yellow, rgb(0, 0, 255)",
+  "background-image: -moz-radial-gradient(",
+  "background-image: -moz-radial-gradient( ",
+  "background-image: -moz-radial-gradient(top left 45deg, red, blue",
+  "background-image: -moz-radial-gradient(cover, red, blue",
+  "background-image: -moz-repeating-radial-gradient(circle, red, blue",
+  "background-image: -moz-radial-gradient(ellipse closest-corner, red, hsl(240, 50%, 50%)",
+  "background-image: -moz-radial-gradient(farthest-side circle, red, blue",
+  "background-image: -moz-image-rect(",
+  "background-image: -moz-image-rect( ",
+  "background-image: -moz-image-rect(url(foo.jpg)",
+  "background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10",
+  "background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10 ",
+  "background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10,",
+  "background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10, ",
+  "background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10, 10",
+  "background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10, 10 ",
+  "background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10, 10,",
+  "background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10, 10, ",
+  "color: rgb(",
+  "color: rgb( ",
+  "color: rgb(128, 0",
+  "color: rgb(128, 0, 128",
+  "color: rgb(128, 0, 128, 128",
+  "color: rgba(",
+  "color: rgba( ",
+  "color: rgba(128, 0",
+  "color: rgba(128, 0, 128",
+  "color: rgba(128, 0, 128, 1",
+  "color: rgba(128, 0, 128, 1, 1",
+  "color: hsl(",
+  "color: hsl( ",
+  "color: hsl(240, 50%",
+  "color: hsl(240, 50%, 50%",
+  "color: hsl(240, 50%, 50%, 50%",
+  "color: hsla(",
+  "color: hsla( ",
+  "color: hsla(240, 50%",
+  "color: hsla(240, 50%, 50%",
+  "color: hsla(240, 50%, 50%, 1",
+  "color: hsla(240, 50%, 50%, 1, 1",
+  "content: counter(",
+  "content: counter( ",
+  "content: counter(foo",
+  "content: counter(foo ",
+  "content: counter(foo,",
+  "content: counter(foo, ",
+  "content: counter(foo, upper-roman",
+  "content: counter(foo, upper-roman ",
+  "content: counter(foo, upper-roman,",
+  "content: counter(foo, upper-roman, ",
+  "content: counters(",
+  "content: counters( ",
+  "content: counters(foo, ','",
+  "content: counters(foo, ',' ",
+  "content: counters(foo, ',',",
+  "content: counters(foo, ',', ",
+  "content: counters(foo, ',', upper-roman",
+  "content: counters(foo, ',', upper-roman ",
+  "content: counters(foo, ',', upper-roman,",
+  "content: counters(foo, ',', upper-roman, ",
+  "content: attr(",
+  "content: attr( ",
+  "content: attr(href",
+  "content: attr(href ",
+  "content: attr(html",
+  "content: attr(html ",
+  "content: attr(html|",
+  "content: attr(html| ",
+  "content: attr(html|href",
+  "content: attr(html|href ",
+  "content: attr(|",
+  "content: attr(| ",
+  "content: attr(|href",
+  "content: attr(|href ",
+  "-moz-transition-timing-function: cubic-bezier(",
+  "-moz-transition-timing-function: cubic-bezier( ",
+  "-moz-transition-timing-function: cubic-bezier(0, 0, 1",
+  "-moz-transition-timing-function: cubic-bezier(0, 0, 1 ",
+  "-moz-transition-timing-function: cubic-bezier(0, 0, 1,",
+  "-moz-transition-timing-function: cubic-bezier(0, 0, 1, ",
+  "-moz-transition-timing-function: cubic-bezier(0, 0, 1, 1",
+  "-moz-transition-timing-function: cubic-bezier(0, 0, 1, 1 ",
+  "-moz-transition-timing-function: cubic-bezier(0, 0, 1, 1,",
+  "-moz-transition-timing-function: cubic-bezier(0, 0, 1, 1, ",
+  "border-top-width: -moz-calc(",
+  "border-top-width: -moz-calc( ",
+  "border-top-width: -moz-calc(2em",
+  "border-top-width: -moz-calc(2em ",
+  "border-top-width: -moz-calc(2em +",
+  "border-top-width: -moz-calc(2em + ",
+  "border-top-width: -moz-calc(2em *",
+  "border-top-width: -moz-calc(2em * ",
+  "border-top-width: -moz-calc((2em)",
+  "border-top-width: -moz-calc((2em) ",
+];
+
+var textNode = document.createTextNode("");
+document.getElementById("style").appendChild(textNode);
+var cs = getComputedStyle(document.getElementById("display"), "");
+
+for (var i = 0; i < declarations.length; ++i) {
+  var sheet = "@namespace html url(http://www.w3.org/1999/xhtml);\n" +
+              "#display { color: green; " + declarations[i] +
+              " x x x x x x x ; color: red; ) ; z-index: " + (i + 1) + " }";
+  textNode.data = sheet;
+  is(cs.color, "rgb(0, 128, 0)",
+     "color for declaration '" + declarations[i] + "'");
+  is(cs.zIndex, i+1,
+     "z-index for declaration '" + declarations[i] + "'");
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/layout/style/test/test_value_computation.html
+++ b/layout/style/test/test_value_computation.html
@@ -3,16 +3,20 @@
 <!--
 -->
 <head>
   <title>Test for computation of values in property database</title>
   <script type="text/javascript" src="/MochiKit/packed.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="property_database.js"></script>
   <style type="text/css" id="stylesheet"></style>
+  <style type="text/css">
+  /* For 'width', 'height', etc., need a constant size container. */
+  #display { width: 500px; height: 200px }
+  </style>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <script type="text/javascript">
   SimpleTest.waitForExplicitFinish();
 
   var load_count = 0;
   function load_done() {
     if (++load_count == 3)
       run_tests();
@@ -74,32 +78,46 @@ function xfail_value(property, value, is
 
   if (!has_frame && (property in gBadComputedNoFrame) &&
       gBadComputedNoFrame[property].indexOf(value) != -1)
     return true;
 
   return false;
 }
 
+var gSwapInitialWhenHaveFrame = {
+  // When there's a frame, '-moz-available' works out to the same as
+  // 'auto' given the prerequisites of only 'display: block'.
+  "width": [ "-moz-available" ],
+};
+
+function swap_when_frame(property, value) {
+  return (property in gSwapInitialWhenHaveFrame) &&
+         gSwapInitialWhenHaveFrame[property].indexOf(value) != -1;
+}
+
 var gElementN = document.getElementById("elementn");
 var gElementF = document.getElementById("elementf");
 var gStyleSheet = document.getElementById("stylesheet").sheet;
 var gRule1 = gStyleSheet.cssRules[gStyleSheet.insertRule("#elementn, #elementf {}", gStyleSheet.cssRules.length)];
 var gRule2 = gStyleSheet.cssRules[gStyleSheet.insertRule("#elementn, #elementf {}", gStyleSheet.cssRules.length)];
 
 var gInitialValuesN;
 var gInitialValuesF;
 var gInitialPrereqsRuleN;
 var gInitialPrereqsRuleF;
 
 function setup_initial_values(id, ivalprop, prereqprop) {
   var iframe = document.getElementById(id);
   window[ivalprop] = iframe.contentWindow.getComputedStyle(
                        iframe.contentDocument.documentElement.firstChild, "");
   var sheet = iframe.contentDocument.styleSheets[0];
+  // For 'width', 'height', etc., need a constant size container.
+  sheet.insertRule(":root { height: 200px; width: 500px }", sheet.cssRules.length);
+
   window[prereqprop] = sheet.cssRules[sheet.insertRule(":root > * {}", sheet.cssRules.length)];
 }
 
 function test_value(property, val, is_initial)
 {
   var info = gCSSProperties[property];
   if (info.backend_only)
     return;
@@ -152,19 +170,21 @@ function test_value(property, val, is_in
        "should get initial value for '" + property + ":" + val + "'");
     (xfail_value(property, val, is_initial, true) ? todo_is : is)(
        val_computed_f, initial_computed_f,
        "should get initial value for '" + property + ":" + val + "'");
   } else {
     (xfail_value(property, val, is_initial, false) ? todo_isnot : isnot)(
        val_computed_n, initial_computed_n,
        "should not get initial value for '" + property + ":" + val + "' on elementn.");
-    (xfail_value(property, val, is_initial, true) ? todo_isnot : isnot)(
+    var swap = swap_when_frame(property, val);
+    (xfail_value(property, val, is_initial, true) ? todo_isnot : (swap ? is : isnot))(
        val_computed_f, initial_computed_f,
-       "should not get initial value for '" + property + ":" + val + "' on elementf.");
+       "should " + (swap ? "" : "not ") +
+       "get initial value for '" + property + ":" + val + "' on elementf.");
   }
   if (is_initial)
     gRule1.style.removeProperty(property);
   gRule2.style.removeProperty(property);
 
   if ("prerequisites" in info) {
     var prereqs = info.prerequisites;
     for (var prereq in prereqs) {
--- a/layout/svg/base/src/nsSVGOuterSVGFrame.cpp
+++ b/layout/svg/base/src/nsSVGOuterSVGFrame.cpp
@@ -465,23 +465,26 @@ nsDisplaySVG::Paint(nsDisplayListBuilder
     Paint(*aCtx, mVisibleRect, aBuilder->ToReferenceFrame(mFrame));
 }
 
 // helper
 static inline PRBool
 DependsOnIntrinsicSize(const nsIFrame* aEmbeddingFrame)
 {
   const nsStylePosition *pos = aEmbeddingFrame->GetStylePosition();
-  nsStyleUnit widthUnit  = pos->mWidth.GetUnit();
-  nsStyleUnit heightUnit = pos->mHeight.GetUnit();
+  const nsStyleCoord &width = pos->mWidth;
+  const nsStyleCoord &height = pos->mHeight;
 
   // XXX it would be nice to know if the size of aEmbeddingFrame's containing
   // block depends on aEmbeddingFrame, then we'd know if we can return false
   // for eStyleUnit_Percent too.
-  return (widthUnit != eStyleUnit_Coord) || (heightUnit != eStyleUnit_Coord);
+  return (width.GetUnit() != eStyleUnit_Coord &&
+          (!width.IsCalcUnit() || width.CalcHasPercent())) ||
+         (height.GetUnit() != eStyleUnit_Coord &&
+          (!height.IsCalcUnit() || height.CalcHasPercent()));
 }
 
 NS_IMETHODIMP
 nsSVGOuterSVGFrame::AttributeChanged(PRInt32  aNameSpaceID,
                                      nsIAtom* aAttribute,
                                      PRInt32  aModType)
 {
   if (aNameSpaceID == kNameSpaceID_None &&
--- a/layout/tables/BasicTableLayoutStrategy.cpp
+++ b/layout/tables/BasicTableLayoutStrategy.cpp
@@ -43,16 +43,18 @@
 
 #include "BasicTableLayoutStrategy.h"
 #include "nsTableFrame.h"
 #include "nsTableCellFrame.h"
 #include "nsLayoutUtils.h"
 #include "nsGkAtoms.h"
 #include "SpanningCellSorter.h"
 
+namespace css = mozilla::css;
+
 #undef  DEBUG_TABLE_STRATEGY 
 
 BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aTableFrame)
   : nsITableLayoutStrategy(nsITableLayoutStrategy::Auto)
   , mTableFrame(aTableFrame)
 {
     MarkIntrinsicWidthsDirty();
 }
@@ -115,38 +117,42 @@ GetWidthInfo(nsIRenderingContext *aRende
         prefCoord = 0;
     }
     float prefPercent = 0.0f;
     PRBool hasSpecifiedWidth = PR_FALSE;
 
     // XXXldb Should we consider -moz-box-sizing?
 
     const nsStylePosition *stylePos = aFrame->GetStylePosition();
-    nsStyleUnit unit = stylePos->mWidth.GetUnit();
+    const nsStyleCoord &width = stylePos->mWidth;
+    nsStyleUnit unit = width.GetUnit();
+    // NOTE: We're ignoring calc() units here, for lack of a sensible
+    // idea for what to do with them.  This means calc() is basically
+    // handled like 'auto' for table cells and columns.
     if (unit == eStyleUnit_Coord) {
         hasSpecifiedWidth = PR_TRUE;
         nscoord w = nsLayoutUtils::ComputeWidthValue(aRenderingContext,
-                      aFrame, 0, 0, 0, stylePos->mWidth);
+                                                     aFrame, 0, 0, 0, width);
         // Quirk: A cell with "nowrap" set and a coord value for the
         // width which is bigger than the intrinsic minimum width uses
         // that coord value as the minimum width.
         // This is kept up-to-date with dynamic changes to nowrap by code in
         // nsTableCellFrame::AttributeChanged
         if (aIsCell && w > minCoord &&
             aFrame->PresContext()->CompatibilityMode() ==
               eCompatibility_NavQuirks &&
             aFrame->GetContent()->HasAttr(kNameSpaceID_None,
                                           nsGkAtoms::nowrap)) {
             minCoord = w;
         }
         prefCoord = NS_MAX(w, minCoord);
     } else if (unit == eStyleUnit_Percent) {
-        prefPercent = stylePos->mWidth.GetPercentValue();
+        prefPercent = width.GetPercentValue();
     } else if (unit == eStyleUnit_Enumerated && aIsCell) {
-        switch (stylePos->mWidth.GetIntValue()) {
+        switch (width.GetIntValue()) {
             case NS_STYLE_WIDTH_MAX_CONTENT:
                 // 'width' only affects pref width, not min
                 // width, so don't change anything
                 break;
             case NS_STYLE_WIDTH_MIN_CONTENT:
                 prefCoord = minCoord;
                 break;
             case NS_STYLE_WIDTH_FIT_CONTENT:
--- a/layout/tables/FixedTableLayoutStrategy.cpp
+++ b/layout/tables/FixedTableLayoutStrategy.cpp
@@ -100,17 +100,18 @@ FixedTableLayoutStrategy::GetMinWidth(ns
             &colFrame->GetStylePosition()->mWidth;
         if (styleWidth->GetUnit() == eStyleUnit_Coord) {
             result += nsLayoutUtils::ComputeWidthValue(aRenderingContext,
                         colFrame, 0, 0, 0, *styleWidth);
         } else if (styleWidth->GetUnit() == eStyleUnit_Percent) {
             // do nothing
         } else {
             NS_ASSERTION(styleWidth->GetUnit() == eStyleUnit_Auto ||
-                         styleWidth->GetUnit() == eStyleUnit_Enumerated,
+                         styleWidth->GetUnit() == eStyleUnit_Enumerated ||
+                         styleWidth->IsCalcUnit(),
                          "bad width");
 
             // The 'table-layout: fixed' algorithm considers only cells
             // in the first row.
             PRBool originates;
             PRInt32 colSpan;
             nsTableCellFrame *cellFrame =
                 cellMap->GetCellInfoAt(0, col, &originates, &colSpan);
@@ -132,18 +133,18 @@ FixedTableLayoutStrategy::GetMinWidth(ns
                     result += cellWidth;
                 } else if (styleWidth->GetUnit() == eStyleUnit_Percent) {
                     if (colSpan > 1) {
                         // XXX Can this force columns to negative
                         // widths?
                         result -= spacing * (colSpan - 1);
                     }
                 }
-                // else, for 'auto', '-moz-available', and '-moz-fit-content'
-                // do nothing
+                // else, for 'auto', '-moz-available', '-moz-fit-content',
+                // and 'calc()', do nothing
             }
         }
     }
 
     return (mMinWidth = result);
 }
 
 /* virtual */ nscoord
@@ -246,17 +247,18 @@ FixedTableLayoutStrategy::ComputeColumnW
             specTotal += colWidth;
         } else if (styleWidth->GetUnit() == eStyleUnit_Percent) {
             float pct = styleWidth->GetPercentValue();
             colWidth = NSToCoordFloor(pct * float(tableWidth));
             colFrame->AddPrefPercent(pct);
             pctTotal += pct;
         } else {
             NS_ASSERTION(styleWidth->GetUnit() == eStyleUnit_Auto ||
-                         styleWidth->GetUnit() == eStyleUnit_Enumerated,
+                         styleWidth->GetUnit() == eStyleUnit_Enumerated ||
+                         styleWidth->IsCalcUnit(),
                          "bad width");
 
             // The 'table-layout: fixed' algorithm considers only cells
             // in the first row.
             PRBool originates;
             PRInt32 colSpan;
             nsTableCellFrame *cellFrame =
                 cellMap->GetCellInfoAt(0, col, &originates, &colSpan);
@@ -281,17 +283,18 @@ FixedTableLayoutStrategy::ComputeColumnW
                         cellFrame->IntrinsicWidthOffsets(aReflowState.rendContext);
                     float pct = styleWidth->GetPercentValue();
                     colWidth = NSToCoordFloor(pct * float(tableWidth)) +
                                offsets.hPadding + offsets.hBorder;
                     pct /= float(colSpan);
                     colFrame->AddPrefPercent(pct);
                     pctTotal += pct;
                 } else {
-                    // 'auto', '-moz-available', and '-moz-fit-content'
+                    // 'auto', '-moz-available', '-moz-fit-content', and
+                    // 'calc()'
                     colWidth = unassignedMarker;
                 }
                 if (colWidth != unassignedMarker) {
                     if (colSpan > 1) {
                         // If a column-spanning cell is in the first
                         // row, split up the space evenly.  (XXX This
                         // isn't quite right if some of the columns it's
                         // in have specified widths.  Should we care?)
--- a/layout/xul/base/src/nsBox.cpp
+++ b/layout/xul/base/src/nsBox.cpp
@@ -674,19 +674,26 @@ nsIBox::AddCSSPrefSize(nsIBox* aBox, nsS
     // add in the css min, max, pref
     const nsStylePosition* position = aBox->GetStylePosition();
 
     // see if the width or height was specifically set
     // XXX Handle eStyleUnit_Enumerated?
     // (Handling the eStyleUnit_Enumerated types requires
     // GetPrefSize/GetMinSize methods that don't consider
     // (min-/max-/)(width/height) properties.)
-    if (position->mWidth.GetUnit() == eStyleUnit_Coord) {
-        aSize.width = position->mWidth.GetCoordValue();
+    const nsStyleCoord &width = position->mWidth;
+    if (width.GetUnit() == eStyleUnit_Coord) {
+        aSize.width = width.GetCoordValue();
         aWidthSet = PR_TRUE;
+    } else if (width.IsCalcUnit()) {
+        if (!width.CalcHasPercent()) {
+            // pass 0 for percentage basis since we know there are no %s
+            aSize.width = nsRuleNode::ComputeComputedCalc(width, 0);
+            aWidthSet = PR_TRUE;
+        }
     }
 
     if (position->mHeight.GetUnit() == eStyleUnit_Coord) {
         aSize.height = position->mHeight.GetCoordValue();     
         aHeightSet = PR_TRUE;
     }
     
     nsIContent* content = aBox->GetContent();
--- a/modules/libpr0n/test/reftest/jpeg/reftest.list
+++ b/modules/libpr0n/test/reftest/jpeg/reftest.list
@@ -1,33 +1,33 @@
 # JPEG tests 
 
 # Images of various sizes.
 == jpg-size-1x1.jpg   jpg-size-1x1.png
-fails-if(winWidget) == jpg-size-2x2.jpg   jpg-size-2x2.png
+fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-2x2.jpg   jpg-size-2x2.png
 == jpg-size-3x3.jpg   jpg-size-3x3.png
 == jpg-size-4x4.jpg   jpg-size-4x4.png
-fails-if(winWidget) == jpg-size-5x5.jpg   jpg-size-5x5.png
+fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-5x5.jpg   jpg-size-5x5.png
 == jpg-size-6x6.jpg   jpg-size-6x6.png
-fails-if(winWidget) == jpg-size-7x7.jpg   jpg-size-7x7.png
+fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-7x7.jpg   jpg-size-7x7.png
 == jpg-size-8x8.jpg   jpg-size-8x8.png
-fails-if(winWidget) == jpg-size-9x9.jpg   jpg-size-9x9.png
-fails-if(winWidget) == jpg-size-15x15.jpg jpg-size-15x15.png
-fails-if(winWidget) == jpg-size-16x16.jpg jpg-size-16x16.png
-fails-if(winWidget) == jpg-size-17x17.jpg jpg-size-17x17.png
-fails-if(winWidget) == jpg-size-31x31.jpg jpg-size-31x31.png
-fails-if(winWidget) == jpg-size-32x32.jpg jpg-size-32x32.png
-fails-if(winWidget) == jpg-size-33x33.jpg jpg-size-33x33.png
+fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-9x9.jpg   jpg-size-9x9.png
+fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-15x15.jpg jpg-size-15x15.png
+fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-16x16.jpg jpg-size-16x16.png
+fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-17x17.jpg jpg-size-17x17.png
+fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-31x31.jpg jpg-size-31x31.png
+fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-32x32.jpg jpg-size-32x32.png
+fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-33x33.jpg jpg-size-33x33.png
 # Progressive encoding
-fails-if(winWidget) == jpg-progressive.jpg jpg-progressive.png
+fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-progressive.jpg jpg-progressive.png
 # Grayscale colorspace
-fails-if(winWidget) == jpg-gray.jpg jpg-gray.png
+fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-gray.jpg jpg-gray.png
 # CMYK colorspace
-fails-if(winWidget) == jpg-cmyk-1.jpg jpg-cmyk-1.png
-fails-if(winWidget) == jpg-cmyk-2.jpg jpg-cmyk-2.png
+fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-cmyk-1.jpg jpg-cmyk-1.png
+fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-cmyk-2.jpg jpg-cmyk-2.png
 == jpg-srgb-icc.jpg jpg-srgb-icc.png
 
 # webcam-simulacrum.mjpg is a hand-edited file containing red.jpg and blue.jpg,
 # concatenated together with the relevant headers for
 # multipart/x-mixed-replace. Specifically, with the headers in
 # webcam-simulacrum.mjpg^headers^, the web browser will get the following:
 #
 # HTTP 200 OK
--- a/testing/mochitest/browser-test.js
+++ b/testing/mochitest/browser-test.js
@@ -78,20 +78,16 @@ Tester.prototype = {
                                               : "Found an unexpected {elt}";
 
     if (this.currentTest && window.gBrowser && gBrowser.tabs.length > 1) {
       while (gBrowser.tabs.length > 1) {
         let lastTab = gBrowser.tabContainer.lastChild;
         let msg = baseMsg.replace("{elt}", "tab") +
                   ": " + lastTab.linkedBrowser.currentURI.spec;
         this.currentTest.addResult(new testResult(false, msg, "", false));
-        if (gBrowser._removingTabs && gBrowser._removingTabs.indexOf(lastTab) > -1) {
-          gBrowser._endRemoveTab(lastTab);
-          continue;
-        }
         gBrowser.removeTab(lastTab);
       }
     }
 
     this.dumper.dump("TEST-INFO | checking window state\n");
     let windowsEnum = this._wm.getEnumerator("navigator:browser");
     while (windowsEnum.hasMoreElements()) {
       let win = windowsEnum.getNext();
--- a/toolkit/content/Geometry.jsm
+++ b/toolkit/content/Geometry.jsm
@@ -9,42 +9,42 @@
  *
  * Software distributed under the License is distributed on an "AS IS" basis,
  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  * for the specific language governing rights and limitations under the
  * License.
  *
  * The Original Code is Mozilla Mobile Browser.
  *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation.
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Roy Frostig <rfrostig@mozilla.com>
  *   Ben Combee <bcombee@mozilla.com>
  *   Matt Brubeck <mbrubeck@mozilla.com>
+ *   Benjamin Stover <bstover@mozilla.com>
  *   Michael Yoshitaka Erlewine <mitcho@mitcho.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-var EXPORTED_SYMBOLS = ["Point","Rect"];
+let EXPORTED_SYMBOLS = ["Point", "Rect"];
 
 /**
  * Simple Point class.
  *
  * Any method that takes an x and y may also take a point.
  */
 function Point(x, y) {
   this.set(x, y);
@@ -55,17 +55,17 @@ Point.prototype = {
     return new Point(this.x, this.y);
   },
 
   set: function set(x, y) {
     this.x = x;
     this.y = y;
     return this;
   },
-  
+
   equals: function equals(x, y) {
     return this.x == x && this.y == y;
   },
 
   toString: function toString() {
     return "(" + this.x + "," + this.y + ")";
   },
 
--- a/toolkit/content/Makefile.in
+++ b/toolkit/content/Makefile.in
@@ -78,19 +78,19 @@ ifdef MOZ_TOOLKIT_SEARCH
 DEFINES += -DMOZ_TOOLKIT_SEARCH
 endif
 
 ifdef ENABLE_TESTS
 DIRS += tests
 endif
 
 EXTRA_JS_MODULES = \
+  Geometry.jsm \
   InlineSpellChecker.jsm \
   PopupNotifications.jsm \
-  Geometry.jsm \
   $(NULL)
 
 EXTRA_PP_JS_MODULES = \
   debug.js \
   LightweightThemeConsumer.jsm \
   Services.jsm \
   WindowDraggingUtils.jsm \
   $(NULL)
--- a/toolkit/content/tests/browser/Makefile.in
+++ b/toolkit/content/tests/browser/Makefile.in
@@ -48,15 +48,15 @@ DIRS = \
   data \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES = \
   $(warning browser_keyevents_during_autoscrolling.js disabled due to frequent timeouts (bug 567950)) \
   browser_bug295977_autoscroll_overflow.js \
+  browser_Geometry.js \
   browser_save_resend_postdata.js \
   browser_Services.js \
-  browser_Geometry.js \
   $(NULL)
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/toolkit/mozapps/extensions/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/XPIProvider.jsm
@@ -5687,18 +5687,21 @@ DirectoryInstallLocation.prototype = {
    */
   uninstallAddon: function DirInstallLocation_uninstallAddon(aId) {
     let dir = this._directory.clone();
     dir.append(aId);
 
     delete this._DirToIDMap[dir.path];
     delete this._IDToDirMap[aId];
 
-    if (!dir.exists())
-      throw new Error("Attempt to uninstall unknown add-on " + aId);
+    if (!dir.exists()) {
+      WARN("Attempted to remove the directory for " + aId + " from " +
+           this._name + " but it was already gone");
+      return;
+    }
 
     dir.remove(true);
   },
 
   /**
    * Gets the ID of the add-on installed in the given directory.
    *
    * @param  aDir
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -128,16 +128,17 @@ function notifyInitialized() {
   if (!gIsInitializing) {
     var event = document.createEvent("Events");
     event.initEvent("Initialized", true, true);
     document.dispatchEvent(event);
   }
 }
 
 function shutdown() {
+  gCategories.shutdown();
   gSearchView.shutdown();
   gEventManager.shutdown();
   gViewController.shutdown();
 }
 
 // Used by external callers to load a specific view into the manager
 function loadView(aViewId, aCallback) {
   gViewController.loadView(aViewId, aCallback);
@@ -788,16 +789,17 @@ function getAddonsAndInstalls(aType, aCa
 
   return {addon: addonTypes, install: installTypes};
 }
 
 
 var gCategories = {
   node: null,
   _search: null,
+  _maybeHidden: null,
 
   initialize: function() {
     this.node = document.getElementById("categories");
     this._search = this.get("addons://search/");
 
     this.maybeHideSearch();
 
     var self = this;
@@ -815,23 +817,31 @@ var gCategories = {
         if (gViewController.parseViewId(viewId).type == "search") {
           viewId += encodeURIComponent(gHeader.searchQuery);
         }
 
         gViewController.loadView(viewId);
       }
     }, false);
 
-    var maybeHidden = ["addons://list/locale", "addons://list/searchengine"];
-    gPendingInitializations += maybeHidden.length;
-    maybeHidden.forEach(function(aId) {
+    this._maybeHidden = ["addons://list/locale", "addons://list/searchengine"];
+    gPendingInitializations += this._maybeHidden.length;
+    this._maybeHidden.forEach(function(aId) {
       var type = gViewController.parseViewId(aId).param;
       getAddonsAndInstalls(type, function(aAddonsList, aInstallsList) {
+        var hidden = (aAddonsList.length == 0 && aInstallsList.length == 0);
+        var item = self.get(aId);
+
+        // Don't load view that is becoming hidden
+        if (hidden && aId == gViewController.currentViewId)
+          gViewController.loadView(VIEW_DEFAULT);
+
+        item.hidden = hidden;
+
         if (aAddonsList.length > 0 || aInstallsList.length > 0) {
-          self.get(aId).hidden = false;
           notifyInitialized();
           return;
         }
 
         gEventManager.registerInstallListener({
           onDownloadStarted: function(aInstall) {
             this._maybeShowCategory(aInstall);
           },
@@ -856,16 +866,25 @@ var gCategories = {
           }
         });
 
         notifyInitialized();
       });
     });
   },
 
+  shutdown: function() {
+    // Force persist of hidden state. See bug 15232
+    var self = this;
+    this._maybeHidden.forEach(function(aId) {
+      var item = self.get(aId);
+      item.setAttribute("hidden", !!item.hidden);
+    });
+  },
+
   select: function(aId) {
     if (this.node.selectedItem &&
         this.node.selectedItem.value == aId)
       return;
 
     var view = gViewController.parseViewId(aId);
     if (view.type == "detail")
       return;
--- a/toolkit/mozapps/extensions/content/extensions.xul
+++ b/toolkit/mozapps/extensions/content/extensions.xul
@@ -109,21 +109,23 @@
         <richlistitem id="category-search" value="addons://search/"
                       class="category"
                       name="&view.search.label;" disabled="true"/>
         <richlistitem id="category-discover" value="addons://discover/"
                       class="category"
                       name="&view.discover.label;"/>
         <richlistitem id="category-languages" value="addons://list/locale"
                       class="category"
-                      name="&view.locales.label;" hidden="true"/>
+                      name="&view.locales.label;"
+                      hidden="true" persist="hidden"/>
         <richlistitem id="category-searchengines"
                       value="addons://list/searchengine"
                       class="category"
-                      name="&view.searchengines.label;" hidden="true"/>
+                      name="&view.searchengines.label;"
+                      hidden="true" persist="hidden"/>
         <richlistitem id="category-extensions" value="addons://list/extension"
                       class="category"
                       name="&view.features.label;"/>
         <richlistitem id="category-themes" value="addons://list/theme"
                       class="category"
                       name="&view.appearance.label;"/>
         <richlistitem id="category-plugins" value="addons://list/plugin"
                       class="category"
--- a/toolkit/mozapps/extensions/test/browser/Makefile.in
+++ b/toolkit/mozapps/extensions/test/browser/Makefile.in
@@ -48,16 +48,17 @@ include $(DEPTH)/config/autoconf.mk
 _TEST_FILES = \
   head.js \
   browser_bug557943.js \
   browser_bug562890.js \
   browser_bug562899.js \
   browser_bug562992.js \
   browser_bug567137.js \
   browser_bug572561.js \
+  browser_bug577990.js \
   browser_dragdrop.js \
   browser_searching.js \
   browser_searching.xml \
   browser_searching_empty.xml \
   browser_sorting.js \
   browser_uninstalling.js \
   browser_updatessl.js \
   browser_updatessl.rdf \
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/browser/browser_bug577990.js
@@ -0,0 +1,127 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Tests that the visible delay in showing the "Language" category occurs
+// very minimally
+
+var gManagerWindow;
+var gCategoryUtilities;
+var gProvider;
+var gInstall;
+var gInstallProperties = [{
+  name: "Locale Category Test",
+  type: "locale"
+}];
+
+function test() {
+  waitForExplicitFinish();
+
+  gProvider = new MockProvider();
+
+  open_manager(null, function(aWindow) {
+    gManagerWindow = aWindow;
+    gCategoryUtilities = new CategoryUtilities(gManagerWindow);
+    run_next_test();
+  });
+}
+
+function end_test() {
+  close_manager(gManagerWindow, finish);
+}
+
+function install_locale(aCallback) {
+  gInstall = gProvider.createInstalls(gInstallProperties)[0];
+  gInstall.addTestListener({
+    onInstallEnded: function(aInstall) {
+      gInstall.removeTestListener(this);
+      aCallback();
+    }
+  });
+  gInstall.install();
+}
+
+function check_hidden(aExpectedHidden) {
+  var hidden = !gCategoryUtilities.isTypeVisible("locale");
+  is(hidden, !!aExpectedHidden, "Should have correct hidden state");
+}
+
+function run_open_test(aTestSetup, aLoadHidden, aInitializedHidden, aSelected) {
+  function loadCallback(aManagerWindow) {
+    gManagerWindow = aManagerWindow;
+    gCategoryUtilities = new CategoryUtilities(gManagerWindow);
+    check_hidden(aLoadHidden);
+  }
+
+  function run() {
+    open_manager(null, function() {
+      check_hidden(aInitializedHidden);
+      var selected = (gCategoryUtilities.selectedCategory == "locale");
+      is(selected, !!aSelected, "Should have correct selected state");
+
+      run_next_test();
+    }, loadCallback);
+  }
+
+  close_manager(gManagerWindow, function() {
+    // Allow for asynchronous functions to run before the manager opens
+    aTestSetup ? aTestSetup(run) : run();
+  });
+}
+
+
+// Tests that the locale category is hidden when there are no locales installed
+add_test(function() {
+  run_open_test(null, true, true);
+});
+
+// Tests that installing a locale while the Add-on Manager is open shows the
+// locale category
+add_test(function() {
+  check_hidden(true);
+  install_locale(function() {
+    check_hidden(false);
+    run_next_test();
+  });
+});
+
+// Tests that the locale category is shown with no delay when restarting
+// Add-on Manager
+add_test(function() {
+  run_open_test(null, false, false);
+});
+
+// Tests that cancelling the locale install and restarting the Add-on Manager
+// causes the locale category to be hidden with an acceptable delay
+add_test(function() {
+  gInstall.cancel();
+  run_open_test(null, false, true)
+});
+
+// Tests that the locale category is hidden with no delay when restarting
+// Add-on Manager
+add_test(function() {
+  run_open_test(null, true, true);
+});
+
+// Tests that installing a locale when the Add-on Manager is closed, and then
+// opening the Add-on Manager causes the locale category to be shown with an
+// acceptable delay
+add_test(function() {
+  run_open_test(install_locale, true, false);
+});
+
+// Tests that selection of the locale category persists
+add_test(function() {
+  gCategoryUtilities.openType("locale", function() {
+    run_open_test(null, false, false, true);
+  });
+});
+
+// Tests that cancelling the locale install and restarting the Add-on Manager
+// causes the locale category to be hidden and not selected
+add_test(function() {
+  gInstall.cancel();
+  run_open_test(null, false, true);
+});
+
--- a/toolkit/mozapps/extensions/test/browser/head.js
+++ b/toolkit/mozapps/extensions/test/browser/head.js
@@ -75,18 +75,21 @@ function wait_for_manager_load(aManagerW
   }
 
   aManagerWindow.document.addEventListener("Initialized", function() {
     aManagerWindow.document.removeEventListener("Initialized", arguments.callee, false);
     aCallback(aManagerWindow);
   }, false);
 }
 
-function open_manager(aView, aCallback) {
+function open_manager(aView, aCallback, aLoadCallback) {
   function setup_manager(aManagerWindow) {
+    if (aLoadCallback)
+      aLoadCallback(aManagerWindow);
+
     if (aView)
       aManagerWindow.loadView(aView);
 
     ok(aManagerWindow != null, "Should have an add-ons manager window");
     is(aManagerWindow.location, MANAGER_URI, "Should be displaying the correct UI");
 
     wait_for_manager_load(aManagerWindow, function() {
       wait_for_view_load(aManagerWindow, aCallback);
@@ -114,18 +117,25 @@ function close_manager(aManagerWindow, a
   aManagerWindow.addEventListener("unload", function() {
     this.removeEventListener("unload", arguments.callee, false);
     aCallback();
   }, false);
 
   aManagerWindow.close();
 }
 
-function restart_manager(aManagerWindow, aView, aCallback) {
-  close_manager(aManagerWindow, function() { open_manager(aView, aCallback); });
+function restart_manager(aManagerWindow, aView, aCallback, aLoadCallback) {
+  if (!aManagerWindow) {
+    open_manager(aView, aCallback, aLoadCallback);
+    return;
+  }
+
+  close_manager(aManagerWindow, function() {
+    open_manager(aView, aCallback, aLoadCallback);
+  });
 }
 
 function is_element_visible(aWindow, aElement, aExpected, aMsg) {
   isnot(aElement, null, "Element should not be null, when checking visibility");
   var style = aWindow.getComputedStyle(aElement, "");
   var visible = style.display != "none" && style.visibility == "visible";
   is(visible, aExpected, aMsg);
 }
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug576735.js
@@ -0,0 +1,70 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Tests that we recover gracefully from an extension directory disappearing
+// when we were expecting to uninstall it.
+
+var addon1 = {
+  id: "addon1@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 1",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "1",
+    maxVersion: "1"
+  }]
+};
+
+var addon2 = {
+  id: "addon2@tests.mozilla.org",
+  version: "2.0",
+  name: "Test 2",
+  targetApplications: [{
+    id: "toolkit@mozilla.org",
+    minVersion: "1",
+    maxVersion: "1"
+  }]
+};
+
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+function run_test() {
+  do_test_pending();
+  createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "2");
+
+  var dest = profileDir.clone();
+  dest.append("addon1@tests.mozilla.org");
+  writeInstallRDFToDir(addon1, dest);
+
+  startupManager();
+
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+    a1.uninstall();
+
+    shutdownManager();
+
+    var dest = profileDir.clone();
+    dest.append("addon1@tests.mozilla.org");
+    dest.remove(true);
+
+    dest = profileDir.clone();
+    dest.append("addon2@tests.mozilla.org");
+    writeInstallRDFToDir(addon2, dest);
+
+    startupManager();
+
+    AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+                                 "addon2@tests.mozilla.org"],
+                                function([a1, a2]) {
+      // Addon1 should no longer be installed
+      do_check_eq(a1, null);
+
+      // Addon2 should have been detected
+      do_check_neq(a2, null);
+
+      do_test_finished();
+    });
+  });
+}
--- a/widget/src/windows/nsClipboard.h
+++ b/widget/src/windows/nsClipboard.h
@@ -91,19 +91,19 @@ protected:
   static PRBool FindPlatformHTML ( IDataObject* inDataObject, UINT inIndex, void** outData, PRUint32* outDataLen );
   static void ResolveShortcut ( nsILocalFile* inFileName, nsACString& outURL ) ;
 
   nsIWidget         * mWindow;
 
 };
 
 #define SET_FORMATETC(fe, cf, td, asp, li, med)   \
-	 {\
-	 (fe).cfFormat=cf;\
-	 (fe).ptd=td;\
-	 (fe).dwAspect=asp;\
-	 (fe).lindex=li;\
-	 (fe).tymed=med;\
-	 }
+   {\
+   (fe).cfFormat=cf;\
+   (fe).ptd=td;\
+   (fe).dwAspect=asp;\
+   (fe).lindex=li;\
+   (fe).tymed=med;\
+   }
 
 
 #endif // nsClipboard_h__
 
--- a/xpcom/string/public/nsString.h
+++ b/xpcom/string/public/nsString.h
@@ -74,16 +74,19 @@
 #include "nsTString.h"
 #include "string-template-undef.h"
 
   // declare nsCString, et. al.
 #include "string-template-def-char.h"
 #include "nsTString.h"
 #include "string-template-undef.h"
 
+PR_STATIC_ASSERT(sizeof(PRUnichar) == 2);
+PR_STATIC_ASSERT(sizeof(nsString::char_type) == 2);
+PR_STATIC_ASSERT(sizeof(nsCString::char_type) == 1);
 
   /**
    * A helper class that converts a UTF-16 string to ASCII in a lossy manner
    */
 class NS_LossyConvertUTF16toASCII : public nsCAutoString
   {
     public:
       explicit