merge the last green changeset on m-c to fx-team
authorTim Taubert <tim.taubert@gmx.de>
Thu, 08 Sep 2011 11:03:35 +0200
changeset 77975 183fb86c9ac4858045a9ca5d9e4997cda3c3f258
parent 77974 e4ab06518d81c805bf0b6f80ca97b93b29761278 (current diff)
parent 77962 b7d269a291b6f91a20958011d610cf8d443bd685 (diff)
child 78024 2bd109e6766f6f563321f7c4efdfe1a57964ec2d
child 78256 0cb195525cbc102e95d21f679ef8e3c39235dbf0
push id78
push userclegnitto@mozilla.com
push dateFri, 16 Dec 2011 17:32:24 +0000
treeherdermozilla-release@79d24e644fdd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone9.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge the last green changeset on m-c to fx-team
js/src/jsapi-tests/testGCChunkAlloc.cpp
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -4034,21 +4034,24 @@
       <handler event="mouseout">
         var anonid = event.originalTarget.getAttribute("anonid");
         if (anonid == "close-button")
           this.mOverCloseButton = false;
       </handler>
       <handler event="dragstart" phase="capturing">
         this.style.MozUserFocus = '';
       </handler>
-      <handler event="mousedown">
+      <handler event="mousedown" phase="capturing">
       <![CDATA[
         if (this.selected) {
           this.style.MozUserFocus = 'ignore';
           this.clientTop; // just using this to flush style updates
+        } else if (this.mOverCloseButton) {
+          // Prevent tabbox.xml from selecting the tab.
+          event.stopPropagation();
         }
       ]]>
       </handler>
       <handler event="mouseup">
         this.style.MozUserFocus = '';
       </handler>
     </handlers>
   </binding>
--- a/browser/components/wintaskbar/WindowsJumpLists.jsm
+++ b/browser/components/wintaskbar/WindowsJumpLists.jsm
@@ -17,16 +17,17 @@
  * 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):
  *   Jim Mathies <jmathies@mozilla.com> (Original author)
  *   Marco Bonardo <mak77@bonardo.net>
+ *   Brian R. Bondy <netzen@gmail.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
@@ -326,17 +327,17 @@ var WinTaskbarJumpList =
 
   _buildTasks: function WTBJL__buildTasks() {
     var items = Cc["@mozilla.org/array;1"].
                 createInstance(Ci.nsIMutableArray);
     this._tasks.forEach(function (task) {
       if ((this._shuttingDown && !task.close) || (!this._shuttingDown && !task.open))
         return;
       var item = this._getHandlerAppItem(task.title, task.description,
-                                         task.args, task.iconIndex);
+                                         task.args, task.iconIndex, null);
       items.appendElement(item, false);
     }, this);
     
     if (items.length > 0)
       this._builder.addListToBuild(this._builder.JUMPLIST_CATEGORY_TASKS, items);
   },
 
   _buildCustom: function WTBJL__buildCustom(title, items) {
@@ -369,17 +370,19 @@ var WinTaskbarJumpList =
           delete this._pendingStatements[LIST_TYPE.FREQUENT];
           // The are no more results, build the list.
           this._buildCustom(_getString("taskbar.frequent.label"), items);
           this._commitBuild();
           return;
         }
 
         let title = aResult.title || aResult.uri;
-        let shortcut = this._getHandlerAppItem(title, title, aResult.uri, 1);
+        let faviconPageUri = Services.io.newURI(aResult.uri, null, null);
+        let shortcut = this._getHandlerAppItem(title, title, aResult.uri, 1, 
+                                               faviconPageUri);
         items.appendElement(shortcut, false);
         this._frequentHashList.push(aResult.uri);
       },
       this
     );
   },
 
   _buildRecent: function WTBJL__buildRecent() {
@@ -412,33 +415,37 @@ var WinTaskbarJumpList =
 
         // Do not add items to recent that have already been added to frequent.
         if (this._frequentHashList &&
             this._frequentHashList.indexOf(aResult.uri) != -1) {
           return;
         }
 
         let title = aResult.title || aResult.uri;
-        let shortcut = this._getHandlerAppItem(title, title, aResult.uri, 1);
+        let faviconPageUri = Services.io.newURI(aResult.uri, null, null);
+        let shortcut = this._getHandlerAppItem(title, title, aResult.uri, 1,
+                                               faviconPageUri);
         items.appendElement(shortcut, false);
         count++;
       },
       this
     );
   },
 
   _deleteActiveJumpList: function WTBJL__deleteAJL() {
     this._builder.deleteActiveList();
   },
 
   /**
    * Jump list item creation helpers
    */
 
-  _getHandlerAppItem: function WTBJL__getHandlerAppItem(name, description, args, icon) {
+  _getHandlerAppItem: function WTBJL__getHandlerAppItem(name, description, 
+                                                        args, iconIndex, 
+                                                        faviconPageUri) {
     var file = Services.dirsvc.get("XCurProcD", Ci.nsILocalFile);
 
     // XXX where can we grab this from in the build? Do we need to?
     file.append("firefox.exe");
 
     var handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
                      createInstance(Ci.nsILocalHandlerApp);
     handlerApp.executable = file;
@@ -446,17 +453,18 @@ var WinTaskbarJumpList =
     if (name && name.length != 0)
       handlerApp.name = name;
     handlerApp.detailedDescription = description;
     handlerApp.appendParameter(args);
 
     var item = Cc["@mozilla.org/windows-jumplistshortcut;1"].
                createInstance(Ci.nsIJumpListShortcut);
     item.app = handlerApp;
-    item.iconIndex = icon;
+    item.iconIndex = iconIndex;
+    item.faviconPageUri = faviconPageUri;
     return item;
   },
 
   _getSeparatorItem: function WTBJL__getSeparatorItem() {
     var item = Cc["@mozilla.org/windows-jumplistseparator;1"].
                createInstance(Ci.nsIJumpListSeparator);
     return item;
   },
--- a/browser/locales/en-US/searchplugins/list.txt
+++ b/browser/locales/en-US/searchplugins/list.txt
@@ -1,6 +1,7 @@
 amazondotcom
 bing
 eBay
 google
+twitter
 wikipedia
 yahoo
new file mode 100644
--- /dev/null
+++ b/browser/locales/en-US/searchplugins/twitter.xml
@@ -0,0 +1,11 @@
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Twitter</ShortName>
+<Description>Realtime Twitter Search</Description>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A/v7+D/7+/j/+/v5g/v7+YP7+/mD+/v5I/v7+KP///wD///8A////AP///wD///8A////AP///wD+/v4H/v7+UPbv4pHgx47B1K9Y3tWwWN7Ur1je3sKCx+rbuKj+/v5n/v7+GP///wD///8A////AP///wD+/v4Y+fbweM2ycMe2iB7/vI0f/8STIf/KlyL/zJki/8yZIv/LmCL/0ahK5/Hp1JH+/v4Y////AP///wD///8A7OTTaquHN+CujkXPs5ZTv6N6G/+2iB7/xpUh/8yZIv/MmSL/zJki/8yZIv/Kmy738OjUi////wD///8A////AMKtfY7w6+Ef////AP///wD///8A3sqbp8iWIf/MmSL/zJki/8yZIv/MmSL/y5gi/8mePO7+/v4w////AP///wD///8A////AP///wD+/v4H/v7+V9CtWN3KmCL/zJki/8yZIv/MmSL/zJki/8yZIv/JlyH/5tSqp/7+/mD+/v4/////AP///wD///8A+PXvJtGyZdXNnS/3y5gi/8qYIv/LmCL/zJki/8yZIv/MmSL/y5gi/82iPO7LqVfe0byMmf///wD///8A/v7+D/Do1JHKmy73ypci/8KSIP+/jyD/xpQh/8uYIv/MmSL/zJki/8qYIv+/jyD/rIEd/9nKqH7///8A////APPu4TzAlSz3wZEg/7mLH/+sgR3/uZdGz7mLH//JlyH/zJki/8yZIv/GlSH/to0r9eXbxD/Vx6dg////AP7+/h/p38WhtIsq9al/HP+kfyjuybaKgf///wCzjzjlwJAg/8qYIv/JlyH/u4wf/8CkYrn///8A////AP///wDj2sRMnHUa/7meYa7Vx6dg////AP///wD///8A2MmnYK6DHf++jiD/vo4g/62CHf/k2sQ/////AP///wD///8A8OvhH/f07w////8A////AP///wD///8A////AP///wC/p3Cfpnwc/66GKvPg1LZ8////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////ANXHp2DJtoqByLWKgf///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A//8AAP//AADgPwAAwA8AAIAHAAB4BwAA+AMAAPAAAADgAQAA4AMAAMEDAADPhwAA/48AAP/nAAD//wAA//8AAA==</Image>
+<SearchForm>https://twitter.com/search/</SearchForm>
+<Url type="text/html" method="GET" template="https://twitter.com/search/{searchTerms}">
+  <Param name="partner" value="Firefox"/>
+  <Param name="source" value="desktop-search"/>
+</Url>
+</SearchPlugin>
--- a/build/autoconf/mozconfig-find
+++ b/build/autoconf/mozconfig-find
@@ -35,18 +35,20 @@
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
 # mozconfigfind - Loads options from .mozconfig onto configure's
 #    command-line. The .mozconfig file is searched for in the 
 #    order:
-#       if $MOZCONFIG is set, use that.
-#       Otherwise, use $TOPSRCDIR/.mozconfig
+#       If $MOZCONFIG is set, use that.
+#       If one of $TOPSRCDIR/.mozconfig or $TOPSRCDIR/mozconfig exists, use it.
+#       If both exist, or if various legacy locations contain a mozconfig, error.
+#       Otherwise, use the default build options.
 #
 topsrcdir=$1
 
 abspath() {
   if uname -s | grep -q MINGW; then
     # We have no way to figure out whether we're in gmake or pymake right
     # now. gmake gives us Unix-style paths while pymake gives us Windows-style
     # paths, so attempt to handle both.
@@ -71,30 +73,35 @@ if [ -n "$MOZCONFIG" ] && ! [ -f "$MOZCO
   exit 1
 fi
 
 if [ -n "$MOZ_MYCONFIG" ]; then
   echo "Your environment currently has the MOZ_MYCONFIG variable set to \"$MOZ_MYCONFIG\". MOZ_MYCONFIG is no longer supported. Please use MOZCONFIG instead."
   exit 1
 fi
 
+if [ -z "$MOZCONFIG" ] && [ -f "$topsrcdir/.mozconfig" ] && [ -f "$topsrcdir/mozconfig" ]; then
+  echo "Both \$topsrcdir/.mozconfig and \$topsrcdir/mozconfig are supported, but you must choose only one. Please remove the other."
+  exit 1
+fi
+
 for _config in "$MOZCONFIG" \
-               "$topsrcdir/.mozconfig"
+               "$topsrcdir/.mozconfig" \
+               "$topsrcdir/mozconfig"
 do
   if test -f "$_config"; then
     echo `abspath $_config`
     exit 0
   fi
 done
 
 # We used to support a number of other implicit .mozconfig locations. We now
 # detect if we were about to use any of these locations and issue an error if we
 # find any.
-for _config in "$topsrcdir/mozconfig" \
-               "$topsrcdir/mozconfig.sh" \
+for _config in "$topsrcdir/mozconfig.sh" \
                "$topsrcdir/myconfig.sh" \
                "$HOME/.mozconfig" \
                "$HOME/.mozconfig.sh" \
                "$HOME/.mozmyconfig.sh"
 do
   if test -f "$_config"; then
     echo "You currently have a mozconfig at \"$_config\". This implicit location is no longer supported. Please move it to $topsrcdir/.mozconfig or specify it explicitly via \$MOZCONFIG.";
     exit 1
--- a/client.mk
+++ b/client.mk
@@ -263,16 +263,17 @@ configure depend realbuild install expor
 else
 
 # MOZ_CURRENT_PROJECT: either doing a single-project build, or building an
 # individual project in a multi-project build.
 
 ####################################
 # Configure
 
+MAKEFILE      = $(wildcard $(OBJDIR)/Makefile)
 CONFIG_STATUS = $(wildcard $(OBJDIR)/config.status)
 CONFIG_CACHE  = $(wildcard $(OBJDIR)/config.cache)
 
 EXTRA_CONFIG_DEPS := \
 	$(TOPSRCDIR)/aclocal.m4 \
 	$(wildcard $(TOPSRCDIR)/build/autoconf/*.m4) \
 	$(TOPSRCDIR)/js/src/aclocal.m4 \
 	$(NULL)
@@ -311,17 +312,23 @@ endif
 	@if test ! -d $(OBJDIR); then $(MKDIR) $(OBJDIR); else true; fi
 	@echo cd $(OBJDIR);
 	@echo $(CONFIGURE) $(CONFIGURE_ARGS)
 	@cd $(OBJDIR) && $(BUILD_PROJECT_ARG) $(CONFIGURE_ENV_ARGS) $(CONFIGURE) $(CONFIGURE_ARGS) \
 	  || ( echo "*** Fix above errors and then restart with\
                \"$(MAKE) -f client.mk build\"" && exit 1 )
 	@touch $(OBJDIR)/Makefile
 
-$(OBJDIR)/Makefile $(OBJDIR)/config.status: $(CONFIG_STATUS_DEPS)
+ifneq (,$(MAKEFILE))
+$(OBJDIR)/Makefile: $(OBJDIR)/config.status
+
+$(OBJDIR)/config.status: $(CONFIG_STATUS_DEPS)
+else
+$(OBJDIR)/Makefile: $(CONFIG_STATUS_DEPS)
+endif
 	@$(MAKE) -f $(TOPSRCDIR)/client.mk configure
 
 ifneq (,$(CONFIG_STATUS))
 $(OBJDIR)/config/autoconf.mk: $(TOPSRCDIR)/config/autoconf.mk.in
 	cd $(OBJDIR); \
 	  CONFIG_FILES=config/autoconf.mk ./config.status
 endif
 
--- a/config/optimizejars.py
+++ b/config/optimizejars.py
@@ -298,16 +298,17 @@ def optimizejar(jar, outjar, inlog = Non
 
     if inlog is None:
         dirend.cdir_offset = out_offset
 
     if dups_found > 0:
         print("WARNING: Found %d duplicate files taking %d bytes"%(dups_found, dupe_bytes))
 
     dirend.cdir_size = len(cdir_data)
+    dirend.disk_entries = dirend.cdir_entries
     dirend_data = dirend.pack()
     assert_true(size_of(cdir_end) == len(dirend_data), "Failed to serialize directory end correctly. Serialized size;%d, expected:%d"%(len(dirend_data), size_of(cdir_end)));
 
     outfd.seek(dirend.cdir_offset)
     outfd.write(cdir_data)
     outfd.write(dirend_data)
 
     # for ordered jars the central directory is written in the begining of the file, so a second central-directory
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -78,16 +78,17 @@ static fp_except_t oldmask = fpsetmask(~
 #include "nsReadableUtils.h"
 #include "mozilla/AutoRestore.h"
 #include "nsINode.h"
 #include "nsHashtable.h"
 #include "nsIDOMNode.h"
 #include "nsHtml5Parser.h"
 #include "nsIFragmentContentSink.h"
 #include "nsMathUtils.h"
+#include "mozilla/TimeStamp.h"
 
 struct nsNativeKeyEvent; // Don't include nsINativeKeyBindings.h here: it will force strange compilation error!
 
 class nsIDOMScriptObjectFactory;
 class nsIXPConnect;
 class nsIContent;
 class nsIDOMKeyEvent;
 class nsIDocument;
@@ -184,16 +185,17 @@ struct nsShortcutCandidate {
   PRUint32 mCharCode;
   PRBool   mIgnoreShift;
 };
 
 class nsContentUtils
 {
   friend class nsAutoScriptBlockerSuppressNodeRemoved;
   typedef mozilla::dom::Element Element;
+  typedef mozilla::TimeDuration TimeDuration;
 
 public:
   static nsresult Init();
 
   /**
    * Get a JSContext from the document's scope object.
    */
   static JSContext* GetContextFromDocument(nsIDocument *aDocument);
@@ -1715,16 +1717,23 @@ public:
 
   /**
    * Returns PR_TRUE if key input is restricted in DOM full-screen mode
    * to non-alpha-numeric key codes only. This mirrors the
    * "full-screen-api.key-input-restricted" pref.
    */
   static PRBool IsFullScreenKeyInputRestricted();
 
+  /**
+   * Returns the time limit on handling user input before
+   * nsEventStateManager::IsHandlingUserInput() stops returning PR_TRUE.
+   * This enables us to detect long running user-generated event handlers.
+   */
+  static TimeDuration HandlingUserInputTimeout();
+
   static void GetShiftText(nsAString& text);
   static void GetControlText(nsAString& text);
   static void GetMetaText(nsAString& text);
   static void GetAltText(nsAString& text);
   static void GetModifierSeparatorText(nsAString& text);
 
   /**
    * Returns if aContent has a tabbable subdocument.
@@ -1882,16 +1891,17 @@ private:
 
   static nsIInterfaceRequestor* sSameOriginChecker;
 
   static PRBool sIsHandlingKeyBoardEvent;
   static PRBool sAllowXULXBL_for_file;
   static PRBool sIsFullScreenApiEnabled;
   static PRBool sTrustedFullScreenOnly;
   static PRBool sFullScreenKeyInputRestricted;
+  static PRUint32 sHandlingInputTimeout;
 
   static nsHtml5Parser* sHTMLFragmentParser;
   static nsIParser* sXMLFragmentParser;
   static nsIFragmentContentSink* sXMLFragmentSink;
 
   static nsString* sShiftText;
   static nsString* sControlText;
   static nsString* sMetaText;
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -196,16 +196,17 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 #include "nsChannelPolicy.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsContentDLF.h"
 #ifdef MOZ_MEDIA
 #include "nsHTMLMediaElement.h"
 #endif
 #include "nsDOMTouchEvent.h"
 #include "nsIScriptElement.h"
+#include "prdtoa.h"
 
 #include "mozilla/Preferences.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::layers;
 using namespace mozilla;
 
 const char kLoadAsData[] = "loadAsData";
@@ -261,16 +262,18 @@ nsString* nsContentUtils::sMetaText = ns
 nsString* nsContentUtils::sAltText = nsnull;
 nsString* nsContentUtils::sModifierSeparator = nsnull;
 
 PRBool nsContentUtils::sInitialized = PR_FALSE;
 PRBool nsContentUtils::sIsFullScreenApiEnabled = PR_FALSE;
 PRBool nsContentUtils::sTrustedFullScreenOnly = PR_TRUE;
 PRBool nsContentUtils::sFullScreenKeyInputRestricted = PR_TRUE;
 
+PRUint32 nsContentUtils::sHandlingInputTimeout = 1000;
+
 nsHtml5Parser* nsContentUtils::sHTMLFragmentParser = nsnull;
 nsIParser* nsContentUtils::sXMLFragmentParser = nsnull;
 nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nsnull;
 
 static PLDHashTable sEventListenerManagersHash;
 
 class EventListenerManagerMapEntry : public PLDHashEntryHdr
 {
@@ -314,16 +317,23 @@ EventListenerManagerHashClearEntry(PLDHa
 class nsSameOriginChecker : public nsIChannelEventSink,
                             public nsIInterfaceRequestor
 {
   NS_DECL_ISUPPORTS
   NS_DECL_NSICHANNELEVENTSINK
   NS_DECL_NSIINTERFACEREQUESTOR
 };
 
+/* static */
+TimeDuration
+nsContentUtils::HandlingUserInputTimeout()
+{
+  return TimeDuration::FromMilliseconds(sHandlingInputTimeout);
+}
+
 // static
 nsresult
 nsContentUtils::Init()
 {
   if (sInitialized) {
     NS_WARNING("Init() called twice");
 
     return NS_OK;
@@ -392,16 +402,20 @@ nsContentUtils::Init()
                                "full-screen-api.enabled");
 
   Preferences::AddBoolVarCache(&sTrustedFullScreenOnly,
                                "full-screen-api.allow-trusted-requests-only");
 
   Preferences::AddBoolVarCache(&sFullScreenKeyInputRestricted,
                                "full-screen-api.key-input-restricted");
 
+  Preferences::AddUintVarCache(&sHandlingInputTimeout,
+                               "dom.event.handling-user-input-time-limit",
+                               1000);
+
   sInitialized = PR_TRUE;
 
   return NS_OK;
 }
 
 void
 nsContentUtils::GetShiftText(nsAString& text)
 {
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -5529,18 +5529,20 @@ nsGenericElement::SizeOf() const
 #define TOUCH_EVENT EVENT
 #include "nsEventNameList.h"
 #undef TOUCH_EVENT
 #undef EVENT
 
 PRBool
 nsINode::Contains(const nsINode* aOther) const
 {
+  if (aOther == this) {
+    return PR_TRUE;
+  }
   if (!aOther ||
-      aOther == this ||
       GetOwnerDoc() != aOther->GetOwnerDoc() ||
       IsInDoc() != aOther->IsInDoc() ||
       !(aOther->IsElement() ||
         aOther->IsNodeOfType(nsINode::eCONTENT)) ||
       !GetFirstChild()) {
     return PR_FALSE;
   }
 
--- a/content/base/test/chrome/test_bug683852.xul
+++ b/content/base/test/chrome/test_bug683852.xul
@@ -16,23 +16,25 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   <!-- test code goes here -->
   <script type="application/javascript">
   <![CDATA[
   /** Test for Bug 683852 **/
   SimpleTest.waitForExplicitFinish();
 
   function startTest() {
-    is(document.contains(document), false, "Document should not contain itself!");
+    is(document.contains(document), true, "Document should contain itself!");
 
     var tb = document.getElementById("testbutton");
     is(document.contains(tb), true, "Document should contain element in it!");
+    is(tb.contains(tb), true, "Element should contain itself.")
     var anon = document.getAnonymousElementByAttribute(tb, "anonid", "button-box");
     is(document.contains(anon), false, "Document should not contain anonymous element in it!");
     is(tb.contains(anon), false, "Element should not contain anonymous element in it!");
+    is(anon.contains(anon), true, "Anonymous element should contain itself.")
     is(document.documentElement.contains(tb), true, "Element should contain element in it!");
     is(document.contains(document.createElement("foo")), false, "Document shouldn't contain element which is't in the document");
     is(document.contains(document.createTextNode("foo")), false, "Document shouldn't contain text node which is't in the document");
 
     var link = document.getElementById("link");
     is(document.contains(link.firstChild), true,
        "Document should contain a text node in it.");
     is(link.contains(link.firstChild), true,
@@ -45,17 +47,17 @@ https://bugzilla.mozilla.org/show_bug.cg
     is(pi.contains(document), false, "Processing instruction shouldn't contain document");
     document.documentElement.appendChild(pi);
     document.contains(pi, true, "Document should contain processing instruction");
 
     var df = document.createRange().createContextualFragment("<div>foo</div>");
     is(df.contains(df.firstChild), true, "Document fragment should contain its child");
     is(df.contains(df.firstChild.firstChild), true,
        "Document fragment should contain its descendant");
-    is(df.contains(df), false, "Document fragment shouldn't contain itself.");
+    is(df.contains(df), true, "Document fragment should contain itself.");
 
     var d = document.implementation.createHTMLDocument("");
     is(document.contains(d), false,
        "Document shouldn't contain another document.");
     is(document.contains(d.createElement("div")), false,
        "Document shouldn't contain an element from another document.");
 
     SimpleTest.finish();
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -170,16 +170,18 @@ static nsITimerCallback* gUserInteractio
 // Pixel scroll accumulation for synthetic line scrolls
 static nscoord gPixelScrollDeltaX = 0;
 static nscoord gPixelScrollDeltaY = 0;
 static PRUint32 gPixelScrollDeltaTimeout = 0;
 
 static nscoord
 GetScrollableLineHeight(nsIFrame* aTargetFrame);
 
+TimeStamp nsEventStateManager::sHandlingInputStart;
+
 static inline PRBool
 IsMouseEventReal(nsEvent* aEvent)
 {
   NS_ABORT_IF_FALSE(NS_IS_MOUSE_EVENT_STRUCT(aEvent), "Not a mouse event");
   // Return true if not synthesized.
   return static_cast<nsMouseEvent*>(aEvent)->reason == nsMouseEvent::eReal;
 }
 
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -52,16 +52,18 @@
 #include "nsIFrameLoader.h"
 #include "nsIFrame.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIMarkupDocumentViewer.h"
 #include "nsIScrollableFrame.h"
 #include "nsFocusManager.h"
 #include "nsIDocument.h"
 #include "nsEventStates.h"
+#include "mozilla/TimeStamp.h"
+#include "nsContentUtils.h"
 
 class nsIPresShell;
 class nsIDocShell;
 class nsIDocShellTreeNode;
 class nsIDocShellTreeItem;
 class imgIContainer;
 class nsDOMDataTransfer;
 
@@ -75,16 +77,20 @@ class TabParent;
  * Event listener manager
  */
 
 class nsEventStateManager : public nsSupportsWeakReference,
                             public nsIObserver
 {
   friend class nsMouseWheelTransaction;
 public:
+
+  typedef mozilla::TimeStamp TimeStamp;
+  typedef mozilla::TimeDuration TimeDuration;
+
   nsEventStateManager();
   virtual ~nsEventStateManager();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   nsresult Init();
   nsresult Shutdown();
@@ -164,34 +170,48 @@ public:
 
   nsresult SetCursor(PRInt32 aCursor, imgIContainer* aContainer,
                      PRBool aHaveHotspot, float aHotspotX, float aHotspotY,
                      nsIWidget* aWidget, PRBool aLockCursor); 
 
   static void StartHandlingUserInput()
   {
     ++sUserInputEventDepth;
+    if (sUserInputEventDepth == 1) {
+      sHandlingInputStart = TimeStamp::Now();
+    }
   }
 
   static void StopHandlingUserInput()
   {
     --sUserInputEventDepth;
+    if (sUserInputEventDepth == 0) {
+      sHandlingInputStart = TimeStamp();
+    }
   }
 
   static PRBool IsHandlingUserInput()
   {
-    return sUserInputEventDepth > 0;
+    if (sUserInputEventDepth <= 0) {
+      return PR_FALSE;
+    }
+    TimeDuration timeout = nsContentUtils::HandlingUserInputTimeout();
+    return timeout <= TimeDuration(0) ||
+           (TimeStamp::Now() - sHandlingInputStart) <= timeout;
   }
 
   /**
    * Returns true if the current code is being executed as a result of user input.
    * This includes timers or anything else that is initiated from user input.
    * However, mouse hover events are not counted as user input, nor are
    * page load events. If this method is called from asynchronously executed code,
-   * such as during layout reflows, it will return false.
+   * such as during layout reflows, it will return false. If more time has elapsed
+   * since the user input than is specified by the
+   * dom.event.handling-user-input-time-limit pref (default 1 second), this
+   * function also returns false.
    */
   NS_IMETHOD_(PRBool) IsHandlingUserInputExternal() { return IsHandlingUserInput(); }
   
   nsPresContext* GetPresContext() { return mPresContext; }
 
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsEventStateManager,
                                            nsIObserver)
 
@@ -502,16 +522,18 @@ private:
   nsCOMPtr<nsIDocument> mDocument;   // Doesn't necessarily need to be owner
 
   PRUint32 mLClickCount;
   PRUint32 mMClickCount;
   PRUint32 mRClickCount;
 
   PRPackedBool m_haveShutdown;
 
+  // Time at which we began handling user input.
+  static TimeStamp sHandlingInputStart;
 
 public:
   static nsresult UpdateUserActivityTimer(void);
   // Array for accesskey support
   nsCOMArray<nsIContent> mAccessKeys;
 
   // Unlocks pixel scrolling
   PRPackedBool mLastLineScrollConsumedX;
--- a/content/html/content/test/test_fullscreen-api.html
+++ b/content/html/content/test/test_fullscreen-api.html
@@ -1,15 +1,16 @@
  <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test for Bug 545812</title>
   <script type="application/javascript" src="/MochiKit/packed.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=545812">Mozilla Bug 545812</a>
 <p id="display"></p>
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
@@ -33,16 +34,33 @@ function run() {
   document.addEventListener("mozfullscreenchange",
     function(){ok(false, "Should never receive a mozfullscreenchange event in the main window.");},
     false);
 
   // Ensure the full-screen api is enabled, and will be disabled on test exit.
   prevEnabled = SpecialPowers.getBoolPref("full-screen-api.enabled");
   SpecialPowers.setBoolPref("full-screen-api.enabled", true);
 
+  // Test requesting full-screen mode in a long-running user-generated event handler.
+  // The request in the key handler should not be granted.
+  window.addEventListener("keypress", keyHandler, false);
+  synthesizeKey("VK_A", {});
+}
+
+function keyHandler(event) {
+  window.removeEventListener("keypress", keyHandler, false);
+  
+  // Busy loop until 2s has passed. We should then be past the 1 second threshold, and so
+  // our request for full-screen mode should be rejected.
+  var end = (new Date()).getTime() + 2000;
+  while ((new Date()).getTime() < end) {
+    ; // Wait...
+  }
+  document.body.mozRequestFullScreen();
+
   prevTrusted = SpecialPowers.getBoolPref("full-screen-api.allow-trusted-requests-only");
 
   // Request full-screen from a non trusted context (this script isn't a user
   // generated event!). We should not receive a "mozfullscreenchange" event.
   SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", true);
   document.body.mozRequestFullScreen();
 
   // Disable the requirement for trusted contexts only, so the tests are easier
--- a/content/smil/nsSMILAnimationController.cpp
+++ b/content/smil/nsSMILAnimationController.cpp
@@ -587,17 +587,17 @@ nsSMILAnimationController::DoMilestoneSa
       nsSMILTimeContainer* container = elem->GetTimeContainer();
       if (!container)
         // The container may be nsnull if the element has been detached from its
         // parent since registering a milestone.
         continue;
 
       nsSMILTimeValue containerTimeValue =
         container->ParentToContainerTime(sampleTime);
-      if (!containerTimeValue.IsResolved())
+      if (!containerTimeValue.IsDefinite())
         continue;
 
       // Clamp the converted container time to non-negative values.
       nsSMILTime containerTime = NS_MAX<nsSMILTime>(0, containerTimeValue.GetMillis());
 
       if (nextMilestone.mIsEnd) {
         elem->TimedElement().SampleEndAt(containerTime);
       } else {
--- a/content/smil/nsSMILAnimationFunction.cpp
+++ b/content/smil/nsSMILAnimationFunction.cpp
@@ -247,18 +247,17 @@ nsSMILAnimationFunction::ComposeResult(c
   // Check that we have the right number of keySplines and keyTimes
   CheckValueListDependentAttrs(values.Length());
   if (mErrorFlags != 0)
     return;
 
   // If this interval is active, we must have a non-negative mSampleTime
   NS_ABORT_IF_FALSE(mSampleTime >= 0 || !mIsActive,
       "Negative sample time for active animation");
-  NS_ABORT_IF_FALSE(mSimpleDuration.IsResolved() ||
-      mSimpleDuration.IsIndefinite() || mLastValue,
+  NS_ABORT_IF_FALSE(mSimpleDuration.IsResolved() || mLastValue,
       "Unresolved simple duration for active or frozen animation");
 
   // If we want to add but don't have a base value then just fail outright.
   // This can happen when we skipped getting the base value because there's an
   // animation function in the sandwich that should replace it but that function
   // failed unexpectedly.
   PRBool isAdditive = IsAdditive();
   if (isAdditive && aResult.IsNull())
@@ -403,17 +402,17 @@ nsSMILAnimationFunction::InterpolateResu
 
   // Get the normalised progress through the simple duration.
   //
   // If we have an indefinite simple duration, just set the progress to be
   // 0 which will give us the expected behaviour of the animation being fixed at
   // its starting point.
   double simpleProgress = 0.0;
 
-  if (mSimpleDuration.IsResolved()) {
+  if (mSimpleDuration.IsDefinite()) {
     nsSMILTime dur = mSimpleDuration.GetMillis();
 
     NS_ABORT_IF_FALSE(dur >= 0, "Simple duration should not be negative");
     NS_ABORT_IF_FALSE(mSampleTime >= 0, "Sample time should not be negative");
 
     if (mSampleTime >= dur || mSampleTime < 0) {
       NS_ERROR("Animation sampled outside interval");
       return NS_ERROR_FAILURE;
--- a/content/smil/nsSMILInterval.cpp
+++ b/content/smil/nsSMILInterval.cpp
@@ -105,18 +105,18 @@ nsSMILInterval::End()
   NS_ABORT_IF_FALSE(mBegin && mEnd,
       "Requesting End() on un-initialized interval.");
   return mEnd;
 }
 
 void
 nsSMILInterval::SetBegin(nsSMILInstanceTime& aBegin)
 {
-  NS_ABORT_IF_FALSE(aBegin.Time().IsResolved(),
-      "Attempting to set unresolved begin time on interval");
+  NS_ABORT_IF_FALSE(aBegin.Time().IsDefinite(),
+      "Attempting to set unresolved or indefinite begin time on interval");
   NS_ABORT_IF_FALSE(!mBeginFixed,
       "Attempting to set begin time but the begin point is fixed");
   // Check that we're not making an instance time dependent on itself. Such an
   // arrangement does not make intuitive sense and should be detected when
   // creating or updating intervals.
   NS_ABORT_IF_FALSE(!mBegin || aBegin.GetBaseTime() != mBegin,
       "Attempting to make self-dependent instance time");
 
--- a/content/smil/nsSMILTimeContainer.cpp
+++ b/content/smil/nsSMILTimeContainer.cpp
@@ -256,17 +256,17 @@ PRBool
 nsSMILTimeContainer::GetNextMilestoneInParentTime(
     nsSMILMilestone& aNextMilestone) const
 {
   if (mMilestoneEntries.IsEmpty())
     return PR_FALSE;
 
   nsSMILTimeValue parentTime =
     ContainerToParentTime(mMilestoneEntries.Top().mMilestone.mTime);
-  if (!parentTime.IsResolved())
+  if (!parentTime.IsDefinite())
     return PR_FALSE;
 
   aNextMilestone = nsSMILMilestone(parentTime.GetMillis(),
                                    mMilestoneEntries.Top().mMilestone.mIsEnd);
 
   return PR_TRUE;
 }
 
@@ -274,17 +274,17 @@ PRBool
 nsSMILTimeContainer::PopMilestoneElementsAtMilestone(
       const nsSMILMilestone& aMilestone,
       AnimElemArray& aMatchedElements)
 {
   if (mMilestoneEntries.IsEmpty())
     return PR_FALSE;
 
   nsSMILTimeValue containerTime = ParentToContainerTime(aMilestone.mTime);
-  if (!containerTime.IsResolved())
+  if (!containerTime.IsDefinite())
     return PR_FALSE;
 
   nsSMILMilestone containerMilestone(containerTime.GetMillis(),
                                      aMilestone.mIsEnd);
 
   NS_ABORT_IF_FALSE(mMilestoneEntries.Top().mMilestone >= containerMilestone,
       "Trying to pop off earliest times but we have earlier ones that were "
       "overlooked");
--- a/content/smil/nsSMILTimeValue.cpp
+++ b/content/smil/nsSMILTimeValue.cpp
@@ -48,22 +48,22 @@ Cmp(PRInt64 aA, PRInt64 aB)
   return aA == aB ? 0 : (aA > aB ? 1 : -1);
 }
 
 PRInt8
 nsSMILTimeValue::CompareTo(const nsSMILTimeValue& aOther) const
 {
   PRInt8 result;
 
-  if (mState == STATE_RESOLVED) {
-    result = (aOther.mState == STATE_RESOLVED)
+  if (mState == STATE_DEFINITE) {
+    result = (aOther.mState == STATE_DEFINITE)
            ? Cmp(mMilliseconds, aOther.mMilliseconds)
            : -1;
   } else if (mState == STATE_INDEFINITE) {
-    if (aOther.mState == STATE_RESOLVED)
+    if (aOther.mState == STATE_DEFINITE)
       result = 1;
     else if (aOther.mState == STATE_INDEFINITE)
       result = 0;
     else
       result = -1;
   } else {
     result = (aOther.mState != STATE_UNRESOLVED) ? 1 : 0;
   }
--- a/content/smil/nsSMILTimeValue.h
+++ b/content/smil/nsSMILTimeValue.h
@@ -61,61 +61,45 @@
  * nsSMILTimeValueSpec -- a component of a begin or end attribute, such as the
  *                        '5s' or 'a.end+2m' in begin="5s; a.end+2m". Acts as
  *                        a broker between an nsSMILTimedElement and its
  *                        nsSMILInstanceTimes by generating new instance times
  *                        and handling changes to existing times.
  *
  * Objects of this class may be in one of three states:
  *
- * 1) The time is resolved and has a millisecond value
- * 2) The time is indefinite
- * 3) The time in unresolved
- *
- * There is considerable chance for confusion with regards to the indefinite
- * state. Is it resolved? We adopt the convention that it is NOT resolved (but
- * nor is it unresolved). This simplifies implementation as you can then write:
- *
- * if (time.IsResolved())
- *    x = time.GetMillis()
- *
- * instead of:
- *
- * if (time.IsResolved() && !time.IsIndefinite())
- *    x = time.GetMillis()
- *
- * Testing if a time is unresolved becomes more complicated but this is tested
- * much less often.
+ * 1) The time is resolved and has a definite millisecond value
+ * 2) The time is resolved and indefinite
+ * 3) The time is unresolved
  *
  * In summary:
  *
- * State         |  GetMillis         |  IsResolved        |  IsIndefinite
- * --------------+--------------------+--------------------+-------------------
- * Resolved      |  The millisecond   |  PR_TRUE           |  PR_FALSE
- *               |  time              |                    |
- * --------------+--------------------+--------------------+-------------------
- * Indefinite    |  LL_MAXINT         |  PR_FALSE          |  PR_TRUE
- * --------------+--------------------+--------------------+-------------------
- * Unresolved    |  LL_MAXINT         |  PR_FALSE          |  PR_FALSE
+ * State      | GetMillis       | IsDefinite | IsIndefinite | IsResolved
+ * -----------+-----------------+------------+--------------+------------
+ * Definite   | nsSMILTimeValue | PR_TRUE    | PR_FALSE     | PR_TRUE
+ * -----------+-----------------+------------+--------------+------------
+ * Indefinite | --              | PR_FALSE   | PR_TRUE      | PR_TRUE
+ * -----------+-----------------+------------+--------------+------------
+ * Unresolved | --              | PR_FALSE   | PR_FALSE     | PR_FALSE
  *
  */
 
 class nsSMILTimeValue
 {
 public:
   // Creates an unresolved time value
   nsSMILTimeValue()
   : mMilliseconds(kUnresolvedMillis),
     mState(STATE_UNRESOLVED)
   { }
 
   // Creates a resolved time value
   explicit nsSMILTimeValue(nsSMILTime aMillis)
   : mMilliseconds(aMillis),
-    mState(STATE_RESOLVED)
+    mState(STATE_DEFINITE)
   { }
 
   // Named constructor to create an indefinite time value
   static nsSMILTimeValue Indefinite()
   {
     nsSMILTimeValue value;
     value.SetIndefinite();
     return value;
@@ -123,34 +107,35 @@ public:
 
   PRBool IsIndefinite() const { return mState == STATE_INDEFINITE; }
   void SetIndefinite()
   {
     mState = STATE_INDEFINITE;
     mMilliseconds = kUnresolvedMillis;
   }
 
-  PRBool IsResolved() const { return mState == STATE_RESOLVED; }
+  PRBool IsResolved() const { return mState != STATE_UNRESOLVED; }
   void SetUnresolved()
   {
     mState = STATE_UNRESOLVED;
     mMilliseconds = kUnresolvedMillis;
   }
 
+  PRBool IsDefinite() const { return mState == STATE_DEFINITE; }
   nsSMILTime GetMillis() const
   {
-    NS_ABORT_IF_FALSE(mState == STATE_RESOLVED,
-       "GetMillis() called for unresolved time");
+    NS_ABORT_IF_FALSE(mState == STATE_DEFINITE,
+       "GetMillis() called for unresolved or indefinite time");
 
-    return mState == STATE_RESOLVED ? mMilliseconds : kUnresolvedMillis;
+    return mState == STATE_DEFINITE ? mMilliseconds : kUnresolvedMillis;
   }
 
   void SetMillis(nsSMILTime aMillis)
   {
-    mState = STATE_RESOLVED;
+    mState = STATE_DEFINITE;
     mMilliseconds = aMillis;
   }
 
   PRInt8 CompareTo(const nsSMILTimeValue& aOther) const;
 
   PRBool operator==(const nsSMILTimeValue& aOther) const
   { return CompareTo(aOther) == 0; }
 
@@ -167,17 +152,17 @@ public:
   { return CompareTo(aOther) <= 0; }
 
   PRBool operator>=(const nsSMILTimeValue& aOther) const
   { return CompareTo(aOther) >= 0; }
 
 private:
   static nsSMILTime kUnresolvedMillis;
 
-  nsSMILTime        mMilliseconds;
+  nsSMILTime mMilliseconds;
   enum {
-    STATE_RESOLVED,
+    STATE_DEFINITE,
     STATE_INDEFINITE,
     STATE_UNRESOLVED
   } mState;
 };
 
 #endif // NS_SMILTIMEVALUE_H_
--- a/content/smil/nsSMILTimeValueSpec.cpp
+++ b/content/smil/nsSMILTimeValueSpec.cpp
@@ -177,17 +177,17 @@ nsSMILTimeValueSpec::HandleNewInterval(n
                                        const nsSMILTimeContainer* aSrcContainer)
 {
   const nsSMILInstanceTime& baseInstance = mParams.mSyncBegin
     ? *aInterval.Begin() : *aInterval.End();
   nsSMILTimeValue newTime =
     ConvertBetweenTimeContainers(baseInstance.Time(), aSrcContainer);
 
   // Apply offset
-  if (newTime.IsResolved()) {
+  if (newTime.IsDefinite()) {
     newTime.SetMillis(newTime.GetMillis() + mParams.mOffset.GetMillis());
   }
 
   // Create the instance time and register it with the interval
   nsRefPtr<nsSMILInstanceTime> newInstance =
     new nsSMILInstanceTime(newTime, nsSMILInstanceTime::SOURCE_SYNCBASE, this,
                            &aInterval);
   mOwner->AddInstanceTime(newInstance, mIsBegin);
@@ -213,17 +213,17 @@ nsSMILTimeValueSpec::HandleChangedInstan
   // time of an active or postactive interval) we just ignore the change.
   if (aInstanceTimeToUpdate.IsFixedTime())
     return;
 
   nsSMILTimeValue updatedTime =
     ConvertBetweenTimeContainers(aBaseTime.Time(), aSrcContainer);
 
   // Apply offset
-  if (updatedTime.IsResolved()) {
+  if (updatedTime.IsDefinite()) {
     updatedTime.SetMillis(updatedTime.GetMillis() +
                           mParams.mOffset.GetMillis());
   }
 
   // The timed element that owns the instance time does the updating so it can
   // re-sort its array of instance times more efficiently
   if (aInstanceTimeToUpdate.Time() != updatedTime || aObjectChanged) {
     mOwner->UpdateInstanceTime(&aInstanceTimeToUpdate, updatedTime, mIsBegin);
@@ -504,17 +504,17 @@ nsSMILTimeValueSpec::CheckAccessKeyEvent
 
 nsSMILTimeValue
 nsSMILTimeValueSpec::ConvertBetweenTimeContainers(
     const nsSMILTimeValue& aSrcTime,
     const nsSMILTimeContainer* aSrcContainer)
 {
   // If the source time is either indefinite or unresolved the result is going
   // to be the same
-  if (!aSrcTime.IsResolved())
+  if (!aSrcTime.IsDefinite())
     return aSrcTime;
 
   // Convert from source time container to our parent time container
   const nsSMILTimeContainer* dstContainer = mOwner->GetTimeContainer();
   if (dstContainer == aSrcContainer)
     return aSrcTime;
 
   // If one of the elements is not attached to a time container then we can't do
@@ -525,13 +525,13 @@ nsSMILTimeValueSpec::ConvertBetweenTimeC
   nsSMILTimeValue docTime =
     aSrcContainer->ContainerToParentTime(aSrcTime.GetMillis());
 
   if (docTime.IsIndefinite())
     // This will happen if the source container is paused and we have a future
     // time. Just return the indefinite time.
     return docTime;
 
-   NS_ABORT_IF_FALSE(docTime.IsResolved(),
-       "ContainerToParentTime gave us an unresolved time");
+  NS_ABORT_IF_FALSE(docTime.IsDefinite(),
+    "ContainerToParentTime gave us an unresolved or indefinite time");
 
   return dstContainer->ParentToContainerTime(docTime.GetMillis());
 }
--- a/content/smil/nsSMILTimedElement.cpp
+++ b/content/smil/nsSMILTimedElement.cpp
@@ -913,31 +913,31 @@ nsSMILTimedElement::SetSimpleDuration(co
   rv = nsSMILParserUtils::ParseClockValue(aDurSpec, &duration,
           nsSMILParserUtils::kClockValueAllowIndefinite, &isMedia);
 
   if (NS_FAILED(rv)) {
     mSimpleDur.SetIndefinite();
     return NS_ERROR_FAILURE;
   }
 
-  if (duration.IsResolved() && duration.GetMillis() == 0L) {
+  if (duration.IsDefinite() && duration.GetMillis() == 0L) {
     mSimpleDur.SetIndefinite();
     return NS_ERROR_FAILURE;
   }
 
   //
   // SVG-specific: "For SVG's animation elements, if "media" is specified, the
   // attribute will be ignored." (SVG 1.1, section 19.2.6)
   //
   if (isMedia)
     duration.SetIndefinite();
 
   // mSimpleDur should never be unresolved. ParseClockValue will either set
   // duration to resolved/indefinite/media or will return a failure code.
-  NS_ASSERTION(duration.IsResolved() || duration.IsIndefinite(),
+  NS_ABORT_IF_FALSE(duration.IsResolved(),
     "Setting unresolved simple duration");
 
   mSimpleDur = duration;
   UpdateCurrentInterval();
 
   return NS_OK;
 }
 
@@ -956,17 +956,17 @@ nsSMILTimedElement::SetMin(const nsAStri
   nsresult rv;
 
   rv = nsSMILParserUtils::ParseClockValue(aMinSpec, &duration, 0, &isMedia);
 
   if (isMedia) {
     duration.SetMillis(0L);
   }
 
-  if (NS_FAILED(rv) || !duration.IsResolved()) {
+  if (NS_FAILED(rv) || !duration.IsDefinite()) {
     mMin.SetMillis(0L);
     return NS_ERROR_FAILURE;
   }
 
   if (duration.GetMillis() < 0L) {
     mMin.SetMillis(0L);
     return NS_ERROR_FAILURE;
   }
@@ -992,22 +992,22 @@ nsSMILTimedElement::SetMax(const nsAStri
   nsresult rv;
 
   rv = nsSMILParserUtils::ParseClockValue(aMaxSpec, &duration,
           nsSMILParserUtils::kClockValueAllowIndefinite, &isMedia);
 
   if (isMedia)
     duration.SetIndefinite();
 
-  if (NS_FAILED(rv) || (!duration.IsResolved() && !duration.IsIndefinite())) {
+  if (NS_FAILED(rv) || !duration.IsResolved()) {
     mMax.SetIndefinite();
     return NS_ERROR_FAILURE;
   }
 
-  if (duration.IsResolved() && duration.GetMillis() <= 0L) {
+  if (duration.IsDefinite() && duration.GetMillis() <= 0L) {
     mMax.SetIndefinite();
     return NS_ERROR_FAILURE;
   }
 
   mMax = duration;
   UpdateCurrentInterval();
 
   return NS_OK;
@@ -1069,17 +1069,17 @@ nsresult
 nsSMILTimedElement::SetRepeatDur(const nsAString& aRepeatDurSpec)
 {
   nsresult rv;
   nsSMILTimeValue duration;
 
   rv = nsSMILParserUtils::ParseClockValue(aRepeatDurSpec, &duration,
           nsSMILParserUtils::kClockValueAllowIndefinite);
 
-  if (NS_FAILED(rv) || (!duration.IsResolved() && !duration.IsIndefinite())) {
+  if (NS_FAILED(rv) || !duration.IsResolved()) {
     mRepeatDur.SetUnresolved();
     return NS_ERROR_FAILURE;
   }
 
   mRepeatDur = duration;
   UpdateCurrentInterval();
 
   return NS_OK;
@@ -1603,18 +1603,18 @@ nsSMILTimedElement::FilterInstanceTimes(
 // http://www.w3.org/TR/2001/REC-smil-animation-20010904/#Timing-BeginEnd-LC-Start
 //
 PRBool
 nsSMILTimedElement::GetNextInterval(const nsSMILInterval* aPrevInterval,
                                     const nsSMILInterval* aReplacedInterval,
                                     const nsSMILInstanceTime* aFixedBeginTime,
                                     nsSMILInterval& aResult) const
 {
-  NS_ABORT_IF_FALSE(!aFixedBeginTime || aFixedBeginTime->Time().IsResolved(),
-      "Unresolved begin time specified for interval start");
+  NS_ABORT_IF_FALSE(!aFixedBeginTime || aFixedBeginTime->Time().IsDefinite(),
+      "Unresolved or indefinite begin time specified for interval start");
   static const nsSMILTimeValue zeroTime(0L);
 
   if (mRestartMode == RESTART_NEVER && aPrevInterval)
     return PR_FALSE;
 
   // Calc starting point
   nsSMILTimeValue beginAfter;
   PRBool prevIntervalWasZeroDur = PR_FALSE;
@@ -1650,23 +1650,23 @@ nsSMILTimedElement::GetNextInterval(cons
       // If we're updating the current interval then skip any begin time that is
       // dependent on the current interval's begin time. e.g.
       //   <animate id="a" begin="b.begin; a.begin+2s"...
       // If b's interval disappears whilst 'a' is in the waiting state the begin
       // time at "a.begin+2s" should be skipped since 'a' never begun.
       do {
         tempBegin =
           GetNextGreaterOrEqual(mBeginInstances, beginAfter, beginPos);
-        if (!tempBegin || !tempBegin->Time().IsResolved()) {
+        if (!tempBegin || !tempBegin->Time().IsDefinite()) {
           return PR_FALSE;
         }
       } while (aReplacedInterval &&
                tempBegin->GetBaseTime() == aReplacedInterval->Begin());
     }
-    NS_ABORT_IF_FALSE(tempBegin && tempBegin->Time().IsResolved() &&
+    NS_ABORT_IF_FALSE(tempBegin && tempBegin->Time().IsDefinite() &&
         tempBegin->Time() >= beginAfter,
         "Got a bad begin time while fetching next interval");
 
     // Calculate end time
     {
       PRInt32 endPos = 0;
       // As above with begin times, avoid creating self-referential loops
       // between instance times by checking that the newly found end instance
@@ -1683,25 +1683,24 @@ nsSMILTimedElement::GetNextInterval(cons
           prevIntervalWasZeroDur) {
         tempEnd = GetNextGreater(mEndInstances, tempBegin->Time(), endPos);
       }
 
       // If all the ends are before the beginning we have a bad interval UNLESS:
       // a) We never had any end attribute to begin with (and hence we should
       //    just use the active duration after allowing for the possibility of
       //    an end instance provided by a DOM call), OR
-      // b) We have no resolved (not incl. indefinite) end instances
-      //    (SMIL only says "if the instance list is empty"--but if we have
-      //    indefinite/unresolved instance times then there must be a good
-      //    reason we haven't used them (since they'll be >= tempBegin) such as
-      //    avoiding creating a self-referential loop. In any case, the interval
-      //    should be allowed to be open.), OR
+      // b) We have no definite end instances (SMIL only says "if the instance
+      //    list is empty"--but if we have indefinite/unresolved instance times
+      //    then there must be a good reason we haven't used them (since they
+      //    will be >= tempBegin) such as avoiding creating a self-referential
+      //    loop. In any case, the interval should be allowed to be open.), OR
       // c) We have end events which leave the interval open-ended.
       PRBool openEndedIntervalOk = mEndSpecs.IsEmpty() ||
-                                   !HaveResolvedEndTimes() ||
+                                   !HaveDefiniteEndTimes() ||
                                    EndHasEventConditions();
       if (!tempEnd && !openEndedIntervalOk)
         return PR_FALSE; // Bad interval
 
       nsSMILTimeValue intervalEnd = tempEnd
                                   ? tempEnd->Time() : nsSMILTimeValue();
       nsSMILTimeValue activeEnd = CalcActiveEnd(tempBegin->Time(), intervalEnd);
 
@@ -1709,17 +1708,17 @@ nsSMILTimedElement::GetNextInterval(cons
         tempEnd = new nsSMILInstanceTime(activeEnd);
       }
     }
     NS_ABORT_IF_FALSE(tempEnd, "Failed to get end point for next interval");
 
     // If we get two zero-length intervals in a row we will potentially have an
     // infinite loop so we break it here by searching for the next begin time
     // greater than tempEnd on the next time around.
-    if (tempEnd->Time().IsResolved() && tempBegin->Time() == tempEnd->Time()) {
+    if (tempEnd->Time().IsDefinite() && tempBegin->Time() == tempEnd->Time()) {
       if (prevIntervalWasZeroDur) {
         beginAfter.SetMillis(tempEnd->Time().GetMillis() + 1);
         prevIntervalWasZeroDur = PR_FALSE;
         continue;
       }
       prevIntervalWasZeroDur = PR_TRUE;
     }
 
@@ -1776,79 +1775,79 @@ nsSMILTimedElement::GetNextGreaterOrEqua
  * @see SMILANIM 3.3.4
  */
 nsSMILTimeValue
 nsSMILTimedElement::CalcActiveEnd(const nsSMILTimeValue& aBegin,
                                   const nsSMILTimeValue& aEnd) const
 {
   nsSMILTimeValue result;
 
-  NS_ABORT_IF_FALSE(mSimpleDur.IsResolved() || mSimpleDur.IsIndefinite(),
+  NS_ABORT_IF_FALSE(mSimpleDur.IsResolved(),
     "Unresolved simple duration in CalcActiveEnd");
-  NS_ABORT_IF_FALSE(aBegin.IsResolved(),
-    "Unresolved begin time in CalcActiveEnd");
+  NS_ABORT_IF_FALSE(aBegin.IsDefinite(),
+    "Indefinite or unresolved begin time in CalcActiveEnd");
 
   if (mRepeatDur.IsIndefinite()) {
     result.SetIndefinite();
   } else {
     result = GetRepeatDuration();
   }
 
-  if (aEnd.IsResolved()) {
+  if (aEnd.IsDefinite()) {
     nsSMILTime activeDur = aEnd.GetMillis() - aBegin.GetMillis();
 
-    if (result.IsResolved()) {
+    if (result.IsDefinite()) {
       result.SetMillis(NS_MIN(result.GetMillis(), activeDur));
     } else {
       result.SetMillis(activeDur);
     }
   }
 
   result = ApplyMinAndMax(result);
 
-  if (result.IsResolved()) {
+  if (result.IsDefinite()) {
     nsSMILTime activeEnd = result.GetMillis() + aBegin.GetMillis();
     result.SetMillis(activeEnd);
   }
 
   return result;
 }
 
 nsSMILTimeValue
 nsSMILTimedElement::GetRepeatDuration() const
 {
   nsSMILTimeValue result;
 
-  if (mRepeatCount.IsDefinite() && mRepeatDur.IsResolved()) {
-    if (mSimpleDur.IsResolved()) {
+  if (mRepeatCount.IsDefinite() && mRepeatDur.IsDefinite()) {
+    if (mSimpleDur.IsDefinite()) {
       nsSMILTime activeDur =
         nsSMILTime(mRepeatCount * double(mSimpleDur.GetMillis()));
       result.SetMillis(NS_MIN(activeDur, mRepeatDur.GetMillis()));
     } else {
       result = mRepeatDur;
     }
-  } else if (mRepeatCount.IsDefinite() && mSimpleDur.IsResolved()) {
+  } else if (mRepeatCount.IsDefinite() && mSimpleDur.IsDefinite()) {
     nsSMILTime activeDur =
       nsSMILTime(mRepeatCount * double(mSimpleDur.GetMillis()));
     result.SetMillis(activeDur);
-  } else if (mRepeatDur.IsResolved()) {
+  } else if (mRepeatDur.IsDefinite()) {
     result = mRepeatDur;
   } else if (mRepeatCount.IsIndefinite()) {
     result.SetIndefinite();
   } else {
     result = mSimpleDur;
   }
 
   return result;
 }
 
 nsSMILTimeValue
 nsSMILTimedElement::ApplyMinAndMax(const nsSMILTimeValue& aDuration) const
 {
-  if (!aDuration.IsResolved() && !aDuration.IsIndefinite()) {
+  if (!aDuration.IsResolved()) {
     return aDuration;
   }
 
   if (mMax < mMin) {
     return aDuration;
   }
 
   nsSMILTimeValue result;
@@ -1866,17 +1865,17 @@ nsSMILTimedElement::ApplyMinAndMax(const
 }
 
 nsSMILTime
 nsSMILTimedElement::ActiveTimeToSimpleTime(nsSMILTime aActiveTime,
                                            PRUint32& aRepeatIteration)
 {
   nsSMILTime result;
 
-  NS_ASSERTION(mSimpleDur.IsResolved() || mSimpleDur.IsIndefinite(),
+  NS_ASSERTION(mSimpleDur.IsResolved(),
       "Unresolved simple duration in ActiveTimeToSimpleTime");
   NS_ASSERTION(aActiveTime >= 0, "Expecting non-negative active time");
   // Note that a negative aActiveTime will give us a negative value for
   // aRepeatIteration, which is bad because aRepeatIteration is unsigned
 
   if (mSimpleDur.IsIndefinite() || mSimpleDur.GetMillis() == 0L) {
     aRepeatIteration = 0;
     result = aActiveTime;
@@ -2030,17 +2029,17 @@ void
 nsSMILTimedElement::SampleFillValue()
 {
   if (mFillMode != FILL_FREEZE || !mClient)
     return;
 
   const nsSMILInterval* prevInterval = GetPreviousInterval();
   NS_ABORT_IF_FALSE(prevInterval,
       "Attempting to sample fill value but there is no previous interval");
-  NS_ABORT_IF_FALSE(prevInterval->End()->Time().IsResolved() &&
+  NS_ABORT_IF_FALSE(prevInterval->End()->Time().IsDefinite() &&
       prevInterval->End()->IsFixedTime(),
       "Attempting to sample fill value but the endpoint of the previous "
       "interval is not resolved and fixed");
 
   nsSMILTime activeTime = prevInterval->End()->Time().GetMillis() -
                           prevInterval->Begin()->Time().GetMillis();
 
   PRUint32 repeatIteration;
@@ -2131,33 +2130,33 @@ nsSMILTimedElement::GetNextMilestone(nsS
     aNextMilestone.mIsEnd = PR_FALSE;
     aNextMilestone.mTime = mCurrentInterval->Begin()->Time().GetMillis();
     return PR_TRUE;
 
   case STATE_ACTIVE:
     {
       // Work out what comes next: the interval end or the next repeat iteration
       nsSMILTimeValue nextRepeat;
-      if (mSeekState == SEEK_NOT_SEEKING && mSimpleDur.IsResolved()) {
+      if (mSeekState == SEEK_NOT_SEEKING && mSimpleDur.IsDefinite()) {
         nextRepeat.SetMillis(mCurrentInterval->Begin()->Time().GetMillis() +
             (mCurrentRepeatIteration + 1) * mSimpleDur.GetMillis());
       }
       nsSMILTimeValue nextMilestone =
         NS_MIN(mCurrentInterval->End()->Time(), nextRepeat);
 
       // Check for an early end before that time
       nsSMILInstanceTime* earlyEnd = CheckForEarlyEnd(nextMilestone);
       if (earlyEnd) {
         aNextMilestone.mIsEnd = PR_TRUE;
         aNextMilestone.mTime = earlyEnd->Time().GetMillis();
         return PR_TRUE;
       }
 
       // Apply the previously calculated milestone
-      if (nextMilestone.IsResolved()) {
+      if (nextMilestone.IsDefinite()) {
         aNextMilestone.mIsEnd = nextMilestone != nextRepeat;
         aNextMilestone.mTime = nextMilestone.GetMillis();
         return PR_TRUE;
       }
 
       return PR_FALSE;
     }
 
@@ -2249,24 +2248,24 @@ const nsSMILInterval*
 nsSMILTimedElement::GetPreviousInterval() const
 {
   return mOldIntervals.IsEmpty()
     ? nsnull
     : mOldIntervals[mOldIntervals.Length()-1].get();
 }
 
 PRBool
-nsSMILTimedElement::HaveResolvedEndTimes() const
+nsSMILTimedElement::HaveDefiniteEndTimes() const
 {
   if (mEndInstances.IsEmpty())
     return PR_FALSE;
 
-  // mEndInstances is sorted so if the first time is not resolved then none of
+  // mEndInstances is sorted so if the first time is not definite then none of
   // them are
-  return mEndInstances[0]->Time().IsResolved();
+  return mEndInstances[0]->Time().IsDefinite();
 }
 
 PRBool
 nsSMILTimedElement::EndHasEventConditions() const
 {
   for (PRUint32 i = 0; i < mEndSpecs.Length(); ++i) {
     if (mEndSpecs[i]->IsEventBased())
       return PR_TRUE;
--- a/content/smil/nsSMILTimedElement.h
+++ b/content/smil/nsSMILTimedElement.h
@@ -520,17 +520,17 @@ protected:
   void              NotifyChangedInterval(nsSMILInterval* aInterval,
                                           PRBool aBeginObjectChanged,
                                           PRBool aEndObjectChanged);
 
   void              FireTimeEventAsync(PRUint32 aMsg, PRInt32 aDetail);
   const nsSMILInstanceTime* GetEffectiveBeginInstance() const;
   const nsSMILInterval* GetPreviousInterval() const;
   PRBool            HasPlayed() const { return !mOldIntervals.IsEmpty(); }
-  PRBool            HaveResolvedEndTimes() const;
+  PRBool            HaveDefiniteEndTimes() const;
   PRBool            EndHasEventConditions() const;
 
   // Reset the current interval by first passing ownership to a temporary
   // variable so that if Unlink() results in us receiving a callback,
   // mCurrentInterval will be nsnull and we will be in a consistent state.
   void ResetCurrentInterval()
   {
     if (mCurrentInterval) {
--- a/content/svg/content/src/SVGMotionSMILAnimationFunction.cpp
+++ b/content/svg/content/src/SVGMotionSMILAnimationFunction.cpp
@@ -378,16 +378,28 @@ SVGMotionSMILAnimationFunction::
 {
   // Call superclass method.
   nsSMILAnimationFunction::CheckValueListDependentAttrs(aNumValues);
 
   // Added behavior: Do checks specific to keyPoints.
   CheckKeyPoints();
 }
 
+PRBool
+SVGMotionSMILAnimationFunction::IsToAnimation() const
+{
+  // Rely on inherited method, but not if we have an <mpath> child or a |path|
+  // attribute, because they'll override any 'to' attr we might have.
+  // NOTE: We can't rely on mPathSourceType, because it might not have been
+  // set to a useful value yet (or it might be stale).
+  return !GetFirstMpathChild(&mAnimationElement->AsElement()) &&
+    !HasAttr(nsGkAtoms::path) &&
+    nsSMILAnimationFunction::IsToAnimation();
+}
+
 void
 SVGMotionSMILAnimationFunction::CheckKeyPoints()
 {
   if (!HasAttr(nsGkAtoms::keyPoints))
     return;
 
   // attribute is ignored for calcMode="paced" (even if it's got errors)
   if (GetCalcMode() == CALC_PACED) {
@@ -480,20 +492,9 @@ SVGMotionSMILAnimationFunction::SetRotat
 void
 SVGMotionSMILAnimationFunction::UnsetRotate()
 {
   mRotateAngle = 0.0f; // default value
   mRotateType = eRotateType_Explicit;
   mHasChanged = PR_TRUE;
 }
 
-PRBool
-SVGMotionSMILAnimationFunction::TreatSingleValueAsStatic() const
-{
-  // <animateMotion> has two more ways that we could be just sampling a single
-  // value -- via path attribute and the <mpath> element, with a path
-  // description that just includes a single "move" command.
-  return (mPathSourceType == ePathSourceType_ValuesAttr ||
-          mPathSourceType == ePathSourceType_PathAttr ||
-          mPathSourceType == ePathSourceType_Mpath);
-}
-
 } // namespace mozilla
--- a/content/svg/content/src/SVGMotionSMILAnimationFunction.h
+++ b/content/svg/content/src/SVGMotionSMILAnimationFunction.h
@@ -80,17 +80,18 @@ protected:
     ePathSourceType_PathAttr,
     ePathSourceType_Mpath
   };
 
   NS_OVERRIDE virtual nsSMILCalcMode GetCalcMode() const;
   NS_OVERRIDE virtual nsresult GetValues(const nsISMILAttr& aSMILAttr,
                                          nsSMILValueArray& aResult);
   NS_OVERRIDE virtual void CheckValueListDependentAttrs(PRUint32 aNumValues);
-  NS_OVERRIDE virtual PRBool TreatSingleValueAsStatic() const;
+
+  NS_OVERRIDE virtual PRBool IsToAnimation() const;
 
   void     CheckKeyPoints();
   nsresult SetKeyPoints(const nsAString& aKeyPoints, nsAttrValue& aResult);
   void     UnsetKeyPoints();
   nsresult SetRotate(const nsAString& aRotate, nsAttrValue& aResult);
   void     UnsetRotate();
 
   // Helpers for GetValues
--- a/content/svg/content/src/nsSVGAnimationElement.cpp
+++ b/content/svg/content/src/nsSVGAnimationElement.cpp
@@ -211,17 +211,17 @@ nsSVGAnimationElement::GetTargetElement(
 
 /* float getStartTime() raises( DOMException ); */
 NS_IMETHODIMP
 nsSVGAnimationElement::GetStartTime(float* retval)
 {
   FlushAnimations();
 
   nsSMILTimeValue startTime = mTimedElement.GetStartTime();
-  if (!startTime.IsResolved())
+  if (!startTime.IsDefinite())
     return NS_ERROR_DOM_INVALID_STATE_ERR;
 
   *retval = float(double(startTime.GetMillis()) / PR_MSEC_PER_SEC);
 
   return NS_OK;
 }
 
 /* float getCurrentTime(); */
@@ -241,17 +241,17 @@ nsSVGAnimationElement::GetCurrentTime(fl
 
 /* float getSimpleDuration() raises( DOMException ); */
 NS_IMETHODIMP
 nsSVGAnimationElement::GetSimpleDuration(float* retval)
 {
   // Not necessary to call FlushAnimations() for this
 
   nsSMILTimeValue simpleDur = mTimedElement.GetSimpleDuration();
-  if (!simpleDur.IsResolved()) {
+  if (!simpleDur.IsDefinite()) {
     *retval = 0.f;
     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
   }
 
   *retval = float(double(simpleDur.GetMillis()) / PR_MSEC_PER_SEC);
   return NS_OK;
 }
 
--- a/content/svg/content/src/nsSVGFilters.cpp
+++ b/content/svg/content/src/nsSVGFilters.cpp
@@ -5430,17 +5430,17 @@ nsSVGFEImageElement::LoadSVGImage(PRBool
   nsAutoString href;
   mStringAttributes[HREF].GetAnimValue(href, this);
   href.Trim(" \t\n\r");
 
   if (baseURI && !href.IsEmpty())
     NS_MakeAbsoluteURI(href, href, baseURI);
 
   // Make sure we don't get in a recursive death-spiral
-  nsIDocument* doc = GetOurDocument();
+  nsIDocument* doc = GetOwnerDoc();
   if (doc) {
     nsCOMPtr<nsIURI> hrefAsURI;
     if (NS_SUCCEEDED(StringToURI(href, doc, getter_AddRefs(hrefAsURI)))) {
       PRBool isEqual;
       if (NS_SUCCEEDED(hrefAsURI->Equals(baseURI, &isEqual)) && isEqual) {
         // Image URI matches our URI exactly! Bail out.
         return NS_OK;
       }
--- a/content/xbl/crashtests/crashtests.list
+++ b/content/xbl/crashtests/crashtests.list
@@ -26,12 +26,12 @@ load 421997-1.xhtml
 load 432813-1.xhtml
 load 454820-1.html
 load 460665-1.xhtml
 load 463511-1.xhtml
 load 464863-1.xhtml
 load 472260-1.xhtml
 load 477878-1.html
 load 492978-1.xul
-load 493123-1.xhtml
+asserts-if(Android,2) load 493123-1.xhtml
 load 495354-1.xhtml
 load 507628-1.xhtml
 load 507991-1.xhtml
--- a/docshell/base/crashtests/crashtests.list
+++ b/docshell/base/crashtests/crashtests.list
@@ -1,13 +1,13 @@
 load 40929-1.html
 load 369126-1.html
 load 403574-1.xhtml
 load 430124-1.html
 load 430628-1.html
 load 432114-1.html
 load 432114-2.html
-load 436900-1.html
-asserts(0-2) load 436900-2.html # bug 566159
+asserts-if(Android,2) load 436900-1.html
+asserts(0-3) load 436900-2.html # bug 566159
 load 500328-1.html
 load 514779-1.xhtml
 load 614499-1.html
 load 678872-1.html
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -1,9 +1,9 @@
-load 90613-1.html
+asserts-if(Android,1) load 90613-1.html
 load 244933-1.html
 load 275912-1.html
 load 327571-1.html
 load 327695-1.html
 load 329481-1.xhtml
 load 338674-1.xhtml
 load 346381-1.html
 load 359432-1.xhtml
@@ -16,16 +16,16 @@ load 375399-1.html
 load 404869-1.xul
 load 417852-1.html
 load 462947.html
 load 439206-1.html
 load 473284.xul
 load 499006-1.html
 load 499006-2.html
 load 502617.html
-asserts(1) load 504224.html # bug 564098
+asserts(1-2) load 504224.html # bug 564098
 load 603531.html
 load 601247.html
 load 609560-1.xhtml
 load 612018-1.html
 load 637116.html
 load 666869.html
 load 675621-1.html
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -660,17 +660,18 @@ static nsDOMClassInfoData sClassInfoData
                            (DOM_DEFAULT_SCRIPTABLE_FLAGS &
                             ~nsIXPCScriptable::ALLOW_PROP_MODS_TO_PROTOTYPE))
 
   NS_DEFINE_CLASSINFO_DATA(CaretPosition, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(Navigator, nsNavigatorSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS |
-                           nsIXPCScriptable::WANT_PRECREATE)
+                           nsIXPCScriptable::WANT_PRECREATE |
+                           nsIXPCScriptable::WANT_NEWRESOLVE)
   NS_DEFINE_CLASSINFO_DATA(Plugin, nsPluginSH,
                            ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(PluginArray, nsPluginArraySH,
                            ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MimeType, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MimeTypeArray, nsMimeTypeArraySH,
                            ARRAY_SCRIPTABLE_FLAGS)
@@ -2009,33 +2010,35 @@ CutPrefix(const char *aName) {
 
   return aName;
 }
 
 // static
 nsresult
 nsDOMClassInfo::RegisterClassName(PRInt32 aClassInfoID)
 {
-  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  nsScriptNameSpaceManager *nameSpaceManager =
+    nsJSRuntime::GetNameSpaceManager();
   NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
 
   nameSpaceManager->RegisterClassName(sClassInfoData[aClassInfoID].mName,
                                       aClassInfoID,
                                       sClassInfoData[aClassInfoID].mChromeOnly,
                                       sClassInfoData[aClassInfoID].mDisabled,
                                       &sClassInfoData[aClassInfoID].mNameUTF16);
 
   return NS_OK;
 }
 
 // static
 nsresult
 nsDOMClassInfo::RegisterClassProtos(PRInt32 aClassInfoID)
 {
-  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  nsScriptNameSpaceManager *nameSpaceManager =
+    nsJSRuntime::GetNameSpaceManager();
   NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
   PRBool found_old;
 
   const nsIID *primary_iid = sClassInfoData[aClassInfoID].mProtoChainInterface;
 
   if (!primary_iid || primary_iid == &NS_GET_IID(nsISupports)) {
     return NS_OK;
   }
@@ -2077,17 +2080,18 @@ nsDOMClassInfo::RegisterClassProtos(PRIn
 
   return NS_OK;
 }
 
 // static
 nsresult
 nsDOMClassInfo::RegisterExternalClasses()
 {
-  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  nsScriptNameSpaceManager *nameSpaceManager =
+    nsJSRuntime::GetNameSpaceManager();
   NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
 
   nsCOMPtr<nsIComponentRegistrar> registrar;
   nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(registrar));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsICategoryManager> cm =
     do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
@@ -5526,17 +5530,18 @@ private:
     return nameStruct;
   }
 
   static nsresult GetNameStruct(const nsAString& aName,
                                 const nsGlobalNameStruct **aNameStruct)
   {
     *aNameStruct = nsnull;
 
-    nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+    nsScriptNameSpaceManager *nameSpaceManager =
+      nsJSRuntime::GetNameSpaceManager();
     if (!nameSpaceManager) {
       NS_ERROR("Can't get namespace manager.");
       return NS_ERROR_UNEXPECTED;
     }
 
     nameSpaceManager->LookupName(aName, aNameStruct);
 
     // Return NS_OK here, aName just isn't a DOM class but nothing failed.
@@ -5734,17 +5739,18 @@ nsDOMConstructor::HasInstance(nsIXPConne
   NS_ENSURE_TRUE(class_name_struct, NS_ERROR_FAILURE);
 
   if (name_struct == class_name_struct) {
     *bp = JS_TRUE;
 
     return NS_OK;
   }
 
-  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  nsScriptNameSpaceManager *nameSpaceManager =
+    nsJSRuntime::GetNameSpaceManager();
   NS_ASSERTION(nameSpaceManager, "Can't get namespace manager?");
 
   const nsIID *class_iid;
   if (class_name_struct->mType == nsGlobalNameStruct::eTypeInterface ||
       class_name_struct->mType == nsGlobalNameStruct::eTypeClassProto) {
     class_iid = &class_name_struct->mIID;
   } else if (class_name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
     class_iid =
@@ -6087,17 +6093,18 @@ ResolvePrototype(nsIXPConnect *aXPConnec
 
 // static
 nsresult
 nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
                           JSObject *obj, jsid id, PRBool *did_resolve)
 {
   *did_resolve = PR_FALSE;
 
-  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  nsScriptNameSpaceManager *nameSpaceManager =
+    nsJSRuntime::GetNameSpaceManager();
   NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
 
   nsDependentJSString name(id);
 
   const nsGlobalNameStruct *name_struct = nsnull;
   const PRUnichar *class_name = nsnull;
 
   nameSpaceManager->LookupName(name, &name_struct, &class_name);
@@ -7015,16 +7022,87 @@ nsLocationSH::PreCreate(nsISupports *nat
     return NS_ERROR_UNEXPECTED;
   }
 
   *parentObj = sgo->GetGlobalJSObject();
   return NS_OK;
 }
 
 // DOM Navigator helper
+
+NS_IMETHODIMP
+nsNavigatorSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
+                          JSObject *obj, jsid id, PRUint32 flags,
+                          JSObject **objp, PRBool *_retval)
+{
+  if (!JSID_IS_STRING(id) || (flags & JSRESOLVE_ASSIGNING)) {
+    return NS_OK;
+  }
+
+  nsScriptNameSpaceManager *nameSpaceManager =
+    nsJSRuntime::GetNameSpaceManager();
+  NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
+
+  nsDependentJSString name(id);
+
+  const nsGlobalNameStruct *name_struct = nsnull;
+
+  nameSpaceManager->LookupNavigatorName(name, &name_struct);
+
+  if (!name_struct) {
+    return NS_OK;
+  }
+  NS_ASSERTION(name_struct->mType == nsGlobalNameStruct::eTypeNavigatorProperty,
+               "unexpected type");
+
+  nsresult rv = NS_OK;
+
+  nsCOMPtr<nsISupports> native(do_CreateInstance(name_struct->mCID, &rv));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  jsval prop_val = JSVAL_VOID; // Property value.
+
+  nsCOMPtr<nsIDOMGlobalPropertyInitializer> gpi(do_QueryInterface(native));
+
+  if (gpi) {
+    JSObject *global = JS_GetGlobalForObject(cx, obj);
+
+    nsISupports *globalNative = XPConnect()->GetNativeOfWrapper(cx, global);
+    nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(globalNative);
+
+    if (!window) {
+      return NS_ERROR_UNEXPECTED;
+    }
+
+    rv = gpi->Init(window, &prop_val);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  if (JSVAL_IS_PRIMITIVE(prop_val)) {
+    nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+    rv = WrapNative(cx, obj, native, PR_TRUE, &prop_val,
+                    getter_AddRefs(holder));
+
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  if (!JS_WrapValue(cx, &prop_val)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  JSBool ok = ::JS_DefinePropertyById(cx, obj, id, prop_val, nsnull, nsnull,
+                                      JSPROP_ENUMERATE);
+
+  *_retval = PR_TRUE;
+  *objp = obj;
+
+  return ok ? NS_OK : NS_ERROR_FAILURE;
+}
+
+// static
 nsresult
 nsNavigatorSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
                          JSObject *globalObj, JSObject **parentObj)
 {
   // window.navigator is persisted across document transitions if
   // we're loading a page from the same origin. Because of that we
   // need to parent the navigator wrapper at the outer window to avoid
   // holding on to the inner window where the navigator was initially
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -476,16 +476,19 @@ protected:
 
   virtual ~nsNavigatorSH()
   {
   }
 
 public:
   NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
                        JSObject *globalObj, JSObject **parentObj);
+  NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
+                        JSObject *obj, jsid id, PRUint32 flags,
+                        JSObject **objp, PRBool *_retval);
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsNavigatorSH(aData);
   }
 };
 
 
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -532,16 +532,20 @@ public:
                                     const nsAString &aPopupWindowName,
                                     const nsAString &aPopupWindowFeatures);
 
   virtual PRUint32 GetSerial() {
     return mSerial;
   }
 
   static nsGlobalWindow* GetOuterWindowWithId(PRUint64 aWindowID) {
+    if (!sWindowsById) {
+      return nsnull;
+    }
+
     nsGlobalWindow* outerWindow = sWindowsById->Get(aWindowID);
     return outerWindow && !outerWindow->IsInnerWindow() ? outerWindow : nsnull;
   }
 
   static nsGlobalWindow* GetInnerWindowWithId(PRUint64 aInnerWindowID) {
     if (!sWindowsById) {
       return nsnull;
     }
--- a/dom/base/nsIScriptNameSpaceManager.h
+++ b/dom/base/nsIScriptNameSpaceManager.h
@@ -46,16 +46,19 @@
 
 #define JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY \
   "JavaScript-global-property"
 
 // a global property that is only accessible to privileged script 
 #define JAVASCRIPT_GLOBAL_PRIVILEGED_PROPERTY_CATEGORY \
   "JavaScript-global-privileged-property"
 
+#define JAVASCRIPT_NAVIGATOR_PROPERTY_CATEGORY \
+  "JavaScript-navigator-property"
+
 #define JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY \
   "JavaScript-global-static-nameset"
 
 #define JAVASCRIPT_GLOBAL_DYNAMIC_NAMESET_CATEGORY \
   "JavaScript-global-dynamic-nameset"
 
 #define JAVASCRIPT_DOM_CLASS \
   "JavaScript-DOM-class"
--- a/dom/base/nsScriptNameSpaceManager.cpp
+++ b/dom/base/nsScriptNameSpaceManager.cpp
@@ -143,28 +143,29 @@ nsScriptNameSpaceManager::nsScriptNameSp
   MOZ_COUNT_CTOR(nsScriptNameSpaceManager);
 }
 
 nsScriptNameSpaceManager::~nsScriptNameSpaceManager()
 {
   if (mIsInitialized) {
     // Destroy the hash
     PL_DHashTableFinish(&mGlobalNames);
+    PL_DHashTableFinish(&mNavigatorNames);
   }
   MOZ_COUNT_DTOR(nsScriptNameSpaceManager);
 }
 
 nsGlobalNameStruct *
-nsScriptNameSpaceManager::AddToHash(const char *aKey,
+nsScriptNameSpaceManager::AddToHash(PLDHashTable *aTable, const char *aKey,
                                     const PRUnichar **aClassName)
 {
   NS_ConvertASCIItoUTF16 key(aKey);
   GlobalNameMapEntry *entry =
     static_cast<GlobalNameMapEntry *>
-               (PL_DHashTableOperate(&mGlobalNames, &key, PL_DHASH_ADD));
+               (PL_DHashTableOperate(aTable, &key, PL_DHASH_ADD));
 
   if (!entry) {
     return nsnull;
   }
 
   if (aClassName) {
     *aClassName = entry->mKey.get();
   }
@@ -366,17 +367,17 @@ nsScriptNameSpaceManager::RegisterExtern
 
 nsresult
 nsScriptNameSpaceManager::RegisterInterface(const char* aIfName,
                                             const nsIID *aIfIID,
                                             PRBool* aFoundOld)
 {
   *aFoundOld = PR_FALSE;
 
-  nsGlobalNameStruct *s = AddToHash(aIfName);
+  nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aIfName);
   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
   if (s->mType != nsGlobalNameStruct::eTypeNotInitialized) {
     *aFoundOld = PR_TRUE;
 
     return NS_OK;
   }
 
@@ -403,16 +404,25 @@ nsScriptNameSpaceManager::Init()
     GlobalNameHashInitEntry
   };
 
   mIsInitialized = PL_DHashTableInit(&mGlobalNames, &hash_table_ops, nsnull,
                                      sizeof(GlobalNameMapEntry), 
                                      GLOBALNAME_HASHTABLE_INITIAL_SIZE);
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_OUT_OF_MEMORY);
 
+  mIsInitialized = PL_DHashTableInit(&mNavigatorNames, &hash_table_ops, nsnull,
+                                     sizeof(GlobalNameMapEntry), 
+                                     GLOBALNAME_HASHTABLE_INITIAL_SIZE);
+  if (!mIsInitialized) {
+    PL_DHashTableFinish(&mGlobalNames);
+
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
   nsresult rv = NS_OK;
 
   rv = FillHashWithDOMInterfaces();
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsICategoryManager> cm =
     do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -427,16 +437,19 @@ nsScriptNameSpaceManager::Init()
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = FillHash(cm, JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = FillHash(cm, JAVASCRIPT_GLOBAL_DYNAMIC_NAMESET_CATEGORY);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  rv = FillHash(cm, JAVASCRIPT_NAVIGATOR_PROPERTY_CATEGORY);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   // Initial filling of the has table has been done.
   // Now, listen for changes.
   nsCOMPtr<nsIObserverService> serv = 
     do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
 
   if (serv) {
     serv->AddObserver(this, NS_XPCOM_CATEGORY_ENTRY_ADDED_OBSERVER_ID, PR_TRUE);
   }
@@ -505,27 +518,46 @@ nsScriptNameSpaceManager::LookupName(con
       *aClassName = nsnull;
     }
   }
 
   return NS_OK;
 }
 
 nsresult
+nsScriptNameSpaceManager::LookupNavigatorName(const nsAString& aName,
+                                              const nsGlobalNameStruct **aNameStruct)
+{
+  GlobalNameMapEntry *entry =
+    static_cast<GlobalNameMapEntry *>
+               (PL_DHashTableOperate(&mNavigatorNames, &aName,
+                                     PL_DHASH_LOOKUP));
+
+  if (PL_DHASH_ENTRY_IS_BUSY(entry) &&
+      !((&entry->mGlobalName)->mDisabled)) {
+    *aNameStruct = &entry->mGlobalName;
+  } else {
+    *aNameStruct = nsnull;
+  }
+
+  return NS_OK;
+}
+
+nsresult
 nsScriptNameSpaceManager::RegisterClassName(const char *aClassName,
                                             PRInt32 aDOMClassInfoID,
                                             PRBool aPrivileged,
                                             PRBool aDisabled,
                                             const PRUnichar **aResult)
 {
   if (!nsCRT::IsAscii(aClassName)) {
     NS_ERROR("Trying to register a non-ASCII class name");
     return NS_OK;
   }
-  nsGlobalNameStruct *s = AddToHash(aClassName, aResult);
+  nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aClassName, aResult);
   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
   if (s->mType == nsGlobalNameStruct::eTypeClassConstructor) {
     return NS_OK;
   }
 
   // If a external constructor is already defined with aClassName we
   // won't overwrite it.
@@ -550,17 +582,17 @@ nsresult
 nsScriptNameSpaceManager::RegisterClassProto(const char *aClassName,
                                              const nsIID *aConstructorProtoIID,
                                              PRBool *aFoundOld)
 {
   NS_ENSURE_ARG_POINTER(aConstructorProtoIID);
 
   *aFoundOld = PR_FALSE;
 
-  nsGlobalNameStruct *s = AddToHash(aClassName);
+  nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aClassName);
   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
   if (s->mType != nsGlobalNameStruct::eTypeNotInitialized &&
       s->mType != nsGlobalNameStruct::eTypeInterface) {
     *aFoundOld = PR_TRUE;
 
     return NS_OK;
   }
@@ -570,17 +602,17 @@ nsScriptNameSpaceManager::RegisterClassP
 
   return NS_OK;
 }
 
 nsresult
 nsScriptNameSpaceManager::RegisterExternalClassName(const char *aClassName,
                                                     nsCID& aCID)
 {
-  nsGlobalNameStruct *s = AddToHash(aClassName);
+  nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aClassName);
   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
   // If an external constructor is already defined with aClassName we
   // won't overwrite it.
 
   if (s->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
     return NS_OK;
   }
@@ -600,17 +632,17 @@ nsScriptNameSpaceManager::RegisterDOMCID
                                             nsDOMClassInfoExternalConstructorFnc aConstructorFptr,
                                             const nsIID *aProtoChainInterface,
                                             const nsIID **aInterfaces,
                                             PRUint32 aScriptableFlags,
                                             PRBool aHasClassInterface,
                                             const nsCID *aConstructorCID)
 {
   const PRUnichar* className;
-  nsGlobalNameStruct *s = AddToHash(aName, &className);
+  nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aName, &className);
   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
   // If an external constructor is already defined with aClassName we
   // won't overwrite it.
 
   if (s->mType == nsGlobalNameStruct::eTypeClassConstructor ||
       s->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
     return NS_OK;
@@ -652,16 +684,18 @@ nsScriptNameSpaceManager::AddCategoryEnt
   // Observe() but this way, we have only one place to update and this is
   // not performance sensitive.
   nsGlobalNameStruct::nametype type;
   if (strcmp(aCategory, JAVASCRIPT_GLOBAL_CONSTRUCTOR_CATEGORY) == 0) {
     type = nsGlobalNameStruct::eTypeExternalConstructor;
   } else if (strcmp(aCategory, JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY) == 0 ||
              strcmp(aCategory, JAVASCRIPT_GLOBAL_PRIVILEGED_PROPERTY_CATEGORY) == 0) {
     type = nsGlobalNameStruct::eTypeProperty;
+  } else if (strcmp(aCategory, JAVASCRIPT_NAVIGATOR_PROPERTY_CATEGORY) == 0) {
+    type = nsGlobalNameStruct::eTypeNavigatorProperty;
   } else if (strcmp(aCategory, JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY) == 0) {
     type = nsGlobalNameStruct::eTypeStaticNameSet;
   } else if (strcmp(aCategory, JAVASCRIPT_GLOBAL_DYNAMIC_NAMESET_CATEGORY) == 0) {
     type = nsGlobalNameStruct::eTypeDynamicNameSet;
   } else {
     return NS_OK;
   }
 
@@ -699,17 +733,17 @@ nsScriptNameSpaceManager::AddCategoryEnt
   nsMemory::Free(cidPtr);
 
   if (type == nsGlobalNameStruct::eTypeExternalConstructor) {
     nsXPIDLCString constructorProto;
     rv = aCategoryManager->GetCategoryEntry(JAVASCRIPT_GLOBAL_CONSTRUCTOR_PROTO_ALIAS_CATEGORY,
                                             categoryEntry.get(),
                                             getter_Copies(constructorProto));
     if (NS_SUCCEEDED(rv)) {
-      nsGlobalNameStruct *s = AddToHash(categoryEntry.get());
+      nsGlobalNameStruct *s = AddToHash(&mGlobalNames, categoryEntry.get());
       NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
       if (s->mType == nsGlobalNameStruct::eTypeNotInitialized) {
         s->mAlias = new nsGlobalNameStruct::ConstructorAlias;
         s->mType = nsGlobalNameStruct::eTypeExternalConstructorAlias;
         s->mChromeOnly = PR_FALSE;
         s->mAlias->mCID = cid;
         AppendASCIItoUTF16(constructorProto, s->mAlias->mProtoName);
@@ -717,17 +751,24 @@ nsScriptNameSpaceManager::AddCategoryEnt
       } else {
         NS_WARNING("Global script name not overwritten!");
       }
 
       return NS_OK;
     }
   }
 
-  nsGlobalNameStruct *s = AddToHash(categoryEntry.get());
+  PLDHashTable *table;
+  if (type == nsGlobalNameStruct::eTypeNavigatorProperty) {
+    table = &mNavigatorNames;
+  } else {
+    table = &mGlobalNames;
+  }
+
+  nsGlobalNameStruct *s = AddToHash(table, categoryEntry.get());
   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
   if (s->mType == nsGlobalNameStruct::eTypeNotInitialized) {
     s->mType = type;
     s->mCID = cid;
     s->mChromeOnly =
       strcmp(aCategory, JAVASCRIPT_GLOBAL_PRIVILEGED_PROPERTY_CATEGORY) == 0;
   } else {
--- a/dom/base/nsScriptNameSpaceManager.h
+++ b/dom/base/nsScriptNameSpaceManager.h
@@ -70,16 +70,17 @@ struct nsGlobalNameStruct
     nsString mProtoName;
     nsGlobalNameStruct* mProto;    
   };
 
   enum nametype {
     eTypeNotInitialized,
     eTypeInterface,
     eTypeProperty,
+    eTypeNavigatorProperty,
     eTypeExternalConstructor,
     eTypeStaticNameSet,
     eTypeDynamicNameSet,
     eTypeClassConstructor,
     eTypeClassProto,
     eTypeExternalClassInfoCreator,
     eTypeExternalClassInfo,
     eTypeExternalConstructorAlias
@@ -123,16 +124,22 @@ public:
   // Returns a nsGlobalNameStruct for aName, or null if one is not
   // found. The returned nsGlobalNameStruct is only guaranteed to be
   // valid until the next call to any of the methods in this class.
   // It also returns a pointer to the string buffer of the classname
   // in the nsGlobalNameStruct.
   nsresult LookupName(const nsAString& aName,
                       const nsGlobalNameStruct **aNameStruct,
                       const PRUnichar **aClassName = nsnull);
+  // Returns a nsGlobalNameStruct for the navigator property aName, or
+  // null if one is not found. The returned nsGlobalNameStruct is only
+  // guaranteed to be valid until the next call to any of the methods
+  // in this class.
+  nsresult LookupNavigatorName(const nsAString& aName,
+                               const nsGlobalNameStruct **aNameStruct);
 
   nsresult RegisterClassName(const char *aClassName,
                              PRInt32 aDOMClassInfoID,
                              PRBool aPrivileged,
                              PRBool aDisabled,
                              const PRUnichar **aResult);
 
   nsresult RegisterClassProto(const char *aClassName,
@@ -156,17 +163,17 @@ public:
 
   nsGlobalNameStruct* GetConstructorProto(const nsGlobalNameStruct* aStruct);
 
 protected:
   // Adds a new entry to the hash and returns the nsGlobalNameStruct
   // that aKey will be mapped to. If mType in the returned
   // nsGlobalNameStruct is != eTypeNotInitialized, an entry for aKey
   // already existed.
-  nsGlobalNameStruct *AddToHash(const char *aKey,
+  nsGlobalNameStruct *AddToHash(PLDHashTable *aTable, const char *aKey,
                                 const PRUnichar **aClassName = nsnull);
 
   nsresult FillHash(nsICategoryManager *aCategoryManager,
                     const char *aCategory);
   nsresult FillHashWithDOMInterfaces();
   nsresult RegisterInterface(const char* aIfName,
                              const nsIID *aIfIID,
                              PRBool* aFoundOld);
@@ -179,16 +186,15 @@ protected:
    * @aCategoryManager Instance of the category manager service.
    * @aCategory        Category where the entry comes from.
    * @aEntry           The entry that should be added.
    */
   nsresult AddCategoryEntryToHash(nsICategoryManager* aCategoryManager,
                                   const char* aCategory,
                                   nsISupports* aEntry);
 
-  // Inline PLDHashTable, init with PL_DHashTableInit() and delete
-  // with PL_DHashTableFinish().
   PLDHashTable mGlobalNames;
+  PLDHashTable mNavigatorNames;
 
   PRPackedBool mIsInitialized;
 };
 
 #endif /* nsScriptNameSpaceManager_h__ */
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -980,17 +980,17 @@ PluginInstanceChild::AnswerNPP_SetWindow
     mWsInfo.colormap = aWindow.colormap;
     if (!XVisualIDToInfo(mWsInfo.display, aWindow.visualID,
                          &mWsInfo.visual, &mWsInfo.depth))
         return false;
 
 #ifdef MOZ_WIDGET_GTK2
     if (gtk_check_version(2,18,7) != NULL) { // older
         if (aWindow.type == NPWindowTypeWindow) {
-            GdkWindow* socket_window = gdk_window_lookup(aWindow.window);
+            GdkWindow* socket_window = gdk_window_lookup(static_cast<GdkNativeWindow>(aWindow.window));
             if (socket_window) {
                 // A GdkWindow for the socket already exists.  Need to
                 // workaround https://bugzilla.gnome.org/show_bug.cgi?id=607061
                 // See wrap_gtk_plug_embedded in PluginModuleChild.cpp.
                 g_object_set_data(G_OBJECT(socket_window),
                                   "moz-existed-before-set-window",
                                   GUINT_TO_POINTER(1));
             }
@@ -1034,17 +1034,17 @@ PluginInstanceChild::AnswerNPP_SetWindow
               aWindow.height == 0) {
             // Skip SetWindow call for hidden QuickTime plugins
             return true;
           }
 
           if (!CreatePluginWindow())
               return false;
 
-          ReparentPluginWindow((HWND)aWindow.window);
+          ReparentPluginWindow(reinterpret_cast<HWND>(aWindow.window));
           SizePluginWindow(aWindow.width, aWindow.height);
 
           mWindow.window = (void*)mPluginWindowHWND;
           mWindow.x = aWindow.x;
           mWindow.y = aWindow.y;
           mWindow.width = aWindow.width;
           mWindow.height = aWindow.height;
           mWindow.type = aWindow.type;
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -599,17 +599,17 @@ PluginInstanceParent::RecvShow(const NPR
     return true;
 }
 
 nsresult
 PluginInstanceParent::AsyncSetWindow(NPWindow* aWindow)
 {
     NPRemoteWindow window;
     mWindowType = aWindow->type;
-    window.window = reinterpret_cast<uintptr_t>(aWindow->window);
+    window.window = reinterpret_cast<uint64_t>(aWindow->window);
     window.x = aWindow->x;
     window.y = aWindow->y;
     window.width = aWindow->width;
     window.height = aWindow->height;
     window.clipRect = aWindow->clipRect;
     window.type = aWindow->type;
     if (!SendAsyncSetWindow(gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType(),
                             window))
@@ -906,25 +906,25 @@ PluginInstanceParent::NPP_SetWindow(cons
         // SharedSurfaceSetWindow will take care of NPRemoteWindow.
         if (!SharedSurfaceSetWindow(aWindow, window)) {
           return NPERR_OUT_OF_MEMORY_ERROR;
         }
     }
     else {
         SubclassPluginWindow(reinterpret_cast<HWND>(aWindow->window));
 
-        window.window = reinterpret_cast<uintptr_t>(aWindow->window);
+        window.window = reinterpret_cast<uint64_t>(aWindow->window);
         window.x = aWindow->x;
         window.y = aWindow->y;
         window.width = aWindow->width;
         window.height = aWindow->height;
         window.type = aWindow->type;
     }
 #else
-    window.window = reinterpret_cast<unsigned long>(aWindow->window);
+    window.window = reinterpret_cast<uint64_t>(aWindow->window);
     window.x = aWindow->x;
     window.y = aWindow->y;
     window.width = aWindow->width;
     window.height = aWindow->height;
     window.clipRect = aWindow->clipRect; // MacOS specific
     window.type = aWindow->type;
 #endif
 
--- a/dom/plugins/ipc/PluginMessageUtils.h
+++ b/dom/plugins/ipc/PluginMessageUtils.h
@@ -105,17 +105,17 @@ struct IPCByteRange
 };  
 
 typedef std::vector<IPCByteRange> IPCByteRanges;
 
 typedef nsCString Buffer;
 
 struct NPRemoteWindow
 {
-  unsigned long window;
+  uint64_t window;
   int32_t x;
   int32_t y;
   uint32_t width;
   uint32_t height;
   NPRect clipRect;
   NPWindowType type;
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
   VisualID visualID;
@@ -358,17 +358,17 @@ struct ParamTraits<NPWindowType>
 
 template <>
 struct ParamTraits<mozilla::plugins::NPRemoteWindow>
 {
   typedef mozilla::plugins::NPRemoteWindow paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
-    aMsg->WriteULong(aParam.window);
+    aMsg->WriteUInt64(aParam.window);
     WriteParam(aMsg, aParam.x);
     WriteParam(aMsg, aParam.y);
     WriteParam(aMsg, aParam.width);
     WriteParam(aMsg, aParam.height);
     WriteParam(aMsg, aParam.clipRect);
     WriteParam(aMsg, aParam.type);
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
     aMsg->WriteULong(aParam.visualID);
@@ -376,22 +376,22 @@ struct ParamTraits<mozilla::plugins::NPR
 #endif
 #if defined(XP_WIN)
     WriteParam(aMsg, aParam.surfaceHandle);
 #endif
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
-    unsigned long window;
+    uint64_t window;
     int32_t x, y;
     uint32_t width, height;
     NPRect clipRect;
     NPWindowType type;
-    if (!(aMsg->ReadULong(aIter, &window) &&
+    if (!(aMsg->ReadUInt64(aIter, &window) &&
           ReadParam(aMsg, aIter, &x) &&
           ReadParam(aMsg, aIter, &y) &&
           ReadParam(aMsg, aIter, &width) &&
           ReadParam(aMsg, aIter, &height) &&
           ReadParam(aMsg, aIter, &clipRect) &&
           ReadParam(aMsg, aIter, &type)))
       return false;
 
--- a/dom/tests/mochitest/bugs/Makefile.in
+++ b/dom/tests/mochitest/bugs/Makefile.in
@@ -132,16 +132,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug593174.html \
 		file_bug593174_1.html \
 		file_bug593174_2.html \
 		test_bug612267.html \
 		test_bug617296.html \
 		test_bug620947.html \
 		test_bug622361.html \
 		test_bug633133.html \
+		test_bug641552.html \
 		test_bug642026.html \
 		test_bug648465.html \
 		test_bug654137.html \
 		test_window_bar.html \
 		file_window_bar.html \
 		test_resize_move_windows.html \
 		test_devicemotion_multiple_listeners.html \
 		devicemotion_outer.html \
--- a/dom/tests/mochitest/bugs/test_bug597809.html
+++ b/dom/tests/mochitest/bugs/test_bug597809.html
@@ -13,24 +13,21 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"></p>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 597809 **/
 
 SimpleTest.waitForExplicitFinish();
 
-netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-var cm = Components.classes["@mozilla.org/categorymanager;1"]
-                   .getService(Components.interfaces.nsICategoryManager);
-cm.addCategoryEntry("JavaScript-global-property", "testSNSM", "@mozilla.org/embedcomp/prompt-service;1",
+SpecialPowers.addCategoryEntry("JavaScript-global-property", "testSNSM", "@mozilla.org/embedcomp/prompt-service;1",
                     false, true);
 
 SimpleTest.executeSoon(function () {
-  ok(window.testSNSM, "testSNSM should returns an object");
+  ok(window.testSNSM, "testSNSM should return an object");
   SimpleTest.finish();
 });
 
 
 </script>
 </pre>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/test_bug641552.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=641552
+-->
+<head>
+  <title>Test for Bug 641552</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=641552">Mozilla Bug 641552</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 641552 **/
+
+SimpleTest.waitForExplicitFinish();
+
+SpecialPowers.addCategoryEntry("JavaScript-global-property", "randomname", "@mozilla.org/embedcomp/prompt-service;1",
+                    false, true);
+
+SpecialPowers.addCategoryEntry("JavaScript-navigator-property", "randomname1", "@mozilla.org/embedcomp/prompt-service;1",
+                    false, true);
+
+SpecialPowers.addCategoryEntry("JavaScript-navigator-property", "randomname2", "@mozilla.org/embedcomp/prompt-service;1",
+                    false, true);
+
+SimpleTest.executeSoon(function () {
+  ok(window.randomname, "window.randomname should return an object");
+  is(typeof(window.navigator.randomname1), 'object', "navigator.randomname1 should return an object");
+  is(typeof(window.navigator.randomname2), 'object', "navigator.randomname1 should return an object");
+  SimpleTest.finish();
+});
+
+
+</script>
+</pre>
+</body>
+</html>
--- a/editor/composer/src/crashtests/crashtests.list
+++ b/editor/composer/src/crashtests/crashtests.list
@@ -1,6 +1,6 @@
-load 351236-1.html
+asserts-if(Android,2) load 351236-1.html
 load 407062-1.html
 load 419563-1.xhtml
 skip-if(winWidget) load 428844-1.html # bug 471185
 load 461049-1.html
 asserts(0-1) asserts-if(winWidget,0-2) load removing-editable-xslt.html # bug 500847
--- a/editor/composer/src/nsEditorSpellCheck.cpp
+++ b/editor/composer/src/nsEditorSpellCheck.cpp
@@ -49,22 +49,18 @@
 #include "nsISpellChecker.h"
 #include "nsISelection.h"
 #include "nsIDOMRange.h"
 #include "nsIEditor.h"
 #include "nsIHTMLEditor.h"
 
 #include "nsIComponentManager.h"
 #include "nsIContentPrefService.h"
-#include "nsIObserverService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIChromeRegistry.h"
-#include "nsIPrivateBrowsingService.h"
-#include "nsIContentURIGrouper.h"
-#include "nsNetCID.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsITextServicesFilter.h"
 #include "nsUnicharUtils.h"
 #include "mozilla/Services.h"
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
@@ -82,26 +78,21 @@ class UpdateDictionnaryHolder {
       if (mSpellCheck) {
         mSpellCheck->EndUpdateDictionary();
       }
     }
 };
 
 #define CPS_PREF_NAME NS_LITERAL_STRING("spellcheck.lang")
 
-class LastDictionary : public nsIObserver, public nsSupportsWeakReference {
+class LastDictionary {
 public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIOBSERVER
-
-  LastDictionary();
-
   /**
    * Store current dictionary for editor document url. Use content pref
-   * service. Or, if in private mode, store this information in memory.
+   * service.
    */
   NS_IMETHOD StoreCurrentDictionary(nsIEditor* aEditor, const nsAString& aDictionary);
 
   /**
    * Get last stored current dictionary for editor document url.
    */
   NS_IMETHOD FetchLastDictionary(nsIEditor* aEditor, nsAString& aDictionary);
 
@@ -110,36 +101,18 @@ public:
    */
   NS_IMETHOD ClearCurrentDictionary(nsIEditor* aEditor);
 
   /**
    * get uri of editor's document.
    *
    */
   static nsresult GetDocumentURI(nsIEditor* aEditor, nsIURI * *aURI);
-
-  PRBool mInPrivateBrowsing;
-
-  // During private browsing, dictionaries are stored in memory
-  nsDataHashtable<nsStringHashKey, nsString> mMemoryStorage;
 };
 
-NS_IMPL_ISUPPORTS2(LastDictionary, nsIObserver, nsISupportsWeakReference)
-
-LastDictionary::LastDictionary():
-  mInPrivateBrowsing(PR_FALSE)
-{  
-  nsCOMPtr<nsIPrivateBrowsingService> pbService =
-    do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID);
-  if (pbService) {
-    pbService->GetPrivateBrowsingEnabled(&mInPrivateBrowsing);
-    mMemoryStorage.Init();
-  }
-}
-
 // static
 nsresult
 LastDictionary::GetDocumentURI(nsIEditor* aEditor, nsIURI * *aURI)
 {
   NS_ENSURE_ARG_POINTER(aEditor);
   NS_ENSURE_ARG_POINTER(aURI);
 
   nsCOMPtr<nsIDOMDocument> domDoc;
@@ -163,31 +136,16 @@ LastDictionary::FetchLastDictionary(nsIE
   NS_ENSURE_ARG_POINTER(aEditor);
 
   nsresult rv;
 
   nsCOMPtr<nsIURI> docUri;
   rv = GetDocumentURI(aEditor, getter_AddRefs(docUri));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (mInPrivateBrowsing) {
-    nsCOMPtr<nsIContentURIGrouper> hostnameGrouperService =
-      do_GetService(NS_HOSTNAME_GROUPER_SERVICE_CONTRACTID);
-    NS_ENSURE_TRUE(hostnameGrouperService, NS_ERROR_NOT_AVAILABLE);
-    nsString group;
-    hostnameGrouperService->Group(docUri, group);
-    nsAutoString lastDict;
-    if (mMemoryStorage.Get(group, &lastDict)) {
-      aDictionary.Assign(lastDict);
-    } else {
-      aDictionary.Truncate();
-    }
-    return NS_OK;
-  }
-
   nsCOMPtr<nsIContentPrefService> contentPrefService =
     do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(contentPrefService, NS_ERROR_NOT_AVAILABLE);
 
   nsCOMPtr<nsIWritableVariant> uri = do_CreateInstance(NS_VARIANT_CONTRACTID);
   NS_ENSURE_TRUE(uri, NS_ERROR_OUT_OF_MEMORY);
   uri->SetAsISupports(docUri);
 
@@ -209,30 +167,16 @@ LastDictionary::StoreCurrentDictionary(n
   NS_ENSURE_ARG_POINTER(aEditor);
 
   nsresult rv;
 
   nsCOMPtr<nsIURI> docUri;
   rv = GetDocumentURI(aEditor, getter_AddRefs(docUri));
   NS_ENSURE_SUCCESS(rv, rv);
 
- if (mInPrivateBrowsing) {
-    nsCOMPtr<nsIContentURIGrouper> hostnameGrouperService =
-      do_GetService(NS_HOSTNAME_GROUPER_SERVICE_CONTRACTID);
-    NS_ENSURE_TRUE(hostnameGrouperService, NS_ERROR_NOT_AVAILABLE);
-    nsString group;
-    hostnameGrouperService->Group(docUri, group);
-
-    if (mMemoryStorage.Put(group, nsString(aDictionary))) {
-      return NS_OK;
-    } else {
-      return NS_ERROR_FAILURE;
-    }
-  }
-
   nsCOMPtr<nsIWritableVariant> uri = do_CreateInstance(NS_VARIANT_CONTRACTID);
   NS_ENSURE_TRUE(uri, NS_ERROR_OUT_OF_MEMORY);
   uri->SetAsISupports(docUri);
 
   nsCOMPtr<nsIWritableVariant> prefValue = do_CreateInstance(NS_VARIANT_CONTRACTID);
   NS_ENSURE_TRUE(prefValue, NS_ERROR_OUT_OF_MEMORY);
   prefValue->SetAsAString(aDictionary);
 
@@ -249,55 +193,27 @@ LastDictionary::ClearCurrentDictionary(n
   NS_ENSURE_ARG_POINTER(aEditor);
 
   nsresult rv;
 
   nsCOMPtr<nsIURI> docUri;
   rv = GetDocumentURI(aEditor, getter_AddRefs(docUri));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIContentURIGrouper> hostnameGrouperService =
-      do_GetService(NS_HOSTNAME_GROUPER_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(hostnameGrouperService, NS_ERROR_NOT_AVAILABLE);
-
-  nsString group;
-  hostnameGrouperService->Group(docUri, group);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (mMemoryStorage.IsInitialized()) {
-    mMemoryStorage.Remove(group);
-  }
-
   nsCOMPtr<nsIWritableVariant> uri = do_CreateInstance(NS_VARIANT_CONTRACTID);
   NS_ENSURE_TRUE(uri, NS_ERROR_OUT_OF_MEMORY);
   uri->SetAsISupports(docUri);
 
   nsCOMPtr<nsIContentPrefService> contentPrefService =
     do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(contentPrefService, NS_ERROR_NOT_INITIALIZED);
 
   return contentPrefService->RemovePref(uri, CPS_PREF_NAME);
 }
 
-NS_IMETHODIMP
-LastDictionary::Observe(nsISupports *aSubject, char const *aTopic, PRUnichar const *aData)
-{
-  if (strcmp(aTopic, NS_PRIVATE_BROWSING_SWITCH_TOPIC) == 0) {
-    if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_ENTER).Equals(aData)) {
-      mInPrivateBrowsing = PR_TRUE;
-    } else if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).Equals(aData)) {
-      mInPrivateBrowsing = PR_FALSE;
-      if (mMemoryStorage.IsInitialized()) {
-        mMemoryStorage.Clear();
-      }
-    }
-  } 
-  return NS_OK;
-}
-
 LastDictionary* nsEditorSpellCheck::gDictionaryStore = nsnull;
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsEditorSpellCheck)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsEditorSpellCheck)
 
 NS_INTERFACE_MAP_BEGIN(nsEditorSpellCheck)
   NS_INTERFACE_MAP_ENTRY(nsIEditorSpellCheck)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEditorSpellCheck)
@@ -353,24 +269,16 @@ nsEditorSpellCheck::InitSpellChecker(nsI
 {
   NS_ENSURE_TRUE(aEditor, NS_ERROR_NULL_POINTER);
   mEditor = aEditor;
 
   nsresult rv;
 
   if (!gDictionaryStore) {
     gDictionaryStore = new LastDictionary();
-    if (gDictionaryStore) {
-      NS_ADDREF(gDictionaryStore);
-      nsCOMPtr<nsIObserverService> observerService =
-        mozilla::services::GetObserverService();
-      if (observerService) {
-        observerService->AddObserver(gDictionaryStore, NS_PRIVATE_BROWSING_SWITCH_TOPIC, PR_TRUE);
-      }
-    }
   }
 
 
   // We can spell check with any editor type
   nsCOMPtr<nsITextServicesDocument>tsDoc =
      do_CreateInstance("@mozilla.org/textservices/textservicesdocument;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -834,10 +742,10 @@ nsEditorSpellCheck::UpdateCurrentDiction
 
   DeleteSuggestedWordList();
 
   return NS_OK;
 }
 
 void 
 nsEditorSpellCheck::ShutDown() {
-  NS_IF_RELEASE(gDictionaryStore);
+  delete gDictionaryStore;
 }
--- a/editor/composer/src/nsEditorSpellCheck.h
+++ b/editor/composer/src/nsEditorSpellCheck.h
@@ -38,17 +38,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsEditorSpellCheck_h___
 #define nsEditorSpellCheck_h___
 
 
 #include "nsIEditorSpellCheck.h"
 #include "nsISpellChecker.h"
-#include "nsIObserver.h"
 #include "nsIURI.h"
 #include "nsWeakReference.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDataHashtable.h"
 
 #define NS_EDITORSPELLCHECK_CID                     \
 { /* {75656ad9-bd13-4c5d-939a-ec6351eea0cc} */        \
--- a/editor/libeditor/base/crashtests/crashtests.list
+++ b/editor/libeditor/base/crashtests/crashtests.list
@@ -1,10 +1,10 @@
 load 336104.html
 load 382527-1.html
 load 402172-1.html
 load 407079-1.html
 load 407256-1.html
 load 430624-1.html
 load 459613.html
 load 475132-1.xhtml
-load 633709.xhtml
-asserts(6) load 636074-1.html # Bug 439258, charged to the wrong test due to bug 635550
+asserts-if(Android,6) load 633709.xhtml
+asserts-if(!Android,6) load 636074-1.html # Bug 439258, charged to the wrong test due to bug 635550
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -150,30 +150,30 @@ void GetPathToBinary(FilePath& exePath)
     NS_ASSERTION(directoryService, "Expected XPCOM to be available");
     if (directoryService) {
       nsCOMPtr<nsIFile> greDir;
       nsresult rv = directoryService->Get(NS_GRE_DIR, NS_GET_IID(nsIFile), getter_AddRefs(greDir));
       if (NS_SUCCEEDED(rv)) {
         nsCString path;
         greDir->GetNativePath(path);
         exePath = FilePath(path.get());
+#ifdef OS_MACOSX
+        // We need to use an App Bundle on OS X so that we can hide
+        // the dock icon. See Bug 557225.
+        exePath = exePath.AppendASCII(MOZ_CHILD_PROCESS_BUNDLE);
+#endif
       }
     }
   }
+
   if (exePath.empty()) {
     exePath = FilePath(CommandLine::ForCurrentProcess()->argv()[0]);
     exePath = exePath.DirName();
   }
 
-#ifdef OS_MACOSX
-  // We need to use an App Bundle on OS X so that we can hide
-  // the dock icon. See Bug 557225
-  exePath = exePath.AppendASCII(MOZ_CHILD_PROCESS_BUNDLE);
-#endif
-
   exePath = exePath.AppendASCII(MOZ_CHILD_PROCESS_NAME);
 #endif
 }
 
 #ifdef XP_MACOSX
 class AutoCFTypeObject {
 public:
   AutoCFTypeObject(CFTypeRef object)
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug684796.js
@@ -0,0 +1,2 @@
+if (typeof mjitdatastats == "function")
+    mjitdatastats();
--- a/js/src/jsapi-tests/Makefile.in
+++ b/js/src/jsapi-tests/Makefile.in
@@ -60,17 +60,17 @@ CPPSRCS = \
   testDebugger.cpp \
   testDeepFreeze.cpp \
   testDefineGetterSetterNonEnumerable.cpp \
   testDefineProperty.cpp \
   testExtendedEq.cpp \
   testExternalStrings.cpp \
   testFuncCallback.cpp \
   testFunctionProperties.cpp \
-  testGCChunkAlloc.cpp \
+  testGCOutOfMemory.cpp \
   testGetPropertyDefault.cpp \
   testIndexToString.cpp \
   testIntString.cpp \
   testIntern.cpp \
   testLookup.cpp \
   testLooselyEqual.cpp \
   testNewObject.cpp \
   testOps.cpp \
rename from js/src/jsapi-tests/testGCChunkAlloc.cpp
rename to js/src/jsapi-tests/testGCOutOfMemory.cpp
--- a/js/src/jsapi-tests/testGCChunkAlloc.cpp
+++ b/js/src/jsapi-tests/testGCOutOfMemory.cpp
@@ -5,127 +5,64 @@
  * http://creativecommons.org/licenses/publicdomain/
  * Contributor: Igor Bukanov
  */
 
 #include "tests.h"
 #include "jsgcchunk.h"
 #include "jscntxt.h"
 
-/* We allow to allocate 2 (system/user) chunks. */
-
-static const int SYSTEM  = 0;
-static const int USER    = 1;
-static const int N_POOLS = 2;
-
-class CustomGCChunkAllocator: public js::GCChunkAllocator {
-  public:
-    CustomGCChunkAllocator() { pool[SYSTEM] = NULL; pool[USER] = NULL; }
-    void *pool[N_POOLS];
-    
-  private:
-
-    virtual void *doAlloc() {
-        if (!pool[SYSTEM] && !pool[USER])
-            return NULL;
-        void *chunk = NULL;
-        if (pool[SYSTEM]) {
-            chunk = pool[SYSTEM];
-            pool[SYSTEM] = NULL;
-        } else {
-            chunk = pool[USER];
-            pool[USER] = NULL;
-        }
-        return chunk;
-    }
-        
-    virtual void doFree(void *chunk) {
-        JS_ASSERT(!pool[SYSTEM] || !pool[USER]);
-        if (!pool[SYSTEM]) {
-            pool[SYSTEM] = chunk;
-        } else {
-            pool[USER] = chunk;
-        }
-    }
-};
-
-static CustomGCChunkAllocator customGCChunkAllocator;
-
 static unsigned errorCount = 0;
 
 static void
 ErrorCounter(JSContext *cx, const char *message, JSErrorReport *report)
 {
     ++errorCount;
 }
 
-BEGIN_TEST(testGCChunkAlloc)
+BEGIN_TEST(testGCOutOfMemory)
 {
     JS_SetErrorReporter(cx, ErrorCounter);
 
     jsvalRoot root(cx);
 
     /*
-     * We loop until out-of-memory happens during the chunk allocation. But
-     * we have to disable the jit since it cannot tolerate OOM during the
-     * chunk allocation.
+     * We loop until we get out-of-memory. We have to disable the jit since it
+     * ignores the runtime allocation limits during execution.
      */
     JS_ToggleOptions(cx, JSOPTION_JIT);
 
     static const char source[] =
         "var max = 0; (function() {"
         "    var array = [];"
         "    for (; ; ++max)"
         "        array.push({});"
+        "    array = []; array.push(0);"
         "})();";
     JSBool ok = JS_EvaluateScript(cx, global, source, strlen(source), "", 1,
                                   root.addr());
 
     /* Check that we get OOM. */
     CHECK(!ok);
     CHECK(!JS_IsExceptionPending(cx));
     CHECK_EQUAL(errorCount, 1);
-    CHECK(!customGCChunkAllocator.pool[SYSTEM]);
-    CHECK(!customGCChunkAllocator.pool[USER]);
     JS_GC(cx);
     JS_ToggleOptions(cx, JSOPTION_JIT);
     EVAL("(function() {"
          "    var array = [];"
-         "    for (var i = max >> 1; i != 0;) {"
+         "    for (var i = max >> 2; i != 0;) {"
          "        --i;"
          "        array.push({});"
          "    }"
          "})();", root.addr());
     CHECK_EQUAL(errorCount, 1);
     return true;
 }
 
 virtual JSRuntime * createRuntime() {
-    /*
-     * To test failure of chunk allocation allow to use GC twice the memory
-     * the single chunk contains.
-     */
-    JSRuntime *rt = JS_NewRuntime(2 * js::GC_CHUNK_SIZE);
-    if (!rt)
-        return NULL;
-
-    customGCChunkAllocator.pool[SYSTEM] = js::AllocGCChunk();
-    customGCChunkAllocator.pool[USER] = js::AllocGCChunk();
-    JS_ASSERT(customGCChunkAllocator.pool[SYSTEM]);
-    JS_ASSERT(customGCChunkAllocator.pool[USER]);
-
-    rt->setCustomGCChunkAllocator(&customGCChunkAllocator);
-    return rt;
+    return JS_NewRuntime(256 * 1024);
 }
 
 virtual void destroyRuntime() {
     JS_DestroyRuntime(rt);
-
-    /* We should get the initial chunk back at this point. */
-    JS_ASSERT(customGCChunkAllocator.pool[SYSTEM]);
-    JS_ASSERT(customGCChunkAllocator.pool[USER]);
-    js::FreeGCChunk(customGCChunkAllocator.pool[SYSTEM]);
-    js::FreeGCChunk(customGCChunkAllocator.pool[USER]);
-    customGCChunkAllocator.pool[SYSTEM] = NULL;
-    customGCChunkAllocator.pool[USER] = NULL;
 }
 
-END_TEST(testGCChunkAlloc)
+END_TEST(testGCOutOfMemory)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -633,18 +633,17 @@ JS_IsBuiltinFunctionConstructor(JSFuncti
 /*
  * Has a new runtime ever been created?  This flag is used to detect unsafe
  * changes to js_CStringsAreUTF8 after a runtime has been created, and to
  * control things that should happen only once across all runtimes.
  */
 static JSBool js_NewRuntimeWasCalled = JS_FALSE;
 
 JSRuntime::JSRuntime()
-  : gcChunkAllocator(&defaultGCChunkAllocator),
-    trustedPrincipals_(NULL)
+  : trustedPrincipals_(NULL)
 {
     /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
     JS_INIT_CLIST(&contextList);
     JS_INIT_CLIST(&debuggerList);
 }
 
 bool
 JSRuntime::init(uint32 maxbytes)
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1831,20 +1831,21 @@ js_MergeSort(void *src, size_t nel, size
         memcpy(src, tmp, nel * elsize);
 
     return JS_TRUE;
 }
 
 struct CompareArgs
 {
     JSContext          *context;
-    InvokeSessionGuard session;
-
-    CompareArgs(JSContext *cx)
-      : context(cx)
+    InvokeArgsGuard    args;
+    Value              fval;
+
+    CompareArgs(JSContext *cx, Value fval)
+      : context(cx), fval(fval)
     {}
 };
 
 static JS_REQUIRES_STACK JSBool
 sort_compare(void *arg, const void *a, const void *b, int *result)
 {
     const Value *av = (const Value *)a, *bv = (const Value *)b;
     CompareArgs *ca = (CompareArgs *) arg;
@@ -1855,25 +1856,31 @@ sort_compare(void *arg, const void *a, c
      * come here.
      */
     JS_ASSERT(!av->isMagic() && !av->isUndefined());
     JS_ASSERT(!av->isMagic() && !bv->isUndefined());
 
     if (!JS_CHECK_OPERATION_LIMIT(cx))
         return JS_FALSE;
 
-    InvokeSessionGuard &session = ca->session;
-    session[0] = *av;
-    session[1] = *bv;
-
-    if (!session.invoke(cx))
+    InvokeArgsGuard &args = ca->args;
+    if (!args.pushed() && !cx->stack.pushInvokeArgs(cx, 2, &args))
+        return JS_FALSE;
+        
+    args.calleeHasBeenReset();
+    args.calleev() = ca->fval;
+    args.thisv() = UndefinedValue();
+    args[0] = *av;
+    args[1] = *bv;
+
+    if (!Invoke(cx, args))
         return JS_FALSE;
 
     jsdouble cmp;
-    if (!ToNumber(cx, session.rval(), &cmp))
+    if (!ToNumber(cx, args.rval(), &cmp))
         return JS_FALSE;
 
     /* Clamp cmp to -1, 0, 1. */
     *result = 0;
     if (!JSDOUBLE_IS_NaN(cmp) && cmp != 0)
         *result = cmp > 0 ? 1 : -1;
 
     /*
@@ -2100,20 +2107,17 @@ js::array_sort(JSContext *cx, uintN argc
                  * not call JS_CHECK_OPERATION_LIMIT in the loop.
                  */
                 i = 0;
                 do {
                     vec[i] = vec[2 * i + 1];
                 } while (++i != newlen);
             }
         } else {
-            CompareArgs ca(cx);
-            if (!ca.session.start(cx, fval, UndefinedValue(), 2))
-                return false;
-
+            CompareArgs ca(cx, fval);
             if (!js_MergeSort(vec, size_t(newlen), sizeof(Value),
                               comparator_stack_cast(sort_compare),
                               &ca, mergesort_tmp,
                               JS_SORTING_VALUES)) {
                 return false;
             }
         }
 
@@ -2957,52 +2961,55 @@ array_extra(JSContext *cx, ArrayExtraMod
     Value thisv = (argc > 1 && !REDUCE_MODE(mode)) ? argv[1] : UndefinedValue();
 
     /*
      * For all but REDUCE, we call with 3 args (value, index, array). REDUCE
      * requires 4 args (accum, value, index, array).
      */
     argc = 3 + REDUCE_MODE(mode);
 
-    InvokeSessionGuard session;
-    if (!session.start(cx, ObjectValue(*callable), thisv, argc))
-        return JS_FALSE;
-
     MUST_FLOW_THROUGH("out");
     JSBool ok = JS_TRUE;
     JSBool cond;
 
     Value objv = ObjectValue(*obj);
     AutoValueRooter tvr(cx);
+    InvokeArgsGuard args;
     for (jsuint i = start; i != end; i += step) {
         JSBool hole;
         ok = JS_CHECK_OPERATION_LIMIT(cx) &&
              GetElement(cx, obj, i, &hole, tvr.addr());
         if (!ok)
             goto out;
         if (hole)
             continue;
 
+        if (!args.pushed() && !cx->stack.pushInvokeArgs(cx, argc, &args))
+            return false;
+
         /*
          * Push callable and 'this', then args. We must do this for every
          * iteration around the loop since Invoke clobbers its arguments.
          */
+        args.calleeHasBeenReset();
+        args.calleev() = ObjectValue(*callable);
+        args.thisv() = thisv;
         uintN argi = 0;
         if (REDUCE_MODE(mode))
-            session[argi++] = *vp;
-        session[argi++] = tvr.value();
-        session[argi++] = Int32Value(i);
-        session[argi]   = objv;
+            args[argi++] = *vp;
+        args[argi++] = tvr.value();
+        args[argi++] = Int32Value(i);
+        args[argi]   = objv;
 
         /* Do the call. */
-        ok = session.invoke(cx);
+        ok = Invoke(cx, args);
         if (!ok)
             break;
 
-        const Value &rval = session.rval();
+        const Value &rval = args.rval();
 
         if (mode > MAP)
             cond = js_ValueToBoolean(rval);
 #ifdef __GNUC__ /* quell GCC overwarning */
         else
             cond = JS_FALSE;
 #endif
 
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -507,24 +507,16 @@ struct JSRuntime {
   private:
     /*
      * Malloc counter to measure memory pressure for GC scheduling. It runs
      * from gcMaxMallocBytes down to zero.
      */
     volatile ptrdiff_t  gcMallocBytes;
 
   public:
-    js::GCChunkAllocator    *gcChunkAllocator;
-
-    void setCustomGCChunkAllocator(js::GCChunkAllocator *allocator) {
-        JS_ASSERT(allocator);
-        JS_ASSERT(state == JSRTS_DOWN);
-        gcChunkAllocator = allocator;
-    }
-
     /*
      * The trace operation and its data argument to trace embedding-specific
      * GC roots.
      */
     JSTraceDataOp       gcExtraRootsTraceOp;
     void                *gcExtraRootsData;
 
     /* Well-known numbers held for use by this runtime's contexts. */
--- a/js/src/jsemit.cpp
+++ b/js/src/jsemit.cpp
@@ -72,24 +72,22 @@
 #include "jsatominlines.h"
 #include "jsobjinlines.h"
 #include "jsscopeinlines.h"
 #include "jsscriptinlines.h"
 
 #include "frontend/ParseMaps-inl.h"
 
 /* Allocation chunk counts, must be powers of two in general. */
-#define BYTECODE_CHUNK  256     /* code allocation increment */
-#define SRCNOTE_CHUNK   64      /* initial srcnote allocation increment */
-#define TRYNOTE_CHUNK   64      /* trynote allocation increment */
+#define BYTECODE_CHUNK_LENGTH  1024    /* initial bytecode chunk length */
+#define SRCNOTE_CHUNK_LENGTH   1024    /* initial srcnote chunk length */
 
 /* Macros to compute byte sizes from typed element counts. */
 #define BYTECODE_SIZE(n)        ((n) * sizeof(jsbytecode))
 #define SRCNOTE_SIZE(n)         ((n) * sizeof(jssrcnote))
-#define TRYNOTE_SIZE(n)         ((n) * sizeof(JSTryNote))
 
 using namespace js;
 using namespace js::gc;
 
 static JSBool
 NewTryNote(JSContext *cx, JSCodeGenerator *cg, JSTryNoteKind kind,
            uintN stackDepth, size_t start, size_t end);
 
@@ -101,22 +99,18 @@ static JSBool
 EmitLeaveBlock(JSContext *cx, JSCodeGenerator *cg, JSOp op, JSObjectBox *box);
 
 void
 JSTreeContext::trace(JSTracer *trc)
 {
     bindings.trace(trc);
 }
 
-JSCodeGenerator::JSCodeGenerator(Parser *parser,
-                                 JSArenaPool *cpool, JSArenaPool *npool,
-                                 uintN lineno)
+JSCodeGenerator::JSCodeGenerator(Parser *parser, uintN lineno)
   : JSTreeContext(parser),
-    codePool(cpool), notePool(npool),
-    codeMark(JS_ARENA_MARK(cpool)), noteMark(JS_ARENA_MARK(npool)),
     atomIndices(parser->context),
     stackDepth(0), maxStackDepth(0),
     ntrynotes(0), lastTryNode(NULL),
     spanDeps(NULL), jumpTargets(NULL), jtFreeList(NULL),
     numSpanDeps(0), numJumpTargets(0), spanDepTodo(0),
     arrayCompDepth(0),
     emitLevel(0),
     constMap(parser->context),
@@ -130,69 +124,72 @@ JSCodeGenerator::JSCodeGenerator(Parser 
     traceIndex(0),
     typesetCount(0)
 {
     flags = TCF_COMPILING;
     memset(&prolog, 0, sizeof prolog);
     memset(&main, 0, sizeof main);
     current = &main;
     firstLine = prolog.currentLine = main.currentLine = lineno;
-    prolog.noteMask = main.noteMask = SRCNOTE_CHUNK - 1;
 }
 
 bool
 JSCodeGenerator::init(JSContext *cx, JSTreeContext::InitBehavior ib)
 {
     roLexdeps.init();
     return JSTreeContext::init(cx, ib) && constMap.init() && atomIndices.ensureMap(cx);
 }
 
 JSCodeGenerator::~JSCodeGenerator()
 {
-    JS_ARENA_RELEASE(codePool, codeMark);
-    JS_ARENA_RELEASE(notePool, noteMark);
-
     JSContext *cx = parser->context;
 
+    cx->free_(prolog.base);
+    cx->free_(prolog.notes);
+    cx->free_(main.base);
+    cx->free_(main.notes);
+
     /* NB: non-null only after OOM. */
     if (spanDeps)
         cx->free_(spanDeps);
 }
 
 static ptrdiff_t
-EmitCheck(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t delta)
+EmitCheck(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t delta)
 {
-    jsbytecode *base, *limit, *next;
-    ptrdiff_t offset, length;
-    size_t incr, size;
-
-    base = CG_BASE(cg);
-    next = CG_NEXT(cg);
-    limit = CG_LIMIT(cg);
-    offset = next - base;
+    jsbytecode *base = CG_BASE(cg);
+    jsbytecode *newbase;
+    jsbytecode *next = CG_NEXT(cg);
+    jsbytecode *limit = CG_LIMIT(cg);
+    ptrdiff_t offset = next - base;
+    size_t minlength = offset + delta;
+
     if (next + delta > limit) {
-        length = offset + delta;
-        length = (length <= BYTECODE_CHUNK)
-                 ? BYTECODE_CHUNK
-                 : JS_BIT(JS_CeilingLog2(length));
-        incr = BYTECODE_SIZE(length);
+        size_t newlength;
         if (!base) {
-            JS_ARENA_ALLOCATE_CAST(base, jsbytecode *, cg->codePool, incr);
+            JS_ASSERT(!next && !limit);
+            newlength = BYTECODE_CHUNK_LENGTH;
+            if (newlength < minlength)     /* make it bigger if necessary */
+                newlength = RoundUpPow2(minlength);
+            newbase = (jsbytecode *) cx->malloc_(BYTECODE_SIZE(newlength));
         } else {
-            size = BYTECODE_SIZE(limit - base);
-            incr -= size;
-            JS_ARENA_GROW_CAST(base, jsbytecode *, cg->codePool, size, incr);
-        }
-        if (!base) {
+            JS_ASSERT(base <= next && next <= limit);
+            newlength = (limit - base) * 2;
+            if (newlength < minlength)     /* make it bigger if necessary */
+                newlength = RoundUpPow2(minlength);
+            newbase = (jsbytecode *) cx->realloc_(base, BYTECODE_SIZE(newlength));
+        }
+        if (!newbase) {
             js_ReportOutOfMemory(cx);
             return -1;
         }
-        CG_BASE(cg) = base;
-        CG_LIMIT(cg) = base + length;
-        CG_NEXT(cg) = base + offset;
+        JS_ASSERT(newlength >= size_t(offset + delta));
+        CG_BASE(cg) = newbase;
+        CG_LIMIT(cg) = newbase + newlength;
+        CG_NEXT(cg) = newbase + offset;
     }
     return offset;
 }
 
 static void
 UpdateDepth(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t target)
 {
     jsbytecode *pc;
@@ -258,61 +255,61 @@ UpdateDecomposeLength(JSCodeGenerator *c
     uintN end = CG_OFFSET(cg);
     JS_ASSERT(uintN(end - start) < 256);
     CG_CODE(cg, start)[-1] = end - start;
 }
 
 ptrdiff_t
 js_Emit1(JSContext *cx, JSCodeGenerator *cg, JSOp op)
 {
-    ptrdiff_t offset = EmitCheck(cx, cg, op, 1);
+    ptrdiff_t offset = EmitCheck(cx, cg, 1);
 
     if (offset >= 0) {
         *CG_NEXT(cg)++ = (jsbytecode)op;
         UpdateDepth(cx, cg, offset);
     }
     return offset;
 }
 
 ptrdiff_t
 js_Emit2(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1)
 {
-    ptrdiff_t offset = EmitCheck(cx, cg, op, 2);
+    ptrdiff_t offset = EmitCheck(cx, cg, 2);
 
     if (offset >= 0) {
         jsbytecode *next = CG_NEXT(cg);
         next[0] = (jsbytecode)op;
         next[1] = op1;
         CG_NEXT(cg) = next + 2;
         UpdateDepth(cx, cg, offset);
     }
     return offset;
 }
 
 ptrdiff_t
 js_Emit3(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1,
          jsbytecode op2)
 {
-    ptrdiff_t offset = EmitCheck(cx, cg, op, 3);
+    ptrdiff_t offset = EmitCheck(cx, cg, 3);
 
     if (offset >= 0) {
         jsbytecode *next = CG_NEXT(cg);
         next[0] = (jsbytecode)op;
         next[1] = op1;
         next[2] = op2;
         CG_NEXT(cg) = next + 3;
         UpdateDepth(cx, cg, offset);
     }
     return offset;
 }
 
 ptrdiff_t
 js_Emit5(JSContext *cx, JSCodeGenerator *cg, JSOp op, uint16 op1, uint16 op2)
 {
-    ptrdiff_t offset = EmitCheck(cx, cg, op, 5);
+    ptrdiff_t offset = EmitCheck(cx, cg, 5);
 
     if (offset >= 0) {
         jsbytecode *next = CG_NEXT(cg);
         next[0] = (jsbytecode)op;
         next[1] = UINT16_HI(op1);
         next[2] = UINT16_LO(op1);
         next[3] = UINT16_HI(op2);
         next[4] = UINT16_LO(op2);
@@ -321,17 +318,17 @@ js_Emit5(JSContext *cx, JSCodeGenerator 
     }
     return offset;
 }
 
 ptrdiff_t
 js_EmitN(JSContext *cx, JSCodeGenerator *cg, JSOp op, size_t extra)
 {
     ptrdiff_t length = 1 + (ptrdiff_t)extra;
-    ptrdiff_t offset = EmitCheck(cx, cg, op, length);
+    ptrdiff_t offset = EmitCheck(cx, cg, length);
 
     if (offset >= 0) {
         jsbytecode *next = CG_NEXT(cg);
         *next = (jsbytecode)op;
         memset(next + 1, 0, BYTECODE_SIZE(extra));
         CG_NEXT(cg) = next + length;
 
         /*
@@ -837,17 +834,16 @@ static JSBool
 OptimizeSpanDeps(JSContext *cx, JSCodeGenerator *cg)
 {
     jsbytecode *pc, *oldpc, *base, *limit, *next;
     JSSpanDep *sd, *sd2, *sdbase, *sdlimit, *sdtop, guard;
     ptrdiff_t offset, growth, delta, top, pivot, span, length, target;
     JSBool done;
     JSOp op;
     uint32 type;
-    size_t size, incr;
     jssrcnote *sn, *snlimit;
     JSSrcNoteSpec *spec;
     uintN i, n, noteIndex;
     JSTryNode *tryNode;
     DebugOnly<int> passes = 0;
 
     base = CG_BASE(cg);
     sdbase = cg->spanDeps;
@@ -967,20 +963,17 @@ OptimizeSpanDeps(JSContext *cx, JSCodeGe
         /*
          * Ensure that we have room for the extended jumps, but don't round up
          * to a power of two -- we're done generating code, so we cut to fit.
          */
         limit = CG_LIMIT(cg);
         length = offset + growth;
         next = base + length;
         if (next > limit) {
-            JS_ASSERT(length > BYTECODE_CHUNK);
-            size = BYTECODE_SIZE(limit - base);
-            incr = BYTECODE_SIZE(length) - size;
-            JS_ARENA_GROW_CAST(base, jsbytecode *, cg->codePool, size, incr);
+            base = (jsbytecode *) cx->realloc_(base, BYTECODE_SIZE(length));
             if (!base) {
                 js_ReportOutOfMemory(cx);
                 return JS_FALSE;
             }
             CG_BASE(cg) = base;
             CG_LIMIT(cg) = next = base + length;
         }
         CG_NEXT(cg) = next;
@@ -1052,17 +1045,17 @@ OptimizeSpanDeps(JSContext *cx, JSCodeGe
 
         /*
          * Don't bother copying the jump offset we're about to reset, but do
          * copy the bytecode at oldpc (which comes just before its immediate
          * jump offset operand), on the next iteration through the loop, by
          * including it in offset's new value.
          */
         offset = sd->before + 1;
-        size = BYTECODE_SIZE(delta - (1 + JUMP_OFFSET_LEN));
+        size_t size = BYTECODE_SIZE(delta - (1 + JUMP_OFFSET_LEN));
         if (size) {
             memmove(pc + 1 + JUMPX_OFFSET_LEN,
                     oldpc + 1 + JUMP_OFFSET_LEN,
                     size);
         }
 
         SET_JUMPX_OFFSET(pc, span);
     }
@@ -1222,17 +1215,16 @@ OptimizeSpanDeps(JSContext *cx, JSCodeGe
   }
 #endif
 
     /*
      * Reset so we optimize at most once -- cg may be used for further code
      * generation of successive, independent, top-level statements.  No jump
      * can span top-level statements, because JS lacks goto.
      */
-    size = SPANDEPS_SIZE(JS_BIT(JS_CeilingLog2(cg->numSpanDeps)));
     cx->free_(cg->spanDeps);
     cg->spanDeps = NULL;
     FreeJumpTargets(cg, cg->jumpTargets);
     cg->jumpTargets = NULL;
     cg->numSpanDeps = cg->numJumpTargets = 0;
     cg->spanDepTodo = CG_OFFSET(cg);
     return JS_TRUE;
 }
@@ -3707,18 +3699,17 @@ EmitSwitch(JSContext *cx, JSCodeGenerato
             if (off < 0)
                 return JS_FALSE;
             pn3->pn_offset = off;
             if (beforeCases) {
                 uintN noteCount, noteCountDelta;
 
                 /* Switch note's second offset is to first JSOP_CASE. */
                 noteCount = CG_NOTE_COUNT(cg);
-                if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1,
-                                         off - top)) {
+                if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1, off - top)) {
                     return JS_FALSE;
                 }
                 noteCountDelta = CG_NOTE_COUNT(cg) - noteCount;
                 if (noteCountDelta != 0)
                     caseNoteIndex += noteCountDelta;
                 beforeCases = JS_FALSE;
             }
         }
@@ -5020,28 +5011,21 @@ js_EmitTree(JSContext *cx, JSCodeGenerat
                 return JS_FALSE;
             break;
         }
 
         JS_ASSERT_IF(pn->pn_funbox->tcflags & TCF_FUN_HEAVYWEIGHT,
                      fun->kind() == JSFUN_INTERPRETED);
 
         /* Generate code for the function's body. */
-        void *cg2mark = JS_ARENA_MARK(cg->codePool);
-        void *cg2space;
-        JS_ARENA_ALLOCATE_TYPE(cg2space, JSCodeGenerator, cg->codePool);
-        if (!cg2space) {
+        JSCodeGenerator *cg2 = cx->new_<JSCodeGenerator>(cg->parser, pn->pn_pos.begin.lineno);
+        if (!cg2) {
             js_ReportOutOfMemory(cx);
             return JS_FALSE;
         }
-        JSCodeGenerator *cg2 =
-            new (cg2space) JSCodeGenerator(cg->parser,
-                                           cg->codePool, cg->notePool,
-                                           pn->pn_pos.begin.lineno);
-
         if (!cg2->init(cx))
             return JS_FALSE;
 
         cg2->flags = pn->pn_funbox->tcflags | TCF_COMPILING | TCF_IN_FUNCTION |
                      (cg->flags & TCF_FUN_MIGHT_ALIAS_LOCALS);
         cg2->bindings.transfer(cx, &pn->pn_funbox->bindings);
 #if JS_HAS_SHARP_VARS
         if (cg2->flags & TCF_HAS_SHARPS) {
@@ -5061,18 +5045,17 @@ js_EmitTree(JSContext *cx, JSCodeGenerat
          */
         JS_ASSERT(cg->staticLevel < JS_BITMASK(16) - 1);
         cg2->staticLevel = cg->staticLevel + 1;
 
         /* We measured the max scope depth when we parsed the function. */
         if (!js_EmitFunctionScript(cx, cg2, pn->pn_body))
             pn = NULL;
 
-        cg2->~JSCodeGenerator();
-        JS_ARENA_RELEASE(cg->codePool, cg2mark);
+        cx->delete_(cg2);
         cg2 = NULL;
         if (!pn)
             return JS_FALSE;
 
         /* Make the function object a literal in the outer script's pool. */
         index = cg->objectList.index(pn->pn_funbox);
 
         /* Emit a bytecode pointing to the closure object in its immediate. */
@@ -7440,41 +7423,42 @@ JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNote
     {"newline",         0,      0,      0},
     {"setline",         1,      0,      0},
     {"xdelta",          0,      0,      0},
 };
 
 static intN
 AllocSrcNote(JSContext *cx, JSCodeGenerator *cg)
 {
-    intN index;
-    JSArenaPool *pool;
-    size_t size;
-
-    index = CG_NOTE_COUNT(cg);
-    if (((uintN)index & CG_NOTE_MASK(cg)) == 0) {
-        pool = cg->notePool;
-        size = SRCNOTE_SIZE(CG_NOTE_MASK(cg) + 1);
-        if (!CG_NOTES(cg)) {
-            /* Allocate the first note array lazily; leave noteMask alone. */
-            JS_ARENA_ALLOCATE_CAST(CG_NOTES(cg), jssrcnote *, pool, size);
+    jssrcnote *notes = CG_NOTES(cg);
+    jssrcnote *newnotes;
+    uintN index = CG_NOTE_COUNT(cg);
+    uintN max = CG_NOTE_LIMIT(cg);
+
+    if (index == max) {
+        size_t newlength;
+        if (!notes) {
+            JS_ASSERT(!index && !max);
+            newlength = SRCNOTE_CHUNK_LENGTH;
+            newnotes = (jssrcnote *) cx->malloc_(SRCNOTE_SIZE(newlength));
         } else {
-            /* Grow by doubling note array size; update noteMask on success. */
-            JS_ARENA_GROW_CAST(CG_NOTES(cg), jssrcnote *, pool, size, size);
-            if (CG_NOTES(cg))
-                CG_NOTE_MASK(cg) = (CG_NOTE_MASK(cg) << 1) | 1;
-        }
-        if (!CG_NOTES(cg)) {
+            JS_ASSERT(index <= max);
+            newlength = max * 2;
+            newnotes = (jssrcnote *) cx->realloc_(notes, SRCNOTE_SIZE(newlength));
+        }
+        if (!newnotes) {
             js_ReportOutOfMemory(cx);
             return -1;
         }
+        CG_NOTES(cg) = newnotes;
+        CG_NOTE_LIMIT(cg) = newlength;
     }
 
     CG_NOTE_COUNT(cg) = index + 1;
-    return index;
+    return (intN)index;
 }
 
 intN
 js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type)
 {
     intN index, n;
     jssrcnote *sn;
     ptrdiff_t offset, delta, xdelta;
@@ -7548,28 +7532,24 @@ js_NewSrcNote3(JSContext *cx, JSCodeGene
             return -1;
     }
     return index;
 }
 
 static JSBool
 GrowSrcNotes(JSContext *cx, JSCodeGenerator *cg)
 {
-    JSArenaPool *pool;
-    size_t size;
-
-    /* Grow by doubling note array size; update noteMask on success. */
-    pool = cg->notePool;
-    size = SRCNOTE_SIZE(CG_NOTE_MASK(cg) + 1);
-    JS_ARENA_GROW_CAST(CG_NOTES(cg), jssrcnote *, pool, size, size);
-    if (!CG_NOTES(cg)) {
+    size_t newlength = CG_NOTE_LIMIT(cg) * 2;
+    jssrcnote *newnotes = (jssrcnote *) cx->realloc_(CG_NOTES(cg), newlength);
+    if (!newnotes) {
         js_ReportOutOfMemory(cx);
         return JS_FALSE;
     }
-    CG_NOTE_MASK(cg) = (CG_NOTE_MASK(cg) << 1) | 1;
+    CG_NOTES(cg) = newnotes;
+    CG_NOTE_LIMIT(cg) = newlength;
     return JS_TRUE;
 }
 
 jssrcnote *
 js_AddToSrcNoteDelta(JSContext *cx, JSCodeGenerator *cg, jssrcnote *sn,
                      ptrdiff_t delta)
 {
     ptrdiff_t base, limit, newdelta, diff;
@@ -7584,17 +7564,17 @@ js_AddToSrcNoteDelta(JSContext *cx, JSCo
 
     base = SN_DELTA(sn);
     limit = SN_IS_XDELTA(sn) ? SN_XDELTA_LIMIT : SN_DELTA_LIMIT;
     newdelta = base + delta;
     if (newdelta < limit) {
         SN_SET_DELTA(sn, newdelta);
     } else {
         index = sn - cg->main.notes;
-        if ((cg->main.noteCount & cg->main.noteMask) == 0) {
+        if (cg->main.noteCount == cg->main.noteLimit) {
             if (!GrowSrcNotes(cx, cg))
                 return NULL;
             sn = cg->main.notes + index;
         }
         diff = cg->main.noteCount - index;
         cg->main.noteCount++;
         memmove(sn + 1, sn, SRCNOTE_SIZE(diff));
         SN_MAKE_XDELTA(sn, delta);
@@ -7659,21 +7639,21 @@ js_SetSrcNoteOffset(JSContext *cx, JSCod
     /* See if the new offset requires three bytes. */
     if (offset > (ptrdiff_t)SN_3BYTE_OFFSET_MASK) {
         /* Maybe this offset was already set to a three-byte value. */
         if (!(*sn & SN_3BYTE_OFFSET_FLAG)) {
             /* Losing, need to insert another two bytes for this offset. */
             index = sn - CG_NOTES(cg);
 
             /*
-             * Simultaneously test to see if the source note array must grow to
-             * accommodate either the first or second byte of additional storage
-             * required by this 3-byte offset.
+             * Test to see if the source note array must grow to accommodate
+             * either the first or second byte of additional storage required
+             * by this 3-byte offset.
              */
-            if (((CG_NOTE_COUNT(cg) + 1) & CG_NOTE_MASK(cg)) <= 1) {
+            if (CG_NOTE_COUNT(cg) + 1 >= CG_NOTE_LIMIT(cg)) {
                 if (!GrowSrcNotes(cx, cg))
                     return JS_FALSE;
                 sn = CG_NOTES(cg) + index;
             }
             CG_NOTE_COUNT(cg) += 2;
 
             diff = CG_NOTE_COUNT(cg) - (index + 3);
             JS_ASSERT(diff >= 0);
--- a/js/src/jsemit.h
+++ b/js/src/jsemit.h
@@ -596,28 +596,23 @@ class JSGCConstList {
     bool append(js::Value v) { return list.append(v); }
     size_t length() const { return list.length(); }
     void finish(JSConstArray *array);
 
 };
 
 struct JSCodeGenerator : public JSTreeContext
 {
-    JSArenaPool     *codePool;      /* pointer to thread code arena pool */
-    JSArenaPool     *notePool;      /* pointer to thread srcnote arena pool */
-    void            *codeMark;      /* low watermark in cg->codePool */
-    void            *noteMark;      /* low watermark in cg->notePool */
-
     struct {
         jsbytecode  *base;          /* base of JS bytecode vector */
         jsbytecode  *limit;         /* one byte beyond end of bytecode */
         jsbytecode  *next;          /* pointer to next free bytecode */
         jssrcnote   *notes;         /* source notes, see below */
         uintN       noteCount;      /* number of source notes so far */
-        uintN       noteMask;       /* growth increment for notes */
+        uintN       noteLimit;      /* limit number for source notes in notePool */
         ptrdiff_t   lastNoteOffset; /* code offset for last source note */
         uintN       currentLine;    /* line number for tree-based srcnote gen */
     } prolog, main, *current;
 
     js::OwnedAtomIndexMapPtr atomIndices; /* literals indexed for mapping */
     js::AtomDefnMapPtr roLexdeps;
     uintN           firstLine;      /* first line, for js_NewScriptFromCG */
 
@@ -660,24 +655,17 @@ struct JSCodeGenerator : public JSTreeCo
     /* Vectors of pn_cookie slot values. */
     typedef js::Vector<uint32, 8> SlotVector;
     SlotVector      closedArgs;
     SlotVector      closedVars;
 
     uint16          traceIndex;     /* index for the next JSOP_TRACE instruction */
     uint16          typesetCount;   /* Number of JOF_TYPESET opcodes generated */
 
-    /*
-     * Initialize cg to allocate bytecode space from codePool, source note
-     * space from notePool, and all other arena-allocated temporaries from
-     * parser->context->tempPool.
-     */
-    JSCodeGenerator(js::Parser *parser,
-                    JSArenaPool *codePool, JSArenaPool *notePool,
-                    uintN lineno);
+    JSCodeGenerator(js::Parser *parser, uintN lineno);
     bool init(JSContext *cx, JSTreeContext::InitBehavior ib = USED_AS_CODE_GENERATOR);
 
     JSContext *context() {
         return parser->context;
     }
 
     /*
      * Release cg->codePool, cg->notePool, and parser->context->tempPool to
@@ -756,17 +744,17 @@ struct JSCodeGenerator : public JSTreeCo
 #define CG_BASE(cg)             ((cg)->current->base)
 #define CG_LIMIT(cg)            ((cg)->current->limit)
 #define CG_NEXT(cg)             ((cg)->current->next)
 #define CG_CODE(cg,offset)      (CG_BASE(cg) + (offset))
 #define CG_OFFSET(cg)           (CG_NEXT(cg) - CG_BASE(cg))
 
 #define CG_NOTES(cg)            ((cg)->current->notes)
 #define CG_NOTE_COUNT(cg)       ((cg)->current->noteCount)
-#define CG_NOTE_MASK(cg)        ((cg)->current->noteMask)
+#define CG_NOTE_LIMIT(cg)       ((cg)->current->noteLimit)
 #define CG_LAST_NOTE_OFFSET(cg) ((cg)->current->lastNoteOffset)
 #define CG_CURRENT_LINE(cg)     ((cg)->current->currentLine)
 
 #define CG_PROLOG_BASE(cg)      ((cg)->prolog.base)
 #define CG_PROLOG_LIMIT(cg)     ((cg)->prolog.limit)
 #define CG_PROLOG_NEXT(cg)      ((cg)->prolog.next)
 #define CG_PROLOG_CODE(cg,poff) (CG_PROLOG_BASE(cg) + (poff))
 #define CG_PROLOG_OFFSET(cg)    (CG_PROLOG_NEXT(cg) - CG_PROLOG_BASE(cg))
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1847,17 +1847,16 @@ fun_toSource(JSContext *cx, uintN argc, 
     vp->setString(str);
     return true;
 }
 #endif
 
 JSBool
 js_fun_call(JSContext *cx, uintN argc, Value *vp)
 {
-    LeaveTrace(cx);
     Value fval = vp[1];
 
     if (!js_IsCallable(fval)) {
         ReportIncompatibleMethod(cx, vp, &FunctionClass);
         return false;
     }
 
     Value *argv = vp + 2;
@@ -1913,18 +1912,16 @@ js_fun_apply(JSContext *cx, uintN argc, 
      * Steps 4-5 (note erratum removing steps originally numbered 5 and 7 in
      * original version of ES5).
      */
     JSObject *aobj = &vp[3].toObject();
     jsuint length;
     if (!js_GetLengthProperty(cx, aobj, &length))
         return false;
 
-    LeaveTrace(cx);
-
     /* Step 6. */
     if (length > StackSpace::ARGS_LENGTH_MAX) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TOO_MANY_FUN_APPLY_ARGS);
         return false;
     }
 
     InvokeArgsGuard args;
     if (!cx->stack.pushInvokeArgs(cx, length, &args))
@@ -2022,18 +2019,16 @@ namespace js {
 /* ES5 15.3.4.5.1 and 15.3.4.5.2. */
 JSBool
 CallOrConstructBoundFunction(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj = &vp[0].toObject();
     JS_ASSERT(obj->isFunction());
     JS_ASSERT(obj->isBoundFunction());
 
-    LeaveTrace(cx);
-
     bool constructing = IsConstructing(vp);
 
     /* 15.3.4.5.1 step 1, 15.3.4.5.2 step 3. */
     uintN argslen = obj->getBoundFunctionArgumentCount();
 
     if (argc + argslen > StackSpace::ARGS_LENGTH_MAX) {
         js_ReportAllocationOverflow(cx);
         return false;
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -529,32 +529,32 @@ Chunk::releaseArena(ArenaHeader *aheader
         rt->gcEmptyChunkListHead = this;
         rt->gcEmptyChunkCount++;
     }
 }
 
 inline Chunk *
 AllocateGCChunk(JSRuntime *rt)
 {
-    Chunk *p = (Chunk *)rt->gcChunkAllocator->alloc();
+    Chunk *p = static_cast<Chunk *>(AllocGCChunk());
 #ifdef MOZ_GCTIMER
     if (p)
         JS_ATOMIC_INCREMENT(&newChunkCount);
 #endif
     return p;
 }
 
 inline void
 ReleaseGCChunk(JSRuntime *rt, Chunk *p)
 {
     JS_ASSERT(p);
 #ifdef MOZ_GCTIMER
     JS_ATOMIC_INCREMENT(&destroyChunkCount);
 #endif
-    rt->gcChunkAllocator->free_(p);
+    FreeGCChunk(p);
 }
 
 /* The caller must hold the GC lock. */
 static Chunk *
 PickChunk(JSContext *cx)
 {
     JSCompartment *comp = cx->compartment;
     JSRuntime *rt = comp->rt;
--- a/js/src/jsgcchunk.cpp
+++ b/js/src/jsgcchunk.cpp
@@ -267,27 +267,25 @@ UnmapPages(void *addr, size_t size)
     JS_ALWAYS_TRUE(munmap(addr, size) == 0);
 #endif
 }
 
 #endif
 
 namespace js {
 
-GCChunkAllocator defaultGCChunkAllocator;
-
 inline void *
 FindChunkStart(void *p)
 {
     jsuword addr = reinterpret_cast<jsuword>(p);
     addr = (addr + GC_CHUNK_MASK) & ~GC_CHUNK_MASK;
     return reinterpret_cast<void *>(addr);
 }
 
-JS_FRIEND_API(void *)
+void *
 AllocGCChunk()
 {
     void *p;
 
 #ifdef JS_GC_HAS_MAP_ALIGN
     p = MapAlignedPages(GC_CHUNK_SIZE, GC_CHUNK_SIZE);
     if (!p)
         return NULL;
@@ -324,17 +322,17 @@ AllocGCChunk()
         }
     }
 #endif /* !JS_GC_HAS_MAP_ALIGN */
 
     JS_ASSERT(!(reinterpret_cast<jsuword>(p) & GC_CHUNK_MASK));
     return p;
 }
 
-JS_FRIEND_API(void)
+void
 FreeGCChunk(void *p)
 {
     JS_ASSERT(p);
     JS_ASSERT(!(reinterpret_cast<jsuword>(p) & GC_CHUNK_MASK));
     UnmapPages(p, GC_CHUNK_SIZE);
 }
 
 } /* namespace js */
--- a/js/src/jsgcchunk.h
+++ b/js/src/jsgcchunk.h
@@ -44,49 +44,17 @@
 #include "jsutil.h"
 
 namespace js {
 
 const size_t GC_CHUNK_SHIFT = 20;
 const size_t GC_CHUNK_SIZE = size_t(1) << GC_CHUNK_SHIFT;
 const size_t GC_CHUNK_MASK = GC_CHUNK_SIZE - 1;
 
-JS_FRIEND_API(void *)
+void *
 AllocGCChunk();
 
-JS_FRIEND_API(void)
+void
 FreeGCChunk(void *p);
 
-class GCChunkAllocator {
-  public:
-    GCChunkAllocator() {}
-    
-    void *alloc() {
-        void *chunk = doAlloc();
-        JS_ASSERT(!(reinterpret_cast<jsuword>(chunk) & GC_CHUNK_MASK));
-        return chunk;
-    }
-
-    void free_(void *chunk) {
-        JS_ASSERT(chunk);
-        JS_ASSERT(!(reinterpret_cast<jsuword>(chunk) & GC_CHUNK_MASK));
-        doFree(chunk);
-    }
-    
-  private:
-    virtual void *doAlloc() {
-        return AllocGCChunk();
-    }
-    
-    virtual void doFree(void *chunk) {
-        FreeGCChunk(chunk);
-    }
-
-    /* No copy or assignment semantics. */
-    GCChunkAllocator(const GCChunkAllocator &);
-    void operator=(const GCChunkAllocator &);
-};
-
-extern GCChunkAllocator defaultGCChunkAllocator;
-
 }
 
 #endif /* jsgchunk_h__ */
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -265,16 +265,17 @@ class CellIterImpl
     uintptr_t thing;
     Cell *cell;
 
   protected:
     CellIterImpl() {
     }
 
     void init(JSCompartment *comp, AllocKind kind) {
+        JS_ASSERT(comp->arenas.isSynchronizedFreeList(kind));
         firstThingOffset = Arena::firstThingOffset(kind);
         thingSize = Arena::thingSize(kind);
         aheader = comp->arenas.getFirstArena(kind);
         firstSpan.initAsEmpty();
         span = &firstSpan;
         thing = span->first;
         next();
     }
@@ -317,17 +318,16 @@ class CellIterImpl
     }
 };
 
 class CellIterUnderGC : public CellIterImpl {
 
   public:
     CellIterUnderGC(JSCompartment *comp, AllocKind kind) {
         JS_ASSERT(comp->rt->gcRunning);
-        comp->arenas.checkEmptyFreeList(kind);
         init(comp, kind);
     }
 };
 
 /*
  * When using the iterator outside the GC the caller must ensure that no GC or
  * allocations of GC things are possible and that the background finalization
  * for the given thing kind is not enabled or is done.
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -618,18 +618,16 @@ js::RunScript(JSContext *cx, JSScript *s
  * Find a function reference and its 'this' value implicit first parameter
  * under argc arguments on cx's stack, and call the function.  Push missing
  * required arguments, allocate declared local variables, and pop everything
  * when done.  Then push the return value.
  */
 bool
 js::InvokeKernel(JSContext *cx, const CallArgs &argsRef, MaybeConstruct construct)
 {
-    /* N.B. Must be kept in sync with InvokeSessionGuard::start/invoke */
-
     CallArgs args = argsRef;
     JS_ASSERT(args.argc() <= StackSpace::ARGS_LENGTH_MAX);
 
     JS_ASSERT(!cx->compartment->activeAnalysis);
 
     /* MaybeConstruct is a subset of InitialFrameFlags */
     InitialFrameFlags initial = (InitialFrameFlags) construct;
 
@@ -681,121 +679,19 @@ js::InvokeKernel(JSContext *cx, const Ca
     }
 
     args.rval() = fp->returnValue();
     JS_ASSERT_IF(ok && construct, !args.rval().isPrimitive());
     return ok;
 }
 
 bool
-InvokeSessionGuard::start(JSContext *cx, const Value &calleev, const Value &thisv, uintN argc)
-{
-#ifdef JS_TRACER
-    if (TRACE_RECORDER(cx))
-        AbortRecording(cx, "attempt to reenter VM while recording");
-    LeaveTrace(cx);
-#endif
-
-    /* Always push arguments, regardless of optimized/normal invoke. */
-    ContextStack &stack = cx->stack;
-    if (!stack.pushInvokeArgs(cx, argc, &args_))
-        return false;
-
-    /* Callees may clobber 'this' or 'callee'. */
-    savedCallee_ = args_.calleev() = calleev;
-    savedThis_ = args_.thisv() = thisv;
-
-    /* If anyone (through jsdbgapi) finds this frame, make it safe. */
-    MakeRangeGCSafe(args_.argv(), args_.argc());
-
-    do {
-        /* Hoist dynamic checks from scripted Invoke. */
-        if (!calleev.isObject())
-            break;
-        JSObject &callee = calleev.toObject();
-        if (callee.getClass() != &FunctionClass)
-            break;
-        JSFunction *fun = callee.getFunctionPrivate();
-        if (fun->isNative())
-            break;
-        script_ = fun->script();
-        if (!script_->ensureRanAnalysis(cx, fun, callee.getParent()))
-            return false;
-        if (FunctionNeedsPrologue(cx, fun) || script_->isEmpty())
-            break;
-
-        /*
-         * The frame will remain pushed even when the callee isn't active which
-         * will affect the observable current global, so avoid any change.
-         */
-        if (callee.getGlobal() != GetGlobalForScopeChain(cx))
-            break;
-
-        /* Push the stack frame once for the session. */
-        if (!stack.pushInvokeFrame(cx, args_, INITIAL_NONE, &ifg_))
-            return false;
-
-        /*
-         * Update the 'this' type of the callee according to the value given,
-         * along with the types of any missing arguments. These will be the
-         * same across all calls.
-         */
-        TypeScript::SetThis(cx, script_, thisv);
-        for (unsigned i = argc; i < fun->nargs; i++)
-            TypeScript::SetArgument(cx, script_, i, types::Type::UndefinedType());
-
-        StackFrame *fp = ifg_.fp();
-#ifdef JS_METHODJIT
-        /* Hoist dynamic checks from RunScript. */
-        mjit::CompileStatus status = mjit::CanMethodJIT(cx, script_, false,
-                                                        mjit::CompileRequest_JIT);
-        if (status == mjit::Compile_Error)
-            return false;
-        if (status != mjit::Compile_Okay)
-            break;
-        /* Cannot also cache the raw code pointer; it can change. */
-
-        /* Hoist dynamic checks from CheckStackAndEnterMethodJIT. */
-        JS_CHECK_RECURSION(cx, return false);
-        stackLimit_ = stack.space().getStackLimit(cx, REPORT_ERROR);
-        if (!stackLimit_)
-            return false;
-
-        stop_ = script_->code + script_->length - 1;
-        JS_ASSERT(*stop_ == JSOP_STOP);
-#endif
-
-        /* Cached to avoid canonicalActualArg in InvokeSessionGuard::operator[]. */
-        nformals_ = fp->numFormalArgs();
-        formals_ = fp->formalArgs();
-        actuals_ = args_.argv();
-        JS_ASSERT(actuals_ == fp->actualArgs());
-        return true;
-    } while (0);
-
-    /*
-     * Use the normal invoke path.
-     *
-     * The callee slot gets overwritten during an unoptimized Invoke, so we
-     * cache it here and restore it before every Invoke call. The 'this' value
-     * does not get overwritten, so we can fill it here once.
-     */
-    if (ifg_.pushed())
-        ifg_.pop();
-    formals_ = actuals_ = args_.argv();
-    nformals_ = (unsigned)-1;
-    return true;
-}
-
-bool
 js::Invoke(JSContext *cx, const Value &thisv, const Value &fval, uintN argc, Value *argv,
            Value *rval)
 {
-    LeaveTrace(cx);
-
     InvokeArgsGuard args;
     if (!cx->stack.pushInvokeArgs(cx, argc, &args))
         return false;
 
     args.calleev() = fval;
     args.thisv() = thisv;
     memcpy(args.argv(), argv, argc * sizeof(Value));
 
@@ -816,18 +712,16 @@ js::Invoke(JSContext *cx, const Value &t
 
     *rval = args.rval();
     return true;
 }
 
 bool
 js::InvokeConstructor(JSContext *cx, const Value &fval, uintN argc, Value *argv, Value *rval)
 {
-    LeaveTrace(cx);
-
     InvokeArgsGuard args;
     if (!cx->stack.pushInvokeArgs(cx, argc, &args))
         return false;
 
     args.calleev() = fval;
     args.thisv().setMagic(JS_THIS_POISON);
     memcpy(args.argv(), argv, argc * sizeof(Value));
 
@@ -1239,18 +1133,16 @@ error:
     js_ReportIsNotFunction(cx, &args.calleev(), JSV2F_CONSTRUCT);
     return false;
 }
 
 bool
 js::InvokeConstructorWithGivenThis(JSContext *cx, JSObject *thisobj, const Value &fval,
                                    uintN argc, Value *argv, Value *rval)
 {
-    LeaveTrace(cx);
-
     InvokeArgsGuard args;
     if (!cx->stack.pushInvokeArgs(cx, argc, &args))
         return JS_FALSE;
 
     args.calleev() = fval;
     /* Initialize args.thisv on all paths below. */
     memcpy(args.argv(), argv, argc * sizeof(Value));
 
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -183,42 +183,16 @@ Invoke(JSContext *cx, const Value &thisv
  * This helper takes care of the infinite-recursion check necessary for
  * getter/setter calls.
  */
 extern bool
 InvokeGetterOrSetter(JSContext *cx, JSObject *obj, const Value &fval, uintN argc, Value *argv,
                      Value *rval);
 
 /*
- * Natives like sort/forEach/replace call Invoke repeatedly with the same
- * callee, this, and number of arguments. To optimize this, such natives can
- * start an "invoke session" to factor out much of the dynamic setup logic
- * required by a normal Invoke. Usage is:
- *
- *   InvokeSessionGuard session(cx);
- *   if (!session.start(cx, callee, thisp, argc, &session))
- *     ...
- *
- *   while (...) {
- *     // write actual args (not callee, this)
- *     session[0] = ...
- *     ...
- *     session[argc - 1] = ...
- *
- *     if (!session.invoke(cx, session))
- *       ...
- *
- *     ... = session.rval();
- *   }
- *
- *   // session ended by ~InvokeSessionGuard
- */
-class InvokeSessionGuard;
-
-/*
  * InvokeConstructor* implement a function call from a constructor context
  * (e.g. 'new') handling the the creation of the new 'this' object.
  */
 extern JS_REQUIRES_STACK bool
 InvokeConstructorKernel(JSContext *cx, const CallArgs &args);
 
 /* See the InvokeArgsGuard overload of Invoke. */
 inline bool
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -66,137 +66,16 @@ class AutoPreserveEnumerators {
     }
 
     ~AutoPreserveEnumerators()
     {
         cx->enumerators = enumerators;
     }
 };
 
-class InvokeSessionGuard
-{
-    InvokeArgsGuard args_;
-    InvokeFrameGuard ifg_;
-    Value savedCallee_, savedThis_;
-    Value *formals_, *actuals_;
-    unsigned nformals_;
-    JSScript *script_;
-    Value *stackLimit_;
-    jsbytecode *stop_;
-
-    bool optimized() const { return ifg_.pushed(); }
-
-  public:
-    InvokeSessionGuard() : args_(), ifg_() {}
-    ~InvokeSessionGuard() {}
-
-    bool start(JSContext *cx, const Value &callee, const Value &thisv, uintN argc);
-    bool invoke(JSContext *cx);
-
-    bool started() const {
-        return args_.pushed();
-    }
-
-    Value &operator[](unsigned i) const {
-        JS_ASSERT(i < argc());
-        Value &arg = i < nformals_ ? formals_[i] : actuals_[i];
-        JS_ASSERT_IF(optimized(), &arg == &ifg_.fp()->canonicalActualArg(i));
-        JS_ASSERT_IF(!optimized(), &arg == &args_[i]);
-        return arg;
-    }
-
-    uintN argc() const {
-        return args_.argc();
-    }
-
-    const Value &rval() const {
-        return optimized() ? ifg_.fp()->returnValue() : args_.rval();
-    }
-};
-
-inline bool
-InvokeSessionGuard::invoke(JSContext *cx)
-{
-    /* N.B. Must be kept in sync with Invoke */
-
-    /* Refer to canonical (callee, this) for optimized() sessions. */
-    formals_[-2] = savedCallee_;
-    formals_[-1] = savedThis_;
-
-    /* Prevent spurious accessing-callee-after-rval assert. */
-    args_.calleeHasBeenReset();
-
-    if (!optimized())
-        return Invoke(cx, args_);
-
-    /*
-     * Update the types of each argument. The 'this' type and missing argument
-     * types were handled when the invoke session was created.
-     */
-    for (unsigned i = 0; i < Min(argc(), nformals_); i++)
-        types::TypeScript::SetArgument(cx, script_, i, (*this)[i]);
-
-#ifdef JS_METHODJIT
-    mjit::JITScript *jit = script_->getJIT(false /* !constructing */);
-    if (!jit) {
-        /* Watch in case the code was thrown away due a recompile. */
-        mjit::CompileStatus status = mjit::TryCompile(cx, script_, false);
-        if (status == mjit::Compile_Error)
-            return false;
-        JS_ASSERT(status == mjit::Compile_Okay);
-        jit = script_->getJIT(false);
-    }
-    void *code;
-    if (!(code = jit->invokeEntry))
-        return Invoke(cx, args_);
-#endif
-
-    StackFrame *fp = ifg_.fp();
-
-    /*
-     * Clear any activation objects on the frame. Normally the frame should not
-     * have any, but since we leave it on the stack between calls to invoke()
-     * the debugger can start operating on it. See markFunctionEpilogueDone()
-     * calls below. :XXX: this is pretty gross, and slows us down. Can the
-     * debugger be prevented from observing this frame?
-     */
-    fp->functionEpilogue(/* activationOnly = */ true);
-    fp->markFunctionEpilogueDone(/* activationOnly = */ true);
-
-    fp->resetCallFrame(script_);
-
-    JSBool ok;
-    {
-        AutoPreserveEnumerators preserve(cx);
-        args_.setActive();  /* From js::Invoke(InvokeArgsGuard) overload. */
-        Probes::enterJSFun(cx, fp->fun(), script_);
-#ifdef JS_METHODJIT
-        ok = mjit::EnterMethodJIT(cx, fp, code, stackLimit_, /* partial = */ false);
-        cx->regs().pc = stop_;
-#else
-        cx->regs().pc = script_->code;
-        ok = Interpret(cx, cx->fp());
-
-        /* Interpret does not perform the entry frame's epilogue, unlike EnterMethodJIT. */
-        cx->fp()->functionEpilogue();
-#endif
-        Probes::exitJSFun(cx, fp->fun(), script_);
-        args_.setInactive();
-    }
-
-    /*
-     * Clear activation object flags, for the functionEpilogue() call in the
-     * next invoke().
-     */
-    fp->markFunctionEpilogueDone(/* activationOnly = */ true);
-
-    /* Don't clobber callee with rval; rval gets read from fp->rval. */
-    return ok;
-}
-
 namespace detail {
 
 template<typename T> class PrimitiveBehavior { };
 
 template<>
 class PrimitiveBehavior<JSString *> {
   public:
     static inline bool isType(const Value &v) { return v.isString(); }
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -297,17 +297,16 @@ PreprocessValue(JSContext *cx, JSObject 
         if (!js_GetMethod(cx, &vp->toObject(), id, JSGET_NO_METHOD_BARRIER, &toJSON))
             return false;
 
         if (js_IsCallable(toJSON)) {
             keyStr = IdToString(cx, key);
             if (!keyStr)
                 return false;
 
-            LeaveTrace(cx);
             InvokeArgsGuard args;
             if (!cx->stack.pushInvokeArgs(cx, 1, &args))
                 return false;
 
             args.calleev() = toJSON;
             args.thisv() = *vp;
             args[0] = StringValue(keyStr);
 
--- a/js/src/jsparse.cpp
+++ b/js/src/jsparse.cpp
@@ -898,17 +898,16 @@ Compiler::Compiler(JSContext *cx, JSPrin
 JSScript *
 Compiler::compileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerFrame,
                         JSPrincipals *principals, uint32 tcflags,
                         const jschar *chars, size_t length,
                         const char *filename, uintN lineno, JSVersion version,
                         JSString *source /* = NULL */,
                         uintN staticLevel /* = 0 */)
 {
-    JSArenaPool codePool, notePool;
     TokenKind tt;
     JSParseNode *pn;
     JSScript *script;
     bool inDirectivePrologue;
 
     JS_ASSERT(!(tcflags & ~(TCF_COMPILE_N_GO | TCF_NO_SCRIPT_RVAL | TCF_NEED_MUTABLE_SCRIPT |
                             TCF_COMPILE_FOR_EVAL | TCF_NEED_SCRIPT_OBJECT)));
 
@@ -918,23 +917,20 @@ Compiler::compileScript(JSContext *cx, J
      */
     JS_ASSERT_IF(callerFrame, tcflags & TCF_COMPILE_N_GO);
     JS_ASSERT_IF(staticLevel != 0, callerFrame);
 
     Compiler compiler(cx, principals, callerFrame);
     if (!compiler.init(chars, length, filename, lineno, version))
         return NULL;
 
-    JS_InitArenaPool(&codePool, "code", 1024, sizeof(jsbytecode));
-    JS_InitArenaPool(&notePool, "note", 1024, sizeof(jssrcnote));
-
     Parser &parser = compiler.parser;
     TokenStream &tokenStream = parser.tokenStream;
 
-    JSCodeGenerator cg(&parser, &codePool, &notePool, tokenStream.getLineno());
+    JSCodeGenerator cg(&parser, tokenStream.getLineno());
     if (!cg.init(cx, JSTreeContext::USED_AS_TREE_CONTEXT))
         return NULL;
 
     Probes::compileScriptBegin(cx, filename, lineno);
 
     MUST_FLOW_THROUGH("out");
 
     // We can specialize a bit for the given scope chain if that scope chain is the global object.
@@ -1113,18 +1109,16 @@ Compiler::compileScript(JSContext *cx, J
         goto out;
 
     JS_ASSERT(script->savedCallerFun == savedCallerFun);
 
     if (!defineGlobals(cx, globalScope, script))
         script = NULL;
 
   out:
-    JS_FinishArenaPool(&codePool);
-    JS_FinishArenaPool(&notePool);
     Probes::compileScriptEnd(cx, script, filename, lineno);
     return script;
 
   too_many_slots:
     parser.reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_TOO_MANY_LOCALS);
     script = NULL;
     goto out;
 }
@@ -1777,25 +1771,20 @@ Compiler::compileFunctionBody(JSContext 
                               Bindings *bindings, const jschar *chars, size_t length,
                               const char *filename, uintN lineno, JSVersion version)
 {
     Compiler compiler(cx, principals);
 
     if (!compiler.init(chars, length, filename, lineno, version))
         return false;
 
-    /* No early return from after here until the js_FinishArenaPool calls. */
-    JSArenaPool codePool, notePool;
-    JS_InitArenaPool(&codePool, "code", 1024, sizeof(jsbytecode));
-    JS_InitArenaPool(&notePool, "note", 1024, sizeof(jssrcnote));
-
     Parser &parser = compiler.parser;
     TokenStream &tokenStream = parser.tokenStream;
 
-    JSCodeGenerator funcg(&parser, &codePool, &notePool, tokenStream.getLineno());
+    JSCodeGenerator funcg(&parser, tokenStream.getLineno());
     if (!funcg.init(cx, JSTreeContext::USED_AS_TREE_CONTEXT))
         return false;
 
     funcg.flags |= TCF_IN_FUNCTION;
     funcg.setFunction(fun);
     funcg.bindings.transfer(cx, bindings);
     fun->setArgCount(funcg.bindings.countArgs());
     if (!GenerateBlockId(&funcg, funcg.bodyid))
@@ -1855,19 +1844,16 @@ Compiler::compileFunctionBody(JSContext 
                 pn = fn->pn_body;
             }
 
             if (!js_EmitFunctionScript(cx, &funcg, pn))
                 pn = NULL;
         }
     }
 
-    /* Restore saved state and release code generation arenas. */
-    JS_FinishArenaPool(&codePool);
-    JS_FinishArenaPool(&notePool);
     return pn != NULL;
 }
 
 /*
  * Parameter block types for the several Binder functions.  We use a common
  * helper function signature in order to share code among destructuring and
  * simple variable declaration parsers.  In the destructuring case, the binder
  * function is called indirectly from the variable declaration parser by way
--- a/js/src/jsprvtd.h
+++ b/js/src/jsprvtd.h
@@ -129,17 +129,16 @@ namespace js {
 struct ArgumentsData;
 
 class RegExp;
 class RegExpStatics;
 class AutoStringRooter;
 class ExecuteArgsGuard;
 class InvokeFrameGuard;
 class InvokeArgsGuard;
-class InvokeSessionGuard;
 class StringBuffer;
 class TraceRecorder;
 struct TraceMonitor;
 
 class FrameRegs;
 class StackFrame;
 class StackSegment;
 class StackSpace;
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -1617,18 +1617,17 @@ struct ReplaceData
     JSObject           *lambda;        /* replacement function object or null */
     JSObject           *elembase;      /* object for function(a){return b[a]} replace */
     JSLinearString     *repstr;        /* replacement string */
     const jschar       *dollar;        /* null or pointer to first $ in repstr */
     const jschar       *dollarEnd;     /* limit pointer for js_strchr_limit */
     jsint              leftIndex;      /* left context index in str->chars */
     JSSubString        dollarStr;      /* for "$$" InterpretDollar result */
     bool               calledBack;     /* record whether callback has been called */
-    InvokeSessionGuard session;        /* arguments for repeated lambda Invoke call */
-    InvokeArgsGuard    singleShot;     /* arguments for single lambda Invoke call */
+    InvokeArgsGuard    args;           /* arguments for lambda call */
     StringBuffer       sb;             /* buffer built during DoMatch */
 };
 
 static bool
 InterpretDollar(JSContext *cx, RegExpStatics *res, const jschar *dp, const jschar *ep,
                 ReplaceData &rdata, JSSubString *out, size_t *skip)
 {
     JS_ASSERT(*dp == '$');
@@ -1745,57 +1744,58 @@ FindReplaceLength(JSContext *cx, RegExpS
          * Couldn't handle this property, fall through and despecialize to the
          * general lambda case.
          */
         rdata.elembase = NULL;
     }
 
     JSObject *lambda = rdata.lambda;
     if (lambda) {
+        PreserveRegExpStatics staticsGuard(res);
+        if (!staticsGuard.init(cx))
+            return false;
+
         /*
          * In the lambda case, not only do we find the replacement string's
          * length, we compute repstr and return it via rdata for use within
          * DoReplace.  The lambda is called with arguments ($&, $1, $2, ...,
          * index, input), i.e., all the properties of a regexp match array.
          * For $&, etc., we must create string jsvals from cx->regExpStatics.
          * We grab up stack space to keep the newborn strings GC-rooted.
          */
         uintN p = res->parenCount();
         uintN argc = 1 + p + 2;
 
-        InvokeSessionGuard &session = rdata.session;
-        if (!session.started()) {
-            Value lambdav = ObjectValue(*lambda);
-            if (!session.start(cx, lambdav, UndefinedValue(), argc))
-                return false;
-        }
-
-        PreserveRegExpStatics staticsGuard(res);
-        if (!staticsGuard.init(cx))
+        InvokeArgsGuard &args = rdata.args;
+        if (!args.pushed() && !cx->stack.pushInvokeArgs(cx, argc, &args))
             return false;
 
+        args.calleeHasBeenReset();
+        args.calleev() = ObjectValue(*lambda);
+        args.thisv() = UndefinedValue();
+
         /* Push $&, $1, $2, ... */
         uintN argi = 0;
-        if (!res->createLastMatch(cx, &session[argi++]))
+        if (!res->createLastMatch(cx, &args[argi++]))
             return false;
 
         for (size_t i = 0; i < res->parenCount(); ++i) {
-            if (!res->createParen(cx, i + 1, &session[argi++]))
+            if (!res->createParen(cx, i + 1, &args[argi++]))
                 return false;
         }
 
         /* Push match index and input string. */
-        session[argi++].setInt32(res->matchStart());
-        session[argi].setString(rdata.str);
-
-        if (!session.invoke(cx))
+        args[argi++].setInt32(res->matchStart());
+        args[argi].setString(rdata.str);
+
+        if (!Invoke(cx, args))
             return false;
 
         /* root repstr: rdata is on the stack, so scanned by conservative gc. */
-        JSString *repstr = ValueToString_TestForStringInline(cx, session.rval());
+        JSString *repstr = ValueToString_TestForStringInline(cx, args.rval());
         if (!repstr)
             return false;
         rdata.repstr = repstr->ensureLinear(cx);
         if (!rdata.repstr)
             return false;
         *sizep = rdata.repstr->length();
         return true;
     }
@@ -2069,37 +2069,36 @@ str_replace_regexp(JSContext *cx, uintN 
     return true;
 }
 
 static inline bool
 str_replace_flat_lambda(JSContext *cx, uintN argc, Value *vp, ReplaceData &rdata,
                         const FlatMatch &fm)
 {
     JS_ASSERT(fm.match() >= 0);
-    LeaveTrace(cx);
 
     JSString *matchStr = js_NewDependentString(cx, rdata.str, fm.match(), fm.patternLength());
     if (!matchStr)
         return false;
 
     /* lambda(matchStr, matchStart, textstr) */
     static const uint32 lambdaArgc = 3;
-    if (!cx->stack.pushInvokeArgs(cx, lambdaArgc, &rdata.singleShot))
+    if (!cx->stack.pushInvokeArgs(cx, lambdaArgc, &rdata.args))
         return false;
 
-    CallArgs &args = rdata.singleShot;
+    CallArgs &args = rdata.args;
     args.calleev().setObject(*rdata.lambda);
     args.thisv().setUndefined();
 
     Value *sp = args.argv();
     sp[0].setString(matchStr);
     sp[1].setInt32(fm.match());
     sp[2].setString(rdata.str);
 
-    if (!Invoke(cx, rdata.singleShot))
+    if (!Invoke(cx, rdata.args))
         return false;
 
     JSString *repstr = js_ValueToString(cx, args.rval());
     if (!repstr)
         return false;
 
     JSString *leftSide = js_NewDependentString(cx, rdata.str, 0, fm.match());
     if (!leftSide)
--- a/js/src/methodjit/BaseAssembler.h
+++ b/js/src/methodjit/BaseAssembler.h
@@ -1234,17 +1234,17 @@ static const JSC::MacroAssembler::Regist
      * to result and filling it in according to templateObject. Returns a jump
      * taken if a free thing was not retrieved.
      */
     Jump getNewObject(JSContext *cx, RegisterID result, JSObject *templateObject)
     {
         gc::AllocKind allocKind = templateObject->getAllocKind();
 
         JS_ASSERT(allocKind >= gc::FINALIZE_OBJECT0 && allocKind <= gc::FINALIZE_OBJECT_LAST);
-        size_t thingSize = gc::Arena::thingSize(allocKind);
+        int thingSize = (int)gc::Arena::thingSize(allocKind);
 
         JS_ASSERT(cx->typeInferenceEnabled());
         JS_ASSERT(!templateObject->hasSlotsArray());
 
 #ifdef JS_GC_ZEAL
         if (cx->runtime->needZealousGC())
             return jump();
 #endif
@@ -1275,17 +1275,17 @@ static const JSC::MacroAssembler::Regist
         /*
          * Write out the slots pointer before readjusting the result register,
          * as for dense arrays we will need to get the address of the fixed
          * slots first.
          */
         if (templateObject->isDenseArray()) {
             JS_ASSERT(!templateObject->initializedLength);
             addPtr(Imm32(-thingSize + sizeof(JSObject)), result);
-            storePtr(result, Address(result, -sizeof(JSObject) + JSObject::offsetOfSlots()));
+            storePtr(result, Address(result, -(int)sizeof(JSObject) + JSObject::offsetOfSlots()));
             addPtr(Imm32(-(int)sizeof(JSObject)), result);
         } else {
             JS_ASSERT(!templateObject->newType);
             addPtr(Imm32(-thingSize), result);
             storePtr(ImmPtr(NULL), Address(result, JSObject::offsetOfSlots()));
         }
 
         storePtr(ImmPtr(templateObject->lastProp), Address(result, offsetof(JSObject, lastProp)));
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -4081,17 +4081,17 @@ SumJitDataSizeCallback(JSContext *cx, vo
 
 #endif
 
 JSBool
 MJitDataStats(JSContext *cx, uintN argc, jsval *vp)
 {
 #ifdef JS_METHODJIT
     size_t n = 0;
-    IterateCells(cx, NULL, gc::FINALIZE_TYPE_OBJECT, &n, SumJitDataSizeCallback);
+    IterateCells(cx, NULL, gc::FINALIZE_SCRIPT, &n, SumJitDataSizeCallback);
     JS_SET_RVAL(cx, vp, INT_TO_JSVAL(n));
 #else
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
 #endif
     return true;
 }
 
 JSBool
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -398,17 +398,17 @@ class Debugger {
   private:
     /* Prohibit copying. */
     Debugger(const Debugger &);
     Debugger & operator=(const Debugger &);
 };
 
 class BreakpointSite {
     friend class js::Breakpoint;
-    friend class ::JSCompartment;
+    friend struct ::JSCompartment;
     friend class js::Debugger;
 
   public:
     JSScript * const script;
     jsbytecode * const pc;
     const JSOp realOpcode;
 
   private:
@@ -455,17 +455,17 @@ class BreakpointSite {
  * Debugger::hasAnyLiveHooks to check for rule 1.
  *
  * Nothing else causes a breakpoint to be retained, so if its script or
  * debugger is collected, the breakpoint is destroyed during GC sweep phase,
  * even if the debugger compartment isn't being GC'd. This is implemented in
  * JSCompartment::sweepBreakpoints.
  */
 class Breakpoint {
-    friend class ::JSCompartment;
+    friend struct ::JSCompartment;
     friend class js::Debugger;
 
   public:
     Debugger * const debugger;
     BreakpointSite * const site;
   private:
     JSObject *handler;
     JSCList debuggerLinks;
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -639,16 +639,17 @@ ContextStack::popSegment()
 
     if (!seg_)
         cx_->maybeMigrateVersionOverride();
 }
 
 bool
 ContextStack::pushInvokeArgs(JSContext *cx, uintN argc, InvokeArgsGuard *iag)
 {
+    LeaveTrace(cx);
     JS_ASSERT(argc <= StackSpace::ARGS_LENGTH_MAX);
 
     uintN nvars = 2 + argc;
     Value *firstUnused = ensureOnTop(cx, REPORT_ERROR, nvars, CAN_EXTEND, &iag->pushedSeg_);
     if (!firstUnused)
         return false;
 
     ImplicitCast<CallArgs>(*iag) = CallArgsFromVp(argc, firstUnused);
@@ -1014,23 +1015,16 @@ StackIter::settleOnNewState()
          */
         if (containsFrame && (!containsCall || (Value *)fp_ >= calls_->argv())) {
             /* Nobody wants to see dummy frames. */
             if (fp_->isDummyFrame()) {
                 popFrame();
                 continue;
             }
 
-            /* Censor pushed-but-not-active frames from InvokeSessionGuard. */
-            if (containsCall && !calls_->active() && fp_->hasArgs() &&
-                calls_->argv() == fp_->actualArgs()) {
-                popFrame();
-                continue;
-            }
-
             /*
              * As an optimization, there is no CallArgsList element pushed for
              * natives called directly by a script (compiled or interpreted).
              * We catch these by inspecting the bytecode and stack. This check
              * relies on the property that, at a call opcode,
              *
              *   regs.sp == vp + 2 + argc
              *
--- a/js/src/xpconnect/src/xpcjsruntime.cpp
+++ b/js/src/xpconnect/src/xpcjsruntime.cpp
@@ -1443,51 +1443,17 @@ MakeMemoryReporterPath(const nsACString 
                        const char (&reporterName)[N])
 {
   return pathPrefix + NS_LITERAL_CSTRING("compartment(") + compartmentName +
          NS_LITERAL_CSTRING(")/") + nsDependentCString(reporterName);
 }
 
 } // anonymous namespace
 
-class XPConnectGCChunkAllocator
-    : public js::GCChunkAllocator
-{
-public:
-    XPConnectGCChunkAllocator() {}
-
-private:
-    virtual void *doAlloc() {
-        void *chunk;
-#ifdef MOZ_MEMORY
-        // posix_memalign returns zero on success, nonzero on failure.
-        if (posix_memalign(&chunk, js::GC_CHUNK_SIZE, js::GC_CHUNK_SIZE))
-            chunk = 0;
-#else
-        chunk = js::AllocGCChunk();
-#endif
-        return chunk;
-    }
-
-    virtual void doFree(void *chunk) {
-#ifdef MOZ_MEMORY
-        free(chunk);
-#else
-        js::FreeGCChunk(chunk);
-#endif
-    }
-};
-
-static XPConnectGCChunkAllocator gXPCJSChunkAllocator;
-
-#ifdef MOZ_MEMORY
-#define JS_GC_HEAP_KIND  nsIMemoryReporter::KIND_HEAP
-#else
 #define JS_GC_HEAP_KIND  nsIMemoryReporter::KIND_NONHEAP
-#endif
 
 // We have per-compartment GC heap totals, so we can't put the total GC heap
 // size in the explicit allocations tree.  But it's a useful figure, so put it
 // in the "others" list.
 
 static PRInt64
 GetGCChunkTotalBytes()
 {
@@ -2085,18 +2051,16 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* 
         JS_EnumerateDiagnosticMemoryRegions(DiagnosticMemoryCallback);
 #endif
         mWatchdogWakeup = JS_NEW_CONDVAR(mJSRuntime->gcLock);
         if (!mWatchdogWakeup)
             NS_RUNTIMEABORT("JS_NEW_CONDVAR failed.");
 
         mJSRuntime->setActivityCallback(ActivityCallback, this);
 
-        mJSRuntime->setCustomGCChunkAllocator(&gXPCJSChunkAllocator);
-
         NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSGCHeap));
         NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSSystemCompartmentCount));
         NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSUserCompartmentCount));
         NS_RegisterMemoryMultiReporter(new XPConnectJSCompartmentsMultiReporter);
     }
 
     if(!JS_DHashTableInit(&mJSHolders, JS_DHashGetStubOps(), nsnull,
                           sizeof(ObjectHolder), 512))
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -1898,36 +1898,39 @@ InternalInvalidateThebesLayersInSubtree(
   PRBool foundContainerLayer = PR_FALSE;
   if (aFrame->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER) {
     // Delete the invalid region to indicate that all Thebes contents
     // need to be invalidated
     aFrame->Properties().Delete(ThebesLayerInvalidRegionProperty());
     foundContainerLayer = PR_TRUE;
   }
 
-  nsIFrame* frame = aFrame;
-  while (frame) {
-    nsIFrame::ChildListIterator lists(frame);
-    for (; !lists.IsDone(); lists.Next()) {
-      nsFrameList::Enumerator childFrames(lists.CurrentList());
-      for (; !childFrames.AtEnd(); childFrames.Next()) {
-        if (InternalInvalidateThebesLayersInSubtree(childFrames.get())) {
-          foundContainerLayer = PR_TRUE;
-        }
+  nsAutoTArray<nsIFrame::ChildList,4> childListArray;
+  if (!aFrame->GetFirstPrincipalChild()) {
+    nsSubDocumentFrame* subdocumentFrame = do_QueryFrame(aFrame);
+    if (subdocumentFrame) {
+      // Descend into the subdocument
+      nsIFrame* root = subdocumentFrame->GetSubdocumentRootFrame();
+      if (root) {
+        childListArray.AppendElement(nsIFrame::ChildList(
+          nsFrameList(root, nsLayoutUtils::GetLastSibling(root)),
+          nsIFrame::kPrincipalList));
       }
     }
-    if (frame == aFrame && !frame->GetFirstPrincipalChild()) {
-      nsSubDocumentFrame* subdocumentFrame = do_QueryFrame(frame);
-      if (subdocumentFrame) {
-        // Descend into the subdocument
-        frame = subdocumentFrame->GetSubdocumentRootFrame();
-        continue;
+  }
+
+  aFrame->GetChildLists(&childListArray);
+  nsIFrame::ChildListArrayIterator lists(childListArray);
+  for (; !lists.IsDone(); lists.Next()) {
+    nsFrameList::Enumerator childFrames(lists.CurrentList());
+    for (; !childFrames.AtEnd(); childFrames.Next()) {
+      if (InternalInvalidateThebesLayersInSubtree(childFrames.get())) {
+        foundContainerLayer = PR_TRUE;
       }
     }
-    break;
   }
 
   if (!foundContainerLayer) {
     aFrame->RemoveStateBits(NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT);
   }
   return foundContainerLayer;
 }
 
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -36,20 +36,20 @@ asserts(1) load 243519-1.html # bug 5366
 load 244490-1.html
 load 254367-1.html
 load 263359-1.html
 load 265027-1.html
 load 265736-1.html
 load 265736-2.html
 asserts(2) load 265899-1.html # bug 575011
 load 265973-1.html
-asserts(8-12) load 265986-1.html # Bug 512405
-asserts(4) load 265999-1.html # bug 575011
+asserts(6-12) load 265986-1.html # Bug 512405
+asserts(2-4) load 265999-1.html # bug 575011
 load 266222-1.html
-asserts(5-7) load 266360-1.html # bug 575011 / bug 576358
+asserts(3-7) load 266360-1.html # bug 575011 / bug 576358
 asserts(4) load 266445-1.html # Bug 575011
 load 268157-1.html
 load 269566-1.html
 load 272647-1.html
 load 275746-1.html
 load 276053-1.html
 load 280708-1.html
 load 280708-2.html
@@ -252,22 +252,22 @@ load 468578-1.xhtml
 load 468645-1.xhtml
 load 468645-2.xhtml
 load 468645-3.xhtml
 load 469861-1.xhtml
 load 469861-2.xhtml
 load 471594-1.xhtml
 load 479114-1.html
 load 477333-1.xhtml
-load 477731-1.html
+asserts-if(Android,6) load 477731-1.html
 # 479360-1.xhtml will assert 6 times due to bug 439258 and then make the test
 # after the test after it also assert 6 times.
-asserts(6) load 479360-1.xhtml # Bug 439258
-load 480686-1.html
-asserts(6) load 481806-1.html  # Bug 439258
+asserts-if(!Android,6) load 479360-1.xhtml # Bug 439258
+asserts-if(Android,6) load 480686-1.html
+asserts-if(!Android,6) load 481806-1.html  # Bug 439258
 load 483604-1.xhtml
 load 485501-1.html
 load 487544-1.html
 load 488390-1.xhtml
 load 489691.html
 load 490376-1.xhtml
 load 490559-1.html
 load 490747.html
--- a/layout/forms/crashtests/crashtests.list
+++ b/layout/forms/crashtests/crashtests.list
@@ -15,21 +15,21 @@ load 363696-1.xul
 load 363696-2.html
 load 363696-3.html
 load 366205-1.html
 load 366537-1.xhtml
 load 367587-1.html
 load 370703-1.html
 load 370940-1.html
 load 373586-1.xhtml
-asserts(8-10) load 378413-1.xhtml # bug 424225, bug 402850?
+asserts(5-10) load 378413-1.xhtml # bug 424225, bug 402850?
 load 380116-1.xhtml
 load 382212-1.xhtml
 load 382610-1.html
-asserts-if(winWidget,1) load 383887-1.html # bug 576434
+asserts-if(winWidget||Android,1) load 383887-1.html # bug 576434
 load 386554-1.html
 load 388374-1.xhtml
 load 388374-2.html
 load 393656-1.xhtml
 load 393656-2.xhtml
 load 402852-1.html
 load 403148-1.html
 load 404118-1.html
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -66,17 +66,17 @@ load 370866-1.xhtml
 load 370884-1.xhtml
 load 371348-1.xhtml
 load 371561-1.html
 load 371566-1.xhtml
 load 372376-1.xhtml
 load 373859-1.html
 load 373868-1.xhtml
 load 379217-1.xhtml
-asserts(2) load 379217-2.xhtml # Bug 439204
+asserts(1-2) load 379217-2.xhtml # Bug 439204
 load 379917-1.xhtml
 load 380012-1.html
 load 381152-1.html
 load 381786-1.html
 asserts-if(gtk2Widget,0-2) load 382129-1.xhtml # Bug 540078
 asserts-if(gtk2Widget,0-1) load 382131-1.html # Bug 540078
 load 382199-1.html
 load 382208-1.xhtml
@@ -119,17 +119,17 @@ load 393906-1.html
 load 393923-1.html
 load 393956-1.html
 load 393956-2.html
 load 393956-3.html
 load 393956-4.html
 load 394237-1.html
 load 394820-1.html
 load 394818-1.html
-load 394818-2.html
+asserts-if(Android,1) load 394818-2.html
 load 395316-1.html
 load 395450-1.xhtml
 load 397007-1.html
 load 397187-1.html
 load 397844-1.xhtml
 load 397844-2.xhtml
 load 397852-1.xhtml
 load 398181-1.html
@@ -178,18 +178,18 @@ load 413048-1.html
 load 413079-1.xhtml
 load 413079-2.xhtml
 load 413079-3.xhtml
 load 413085-1.html
 load 413085-2.html
 load 413582-1.xhtml
 load 413582-2.html
 load 413712-1.xhtml
-load 414061-1.html
-asserts(6) load 414180-1.xul # Bug 439258
+asserts-if(Android,6) load 414061-1.html
+asserts-if(!Android,6) load 414180-1.xul # Bug 439258
 load 414719-1.html
 load 415685-1.html
 load 416264-1.html
 load 416476-1.html
 load 417109-1.xhtml
 load 417902-1.html
 load 417902-2.html
 load 418532-1.html
@@ -275,17 +275,17 @@ load 472950-1.html
 load 473278-1.xhtml
 load 473894-1.html
 load 476241-1.html
 load 477731-1.html
 load 477928.html
 load 478131-1.html
 load 478170-1.html
 load 478185-1.html
-asserts(1) load 479938-1.html # Bug 575011
+asserts-if(!Android,1) load 479938-1.html # Bug 575011
 load 480345-1.html
 skip-if(Android) load 481921.html
 load 489462-1.html
 load 489480-1.xhtml
 load 493111-1.html
 load 493118-1.html
 load 494300-1.xul
 load 494332-1.html
@@ -363,12 +363,12 @@ load 650499-1.html
 load 660416.html
 load text-overflow-form-elements.html
 load text-overflow-iframe.html
 load text-overflow-bug666751-1.html
 load text-overflow-bug666751-2.html
 asserts(2) load text-overflow-bug670564.xhtml # asserts(2) for bug 436470
 load text-overflow-bug671796.xhtml
 load 667025.html
-asserts(14) load 673770.html # bug 569193 and bug 459597
+asserts(14) asserts-if(Android,8) load 673770.html # bug 569193 and bug 459597
 load 679933-1.html
 load 682649-1.html
 load 683702-1.xhtml
--- a/layout/reftests/font-matching/reftest.list
+++ b/layout/reftests/font-matching/reftest.list
@@ -57,11 +57,16 @@ HTTP(..) != normalmedium.html normalmedi
 HTTP(..) == weightmapping-12.html weightmapping-12-ref.html
 HTTP(..) == weightmapping-25.html weightmapping-25-ref.html
 HTTP(..) == weightmapping-45.html weightmapping-45-ref.html
 HTTP(..) == weightmapping-458.html weightmapping-458-ref.html
 HTTP(..) == weightmapping-478.html weightmapping-478-ref.html
 HTTP(..) == weightmapping-7.html weightmapping-7-ref.html
 HTTP(..) == weightmapping-12579.html weightmapping-12579-ref.html
 
+HTTP(..) == stretchmapping-all.html stretchmapping-all-ref.html
+HTTP(..) == stretchmapping-reverse.html stretchmapping-reverse-ref.html
+HTTP(..) == stretchmapping-35.html stretchmapping-35-ref.html
+HTTP(..) == stretchmapping-137.html stretchmapping-137-ref.html
+
 # test for font-stretch using @font-face
 HTTP(..) == font-stretch-1.html font-stretch-1-ref.html
 
new file mode 100644
--- /dev/null
+++ b/layout/reftests/font-matching/stretchmapping-137-ref.html
@@ -0,0 +1,348 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>font-stretch mapping tests</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  
+<style type="text/css">
+
+body {
+  margin: 50px;
+  font-family: Verdana, sans-serif;
+}
+
+h3, h4 { font-weight: normal; }
+
+table {
+  border-collapse: collapse;
+  font-size: 28px;
+}
+
+td {
+  padding: 0; margin: 0;
+  font-family: test;
+}
+
+th {
+  font-weight: inherit;
+}
+
+p { width: 300px; }
+
+.red { color: red; }
+
+thead { font-weight: 400; font-size: 75%; }
+
+/* make all the spans blocks to avoid influence of what's outside them
+   on line-height calculations */
+span { display: block; }
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-thin.ttf);
+  font-weight: 100;
+  font-stretch: ultra-condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-regular.ttf);
+  font-weight: 400;
+  font-stretch: ultra-condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-light.ttf);
+  font-weight: 200;
+  font-stretch: condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-heavy.ttf);
+  font-weight: 800;
+  font-stretch: condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-medium.ttf);
+  font-weight: 500;
+  font-stretch: expanded;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-black.ttf);
+  font-weight: 900;
+  font-stretch: expanded;
+}
+
+@font-face {
+  font-family: test100;
+  src: url(../fonts/mplus/mplus-1p-thin.ttf);
+  font-weight: 100;
+}
+
+@font-face {
+  font-family: test200;
+  src: url(../fonts/mplus/mplus-1p-light.ttf);
+  font-weight: 200;
+}
+
+@font-face {
+  font-family: test400;
+  src: url(../fonts/mplus/mplus-1p-regular.ttf);
+  font-weight: 400;
+}
+
+@font-face {
+  font-family: test500;
+  src: url(../fonts/mplus/mplus-1p-medium.ttf);
+  font-weight: 500;
+}
+
+@font-face {
+  font-family: test800;
+  src: url(../fonts/mplus/mplus-1p-heavy.ttf);
+  font-weight: 800;
+}
+
+@font-face {
+  font-family: test900;
+  src: url(../fonts/mplus/mplus-1p-black.ttf);
+  font-weight: 900;
+}
+
+.w1 { font-weight: 100; }
+.w2 { font-weight: 200; }
+.w3 { font-weight: 300; }
+.w4 { font-weight: 400; }
+.w5 { font-weight: 500; }
+.w6 { font-weight: 600; }
+.w7 { font-weight: 700; }
+.w8 { font-weight: 800; }
+.w9 { font-weight: 900; }
+
+.w1 .fs1 { font-family: test100; }
+.w2 .fs1 { font-family: test100; }
+.w3 .fs1 { font-family: test100; }
+.w4 .fs1 { font-family: test400; }
+.w5 .fs1 { font-family: test400; }
+.w6 .fs1 { font-family: test400; }
+.w7 .fs1 { font-family: test400; }
+.w8 .fs1 { font-family: test400; }
+.w9 .fs1 { font-family: test400; }
+
+.w1 .fs2 { font-family: test100; }
+.w2 .fs2 { font-family: test100; }
+.w3 .fs2 { font-family: test100; }
+.w4 .fs2 { font-family: test400; }
+.w5 .fs2 { font-family: test400; }
+.w6 .fs2 { font-family: test400; }
+.w7 .fs2 { font-family: test400; }
+.w8 .fs2 { font-family: test400; }
+.w9 .fs2 { font-family: test400; }
+
+.w1 .fs3 { font-family: test200; }
+.w2 .fs3 { font-family: test200; }
+.w3 .fs3 { font-family: test200; }
+.w4 .fs3 { font-family: test200; }
+.w5 .fs3 { font-family: test200; }
+.w6 .fs3 { font-family: test800; }
+.w7 .fs3 { font-family: test800; }
+.w8 .fs3 { font-family: test800; }
+.w9 .fs3 { font-family: test800; }
+
+.w1 .fs4 { font-family: test200; }
+.w2 .fs4 { font-family: test200; }
+.w3 .fs4 { font-family: test200; }
+.w4 .fs4 { font-family: test200; }
+.w5 .fs4 { font-family: test200; }
+.w6 .fs4 { font-family: test800; }
+.w7 .fs4 { font-family: test800; }
+.w8 .fs4 { font-family: test800; }
+.w9 .fs4 { font-family: test800; }
+
+.w1 .fs5 { font-family: test200; }
+.w2 .fs5 { font-family: test200; }
+.w3 .fs5 { font-family: test200; }
+.w4 .fs5 { font-family: test200; }
+.w5 .fs5 { font-family: test200; }
+.w6 .fs5 { font-family: test800; }
+.w7 .fs5 { font-family: test800; }
+.w8 .fs5 { font-family: test800; }
+.w9 .fs5 { font-family: test800; }
+
+.w1 .fs6 { font-family: test500; }
+.w2 .fs6 { font-family: test500; }
+.w3 .fs6 { font-family: test500; }
+.w4 .fs6 { font-family: test500; }
+.w5 .fs6 { font-family: test500; }
+.w6 .fs6 { font-family: test900; }
+.w7 .fs6 { font-family: test900; }
+.w8 .fs6 { font-family: test900; }
+.w9 .fs6 { font-family: test900; }
+
+.w1 .fs7 { font-family: test500; }
+.w2 .fs7 { font-family: test500; }
+.w3 .fs7 { font-family: test500; }
+.w4 .fs7 { font-family: test500; }
+.w5 .fs7 { font-family: test500; }
+.w6 .fs7 { font-family: test900; }
+.w7 .fs7 { font-family: test900; }
+.w8 .fs7 { font-family: test900; }
+.w9 .fs7 { font-family: test900; }
+
+.w1 .fs8 { font-family: test500; }
+.w2 .fs8 { font-family: test500; }
+.w3 .fs8 { font-family: test500; }
+.w4 .fs8 { font-family: test500; }
+.w5 .fs8 { font-family: test500; }
+.w6 .fs8 { font-family: test900; }
+.w7 .fs8 { font-family: test900; }
+.w8 .fs8 { font-family: test900; }
+.w9 .fs8 { font-family: test900; }
+
+.w1 .fs9 { font-family: test500; }
+.w2 .fs9 { font-family: test500; }
+.w3 .fs9 { font-family: test500; }
+.w4 .fs9 { font-family: test500; }
+.w5 .fs9 { font-family: test500; }
+.w6 .fs9 { font-family: test900; }
+.w7 .fs9 { font-family: test900; }
+.w8 .fs9 { font-family: test900; }
+.w9 .fs9 { font-family: test900; }
+
+</style>
+</head>
+<body>
+
+<p>Font family with ultra-condensed 100, 400, condensed 200, 800 and expanded 500, 900</p>
+
+<table>
+<thead>
+<th></th>
+<th class="red">1</th>
+<th>2</th>
+<th class="red">3</th>
+<th>4</th>
+<th>5</th>
+<th>6</th>
+<th class="red">7</th>
+<th>8</th>
+<th>9</th>
+</thead>
+<tr class="w1">
+<th>100</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w2">
+<th>200</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w3">
+<th>300</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w4">
+<th>400</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w5">
+<th>500</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w6">
+<th>600</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w7">
+<th>700</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w8">
+<th>800</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w9">
+<th>900</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+</table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/font-matching/stretchmapping-137.html
@@ -0,0 +1,268 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>font-stretch mapping tests</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  
+<style type="text/css">
+
+body {
+  margin: 50px;
+  font-family: Verdana, sans-serif;
+}
+
+h3, h4 { font-weight: normal; }
+
+table {
+  border-collapse: collapse;
+  font-size: 28px;
+}
+
+td {
+  padding: 0; margin: 0;
+  font-family: test;
+}
+
+th {
+  font-weight: inherit;
+}
+
+p { width: 300px; }
+
+.red { color: red; }
+
+thead { font-weight: 400; font-size: 75%; }
+
+/* make all the spans blocks to avoid influence of what's outside them
+   on line-height calculations */
+span { display: block; }
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-thin.ttf);
+  font-weight: 100;
+  font-stretch: ultra-condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-regular.ttf);
+  font-weight: 400;
+  font-stretch: ultra-condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-light.ttf);
+  font-weight: 200;
+  font-stretch: condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-heavy.ttf);
+  font-weight: 800;
+  font-stretch: condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-medium.ttf);
+  font-weight: 500;
+  font-stretch: expanded;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-black.ttf);
+  font-weight: 900;
+  font-stretch: expanded;
+}
+
+@font-face {
+  font-family: test100;
+  src: url(../fonts/mplus/mplus-1p-thin.ttf);
+  font-weight: 100;
+}
+
+@font-face {
+  font-family: test200;
+  src: url(../fonts/mplus/mplus-1p-light.ttf);
+  font-weight: 200;
+}
+
+@font-face {
+  font-family: test400;
+  src: url(../fonts/mplus/mplus-1p-regular.ttf);
+  font-weight: 400;
+}
+
+@font-face {
+  font-family: test500;
+  src: url(../fonts/mplus/mplus-1p-medium.ttf);
+  font-weight: 500;
+}
+
+@font-face {
+  font-family: test800;
+  src: url(../fonts/mplus/mplus-1p-heavy.ttf);
+  font-weight: 800;
+}
+
+@font-face {
+  font-family: test900;
+  src: url(../fonts/mplus/mplus-1p-black.ttf);
+  font-weight: 900;
+}
+
+.w1 { font-weight: 100; }
+.w2 { font-weight: 200; }
+.w3 { font-weight: 300; }
+.w4 { font-weight: 400; }
+.w5 { font-weight: 500; }
+.w6 { font-weight: 600; }
+.w7 { font-weight: 700; }
+.w8 { font-weight: 800; }
+.w9 { font-weight: 900; }
+
+.fs1 { font-stretch: ultra-condensed; }
+.fs2 { font-stretch: extra-condensed; }
+.fs3 { font-stretch: condensed; }
+.fs4 { font-stretch: semi-condensed; }
+.fs5 { font-stretch: normal; }
+.fs6 { font-stretch: semi-expanded; }
+.fs7 { font-stretch: expanded; }
+.fs8 { font-stretch: extra-expanded; }
+.fs9 { font-stretch: ultra-expanded; }
+
+</style>
+</head>
+<body>
+
+<p>Font family with ultra-condensed 100, 400, condensed 200, 800 and expanded 500, 900</p>
+
+<table>
+<thead>
+<th></th>
+<th class="red">1</th>
+<th>2</th>
+<th class="red">3</th>
+<th>4</th>
+<th>5</th>
+<th>6</th>
+<th class="red">7</th>
+<th>8</th>
+<th>9</th>
+</thead>
+<tr class="w1">
+<th>100</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w2">
+<th>200</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w3">
+<th>300</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w4">
+<th>400</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w5">
+<th>500</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w6">
+<th>600</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w7">
+<th>700</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w8">
+<th>800</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w9">
+<th>900</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+</table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/font-matching/stretchmapping-35-ref.html
@@ -0,0 +1,320 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>font-stretch mapping tests</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  
+<style type="text/css">
+
+body {
+  margin: 50px;
+  font-family: Verdana, sans-serif;
+}
+
+h3, h4 { font-weight: normal; }
+
+table {
+  border-collapse: collapse;
+  font-size: 28px;
+}
+
+td {
+  padding: 0; margin: 0;
+  font-family: test;
+}
+
+th {
+  font-weight: inherit;
+}
+
+p { width: 300px; }
+
+.red { color: red; }
+
+thead { font-weight: 400; font-size: 75%; }
+
+/* make all the spans blocks to avoid influence of what's outside them
+   on line-height calculations */
+span { display: block; }
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-light.ttf);
+  font-weight: 200;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-medium.ttf);
+  font-weight: 500;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-thin.ttf);
+  font-weight: 100;
+  font-stretch: condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-black.ttf);
+  font-weight: 900;
+  font-stretch: condensed;
+}
+
+@font-face {
+  font-family: test100;
+  src: url(../fonts/mplus/mplus-1p-thin.ttf);
+  font-weight: 100;
+}
+
+@font-face {
+  font-family: test200;
+  src: url(../fonts/mplus/mplus-1p-light.ttf);
+  font-weight: 200;
+}
+
+@font-face {
+  font-family: test500;
+  src: url(../fonts/mplus/mplus-1p-medium.ttf);
+  font-weight: 500;
+}
+
+@font-face {
+  font-family: test900;
+  src: url(../fonts/mplus/mplus-1p-black.ttf);
+  font-weight: 900;
+}
+
+.w1 { font-weight: 100; }
+.w2 { font-weight: 200; }
+.w3 { font-weight: 300; }
+.w4 { font-weight: 400; }
+.w5 { font-weight: 500; }
+.w6 { font-weight: 600; }
+.w7 { font-weight: 700; }
+.w8 { font-weight: 800; }
+.w9 { font-weight: 900; }
+
+.w1 .fs1 { font-family: test100; }
+.w2 .fs1 { font-family: test100; }
+.w3 .fs1 { font-family: test100; }
+.w4 .fs1 { font-family: test100; }
+.w5 .fs1 { font-family: test100; }
+.w6 .fs1 { font-family: test900; }
+.w7 .fs1 { font-family: test900; }
+.w8 .fs1 { font-family: test900; }
+.w9 .fs1 { font-family: test900; }
+
+.w1 .fs2 { font-family: test100; }
+.w2 .fs2 { font-family: test100; }
+.w3 .fs2 { font-family: test100; }
+.w4 .fs2 { font-family: test100; }
+.w5 .fs2 { font-family: test100; }
+.w6 .fs2 { font-family: test900; }
+.w7 .fs2 { font-family: test900; }
+.w8 .fs2 { font-family: test900; }
+.w9 .fs2 { font-family: test900; }
+
+.w1 .fs3 { font-family: test100; }
+.w2 .fs3 { font-family: test100; }
+.w3 .fs3 { font-family: test100; }
+.w4 .fs3 { font-family: test100; }
+.w5 .fs3 { font-family: test100; }
+.w6 .fs3 { font-family: test900; }
+.w7 .fs3 { font-family: test900; }
+.w8 .fs3 { font-family: test900; }
+.w9 .fs3 { font-family: test900; }
+
+.w1 .fs4 { font-family: test100; }
+.w2 .fs4 { font-family: test100; }
+.w3 .fs4 { font-family: test100; }
+.w4 .fs4 { font-family: test100; }
+.w5 .fs4 { font-family: test100; }
+.w6 .fs4 { font-family: test900; }
+.w7 .fs4 { font-family: test900; }
+.w8 .fs4 { font-family: test900; }
+.w9 .fs4 { font-family: test900; }
+
+.w1 .fs5 { font-family: test200; }
+.w2 .fs5 { font-family: test200; }
+.w3 .fs5 { font-family: test200; }
+.w4 .fs5 { font-family: test500; }
+.w5 .fs5 { font-family: test500; }
+.w6 .fs5 { font-family: test500; }
+.w7 .fs5 { font-family: test500; }
+.w8 .fs5 { font-family: test500; }
+.w9 .fs5 { font-family: test500; }
+
+.w1 .fs6 { font-family: test200; }
+.w2 .fs6 { font-family: test200; }
+.w3 .fs6 { font-family: test200; }
+.w4 .fs6 { font-family: test500; }
+.w5 .fs6 { font-family: test500; }
+.w6 .fs6 { font-family: test500; }
+.w7 .fs6 { font-family: test500; }
+.w8 .fs6 { font-family: test500; }
+.w9 .fs6 { font-family: test500; }
+
+.w1 .fs7 { font-family: test200; }
+.w2 .fs7 { font-family: test200; }
+.w3 .fs7 { font-family: test200; }
+.w4 .fs7 { font-family: test500; }
+.w5 .fs7 { font-family: test500; }
+.w6 .fs7 { font-family: test500; }
+.w7 .fs7 { font-family: test500; }
+.w8 .fs7 { font-family: test500; }
+.w9 .fs7 { font-family: test500; }
+
+.w1 .fs8 { font-family: test200; }
+.w2 .fs8 { font-family: test200; }
+.w3 .fs8 { font-family: test200; }
+.w4 .fs8 { font-family: test500; }
+.w5 .fs8 { font-family: test500; }
+.w6 .fs8 { font-family: test500; }
+.w7 .fs8 { font-family: test500; }
+.w8 .fs8 { font-family: test500; }
+.w9 .fs8 { font-family: test500; }
+
+.w1 .fs9 { font-family: test200; }
+.w2 .fs9 { font-family: test200; }
+.w3 .fs9 { font-family: test200; }
+.w4 .fs9 { font-family: test500; }
+.w5 .fs9 { font-family: test500; }
+.w6 .fs9 { font-family: test500; }
+.w7 .fs9 { font-family: test500; }
+.w8 .fs9 { font-family: test500; }
+.w9 .fs9 { font-family: test500; }
+
+</style>
+</head>
+<body>
+
+<p>Font family with normal width 200, 500 and condensed 100, 900</p>
+
+<table>
+<thead>
+<th></th>
+<th>1</th>
+<th>2</th>
+<th class="red">3</th>
+<th>4</th>
+<th class="red">5</th>
+<th>6</th>
+<th>7</th>
+<th>8</th>
+<th>9</th>
+</thead>
+<tr class="w1">
+<th>100</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+<tr class="w2">
+<th>200</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+<tr class="w3">
+<th>300</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+<tr class="w4">
+<th>400</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+<tr class="w5">
+<th>500</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+<tr class="w6">
+<th>600</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+<tr class="w7">
+<th>700</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+<tr class="w8">
+<th>800</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+<tr class="w9">
+<th>900</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+</table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/font-matching/stretchmapping-35.html
@@ -0,0 +1,240 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>font-stretch mapping tests</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  
+<style type="text/css">
+
+body {
+  margin: 50px;
+  font-family: Verdana, sans-serif;
+}
+
+h3, h4 { font-weight: normal; }
+
+table {
+  border-collapse: collapse;
+  font-size: 28px;
+}
+
+td {
+  padding: 0; margin: 0;
+  font-family: test;
+}
+
+th {
+  font-weight: inherit;
+}
+
+p { width: 300px; }
+
+.red { color: red; }
+
+thead { font-weight: 400; font-size: 75%; }
+
+/* make all the spans blocks to avoid influence of what's outside them
+   on line-height calculations */
+span { display: block; }
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-light.ttf);
+  font-weight: 200;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-medium.ttf);
+  font-weight: 500;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-thin.ttf);
+  font-weight: 100;
+  font-stretch: condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-black.ttf);
+  font-weight: 900;
+  font-stretch: condensed;
+}
+
+@font-face {
+  font-family: test100;
+  src: url(../fonts/mplus/mplus-1p-thin.ttf);
+  font-weight: 100;
+}
+
+@font-face {
+  font-family: test200;
+  src: url(../fonts/mplus/mplus-1p-light.ttf);
+  font-weight: 200;
+}
+
+@font-face {
+  font-family: test500;
+  src: url(../fonts/mplus/mplus-1p-medium.ttf);
+  font-weight: 500;
+}
+
+@font-face {
+  font-family: test900;
+  src: url(../fonts/mplus/mplus-1p-black.ttf);
+  font-weight: 900;
+}
+
+.w1 { font-weight: 100; }
+.w2 { font-weight: 200; }
+.w3 { font-weight: 300; }
+.w4 { font-weight: 400; }
+.w5 { font-weight: 500; }
+.w6 { font-weight: 600; }
+.w7 { font-weight: 700; }
+.w8 { font-weight: 800; }
+.w9 { font-weight: 900; }
+
+.fs1 { font-stretch: ultra-condensed; }
+.fs2 { font-stretch: extra-condensed; }
+.fs3 { font-stretch: condensed; }
+.fs4 { font-stretch: semi-condensed; }
+.fs5 { font-stretch: normal; }
+.fs6 { font-stretch: semi-expanded; }
+.fs7 { font-stretch: expanded; }
+.fs8 { font-stretch: extra-expanded; }
+.fs9 { font-stretch: ultra-expanded; }
+
+</style>
+</head>
+<body>
+
+<p>Font family with normal width 200, 500 and condensed 100, 900</p>
+
+<table>
+<thead>
+<th></th>
+<th>1</th>
+<th>2</th>
+<th class="red">3</th>
+<th>4</th>
+<th class="red">5</th>
+<th>6</th>
+<th>7</th>
+<th>8</th>
+<th>9</th>
+</thead>
+<tr class="w1">
+<th>100</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+<tr class="w2">
+<th>200</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+<tr class="w3">
+<th>300</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+<tr class="w4">
+<th>400</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+<tr class="w5">
+<th>500</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+<tr class="w6">
+<th>600</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+<tr class="w7">
+<th>700</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+<tr class="w8">
+<th>800</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+<tr class="w9">
+<th>900</th>
+<td class="fs1"><span>あ</span></td>
+<td class="fs2"><span>あ</span></td>
+<td class="fs3"><span>あ</span></td>
+<td class="fs4"><span>あ</span></td>
+<td class="fs5"><span>あ</span></td>
+<td class="fs6"><span>あ</span></td>
+<td class="fs7"><span>あ</span></td>
+<td class="fs8"><span>あ</span></td>
+<td class="fs9"><span>あ</span></td>
+</tr>
+</table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/font-matching/stretchmapping-all-ref.html
@@ -0,0 +1,366 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>font-stretch matching tests</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  
+<style type="text/css">
+
+body {
+  margin: 50px;
+  font-family: Calibri, Verdana, sans-serif;
+}
+
+p { margin: 0; padding: 0; }
+
+table {
+  border-collapse: collapse;
+}
+
+th { 
+  font-weight: normal;
+  background-color: #eee;
+}
+
+th, td { width: 3em; text-align: left; }
+tr th { text-align: left; }
+
+.fstest-full { font-family: fstest-full; }
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd1.ttf);
+  font-stretch: ultra-condensed;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd2.ttf);
+  font-stretch: extra-condensed;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd3.ttf);
+  font-stretch: condensed;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd4.ttf);
+  font-stretch: semi-condensed;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd5.ttf);
+  font-stretch: normal;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd6.ttf);
+  font-stretch: semi-expanded;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd7.ttf);
+  font-stretch: expanded;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd8.ttf);
+  font-stretch: extra-expanded;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd9.ttf);
+  font-stretch: ultra-expanded;
+}
+
+.fstest-1-3 { font-family: fstest-1-3; }
+
+@font-face {
+  font-family: fstest-1-3;
+  src: url(../fonts/csstest-widths-wd1.ttf);
+  font-stretch: ultra-condensed;
+}
+
+@font-face {
+  font-family: fstest-1-3;
+  src: url(../fonts/csstest-widths-wd3.ttf);
+  font-stretch: condensed;
+}
+
+.fstest-1-4 { font-family: fstest-1-4; }
+
+@font-face {
+  font-family: fstest-1-4;
+  src: url(../fonts/csstest-widths-wd1.ttf);
+  font-stretch: ultra-condensed;
+}
+
+@font-face {
+  font-family: fstest-1-4;
+  src: url(../fonts/csstest-widths-wd4.ttf);
+  font-stretch: semi-condensed;
+}
+
+.fstest-1-5 { font-family: fstest-1-5; }
+
+@font-face {
+  font-family: fstest-1-5;
+  src: url(../fonts/csstest-widths-wd1.ttf);
+  font-stretch: ultra-condensed;
+}
+
+@font-face {
+  font-family: fstest-1-5;
+  src: url(../fonts/csstest-widths-wd5.ttf);
+  font-stretch: normal;
+}
+
+.fstest-2-6 { font-family: fstest-2-6; }
+
+@font-face {
+  font-family: fstest-2-6;
+  src: url(../fonts/csstest-widths-wd2.ttf);
+  font-stretch: extra-condensed;
+}
+
+@font-face {
+  font-family: fstest-2-6;
+  src: url(../fonts/csstest-widths-wd6.ttf);
+  font-stretch: semi-expanded;
+}
+
+.fstest-4-6 { font-family: fstest-4-6; }
+
+@font-face {
+  font-family: fstest-4-6;
+  src: url(../fonts/csstest-widths-wd4.ttf);
+  font-stretch: semi-condensed;
+}
+
+@font-face {
+  font-family: fstest-4-6;
+  src: url(../fonts/csstest-widths-wd6.ttf);
+  font-stretch: semi-expanded;
+}
+
+.fstest-4-7 { font-family: fstest-4-7; }
+
+@font-face {
+  font-family: fstest-4-7;
+  src: url(../fonts/csstest-widths-wd4.ttf);
+  font-stretch: semi-condensed;
+}
+
+@font-face {
+  font-family: fstest-4-7;
+  src: url(../fonts/csstest-widths-wd7.ttf);
+  font-stretch: expanded;
+}
+
+.fstest-6-7 { font-family: fstest-6-7; }
+
+@font-face {
+  font-family: fstest-6-7;
+  src: url(../fonts/csstest-widths-wd6.ttf);
+  font-stretch: semi-expanded;
+}
+
+@font-face {
+  font-family: fstest-6-7;
+  src: url(../fonts/csstest-widths-wd7.ttf);
+  font-stretch: expanded;
+}
+
+.fstest-7-9 { font-family: fstest-7-9; }
+
+@font-face {
+  font-family: fstest-7-9;
+  src: url(../fonts/csstest-widths-wd7.ttf);
+  font-stretch: expanded;
+}
+
+@font-face {
+  font-family: fstest-7-9;
+  src: url(../fonts/csstest-widths-wd9.ttf);
+  font-stretch: ultra-expanded;
+}
+
+.fstest-8-9 { font-family: fstest-8-9; }
+
+@font-face {
+  font-family: fstest-8-9;
+  src: url(../fonts/csstest-widths-wd8.ttf);
+  font-stretch: extra-expanded;
+}
+
+@font-face {
+  font-family: fstest-8-9;
+  src: url(../fonts/csstest-widths-wd9.ttf);
+  font-stretch: ultra-expanded;
+}
+
+.fs1 { font-stretch: ultra-condensed; }
+.fs2 { font-stretch: extra-condensed; }
+.fs3 { font-stretch: condensed; }
+.fs4 { font-stretch: semi-condensed; }
+.fs5 { font-stretch: normal; }
+.fs6 { font-stretch: semi-expanded; }
+.fs7 { font-stretch: expanded; }
+.fs8 { font-stretch: extra-expanded; }
+.fs9 { font-stretch: ultra-expanded; }
+
+</style>
+  
+<script type="text/javascript">
+
+</script>
+  
+</head>
+<body>
+
+<p>font-stretch mapping with different font family sets</p>
+<p>(only numbers should appear in the body of the table)</p>
+
+<table>
+<thead>
+<th>width</th>
+<th>full</th>
+<th>1-3</th>
+<th>1-4</th>
+<th>1-5</th>
+<th>2-6</th>
+<th>4-6</th>
+<th>4-7</th>
+<th>6-7</th>
+<th>7-9</th>
+<th>8-9</th>
+</thead>
+<tr class="fs1">
+<th>1</th>
+<td class="fstest-full">1</td>
+<td class="fstest-1-3">1</td>
+<td class="fstest-1-4">1</td>
+<td class="fstest-1-5">1</td>
+<td class="fstest-2-6">2</td>
+<td class="fstest-4-6">4</td>
+<td class="fstest-4-7">4</td>
+<td class="fstest-6-7">6</td>
+<td class="fstest-7-9">7</td>
+<td class="fstest-8-9">8</td>
+</tr>
+<tr class="fs2">
+<th>2</th>
+<td class="fstest-full">2</td>
+<td class="fstest-1-3">1</td>
+<td class="fstest-1-4">1</td>
+<td class="fstest-1-5">1</td>
+<td class="fstest-2-6">2</td>
+<td class="fstest-4-6">4</td>
+<td class="fstest-4-7">4</td>
+<td class="fstest-6-7">6</td>
+<td class="fstest-7-9">7</td>
+<td class="fstest-8-9">8</td>
+</tr>
+<tr class="fs3">
+<th>3</th>
+<td class="fstest-full">3</td>
+<td class="fstest-1-3">3</td>
+<td class="fstest-1-4">1</td>
+<td class="fstest-1-5">1</td>
+<td class="fstest-2-6">2</td>
+<td class="fstest-4-6">4</td>
+<td class="fstest-4-7">4</td>
+<td class="fstest-6-7">6</td>
+<td class="fstest-7-9">7</td>
+<td class="fstest-8-9">8</td>
+</tr>
+<tr class="fs4">
+<th>4</th>
+<td class="fstest-full">4</td>
+<td class="fstest-1-3">3</td>
+<td class="fstest-1-4">4</td>
+<td class="fstest-1-5">1</td>
+<td class="fstest-2-6">2</td>
+<td class="fstest-4-6">4</td>
+<td class="fstest-4-7">4</td>
+<td class="fstest-6-7">6</td>
+<td class="fstest-7-9">7</td>
+<td class="fstest-8-9">8</td>
+</tr>
+<tr class="fs5">
+<th>5</th>
+<td class="fstest-full">5</td>
+<td class="fstest-1-3">3</td>
+<td class="fstest-1-4">4</td>
+<td class="fstest-1-5">5</td>
+<td class="fstest-2-6">2</td>
+<td class="fstest-4-6">4</td>
+<td class="fstest-4-7">4</td>
+<td class="fstest-6-7">6</td>
+<td class="fstest-7-9">7</td>
+<td class="fstest-8-9">8</td>
+</tr>
+<tr class="fs6">
+<th>6</th>
+<td class="fstest-full">6</td>
+<td class="fstest-1-3">3</td>
+<td class="fstest-1-4">4</td>
+<td class="fstest-1-5">5</td>
+<td class="fstest-2-6">6</td>
+<td class="fstest-4-6">6</td>
+<td class="fstest-4-7">7</td>
+<td class="fstest-6-7">6</td>
+<td class="fstest-7-9">7</td>
+<td class="fstest-8-9">8</td>
+</tr>
+<tr class="fs7">
+<th>7</th>
+<td class="fstest-full">7</td>
+<td class="fstest-1-3">3</td>
+<td class="fstest-1-4">4</td>
+<td class="fstest-1-5">5</td>
+<td class="fstest-2-6">6</td>
+<td class="fstest-4-6">6</td>
+<td class="fstest-4-7">7</td>
+<td class="fstest-6-7">7</td>
+<td class="fstest-7-9">7</td>
+<td class="fstest-8-9">8</td>
+</tr>
+<tr class="fs8">
+<th>8</th>
+<td class="fstest-full">8</td>
+<td class="fstest-1-3">3</td>
+<td class="fstest-1-4">4</td>
+<td class="fstest-1-5">5</td>
+<td class="fstest-2-6">6</td>
+<td class="fstest-4-6">6</td>
+<td class="fstest-4-7">7</td>
+<td class="fstest-6-7">7</td>
+<td class="fstest-7-9">9</td>
+<td class="fstest-8-9">8</td>
+</tr>
+<tr class="fs9">
+<th>9</th>
+<td class="fstest-full">9</td>
+<td class="fstest-1-3">3</td>
+<td class="fstest-1-4">4</td>
+<td class="fstest-1-5">5</td>
+<td class="fstest-2-6">6</td>
+<td class="fstest-4-6">6</td>
+<td class="fstest-4-7">7</td>
+<td class="fstest-6-7">7</td>
+<td class="fstest-7-9">9</td>
+<td class="fstest-8-9">9</td>
+</tr>
+</table>
+
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/layout/reftests/font-matching/stretchmapping-all.html
@@ -0,0 +1,505 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>font-stretch matching tests</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  
+<style type="text/css">
+
+body {
+  margin: 50px;
+  font-family: Calibri, Verdana, sans-serif;
+}
+
+p { margin: 0; padding: 0; }
+
+table {
+  border-collapse: collapse;
+}
+
+th { 
+  font-weight: normal;
+  background-color: #eee;
+}
+
+th, td { width: 3em; text-align: left; }
+tr th { text-align: left; }
+
+.fstest-full { font-family: fstest-full; }
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd1.ttf);
+  font-stretch: ultra-condensed;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd2.ttf);
+  font-stretch: extra-condensed;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd3.ttf);
+  font-stretch: condensed;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd4.ttf);
+  font-stretch: semi-condensed;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd5.ttf);
+  font-stretch: normal;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd6.ttf);
+  font-stretch: semi-expanded;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd7.ttf);
+  font-stretch: expanded;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd8.ttf);
+  font-stretch: extra-expanded;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd9.ttf);
+  font-stretch: ultra-expanded;
+}
+
+.fstest-1-3 { font-family: fstest-1-3; }
+
+@font-face {
+  font-family: fstest-1-3;
+  src: url(../fonts/csstest-widths-wd1.ttf);
+  font-stretch: ultra-condensed;
+}
+
+@font-face {
+  font-family: fstest-1-3;
+  src: url(../fonts/csstest-widths-wd3.ttf);
+  font-stretch: condensed;
+}
+
+.fstest-1-4 { font-family: fstest-1-4; }
+
+@font-face {
+  font-family: fstest-1-4;
+  src: url(../fonts/csstest-widths-wd1.ttf);
+  font-stretch: ultra-condensed;
+}
+
+@font-face {
+  font-family: fstest-1-4;
+  src: url(../fonts/csstest-widths-wd4.ttf);
+  font-stretch: semi-condensed;
+}
+
+.fstest-1-5 { font-family: fstest-1-5; }
+
+@font-face {
+  font-family: fstest-1-5;
+  src: url(../fonts/csstest-widths-wd1.ttf);
+  font-stretch: ultra-condensed;
+}
+
+@font-face {
+  font-family: fstest-1-5;
+  src: url(../fonts/csstest-widths-wd5.ttf);
+  font-stretch: normal;
+}
+
+.fstest-2-6 { font-family: fstest-2-6; }
+
+@font-face {
+  font-family: fstest-2-6;
+  src: url(../fonts/csstest-widths-wd2.ttf);
+  font-stretch: extra-condensed;
+}
+
+@font-face {
+  font-family: fstest-2-6;
+  src: url(../fonts/csstest-widths-wd6.ttf);
+  font-stretch: semi-expanded;
+}
+
+.fstest-4-6 { font-family: fstest-4-6; }
+
+@font-face {
+  font-family: fstest-4-6;
+  src: url(../fonts/csstest-widths-wd4.ttf);
+  font-stretch: semi-condensed;
+}
+
+@font-face {
+  font-family: fstest-4-6;
+  src: url(../fonts/csstest-widths-wd6.ttf);
+  font-stretch: semi-expanded;
+}
+
+.fstest-4-7 { font-family: fstest-4-7; }
+
+@font-face {
+  font-family: fstest-4-7;
+  src: url(../fonts/csstest-widths-wd4.ttf);
+  font-stretch: semi-condensed;
+}
+
+@font-face {
+  font-family: fstest-4-7;
+  src: url(../fonts/csstest-widths-wd7.ttf);
+  font-stretch: expanded;
+}
+
+.fstest-6-7 { font-family: fstest-6-7; }
+
+@font-face {
+  font-family: fstest-6-7;
+  src: url(../fonts/csstest-widths-wd6.ttf);
+  font-stretch: semi-expanded;
+}
+
+@font-face {
+  font-family: fstest-6-7;
+  src: url(../fonts/csstest-widths-wd7.ttf);
+  font-stretch: expanded;
+}
+
+.fstest-7-9 { font-family: fstest-7-9; }
+
+@font-face {
+  font-family: fstest-7-9;
+  src: url(../fonts/csstest-widths-wd7.ttf);
+  font-stretch: expanded;
+}
+
+@font-face {
+  font-family: fstest-7-9;
+  src: url(../fonts/csstest-widths-wd9.ttf);
+  font-stretch: ultra-expanded;
+}
+
+.fstest-8-9 { font-family: fstest-8-9; }
+
+@font-face {
+  font-family: fstest-8-9;
+  src: url(../fonts/csstest-widths-wd8.ttf);
+  font-stretch: extra-expanded;
+}
+
+@font-face {
+  font-family: fstest-8-9;
+  src: url(../fonts/csstest-widths-wd9.ttf);
+  font-stretch: ultra-expanded;
+}
+
+.fs1 { font-stretch: ultra-condensed; }
+.fs2 { font-stretch: extra-condensed; }
+.fs3 { font-stretch: condensed; }
+.fs4 { font-stretch: semi-condensed; }
+.fs5 { font-stretch: normal; }
+.fs6 { font-stretch: semi-expanded; }
+.fs7 { font-stretch: expanded; }
+.fs8 { font-stretch: extra-expanded; }
+.fs9 { font-stretch: ultra-expanded; }
+
+</style>
+  
+<script type="text/javascript">
+
+</script>
+  
+</head>
+<body>
+
+<p>font-stretch mapping with different font family sets</p>
+<p>(only numbers should appear in the body of the table)</p>
+
+<table>
+<thead>
+<th>width</th>
+<th>full</th>
+<th>1-3</th>
+<th>1-4</th>
+<th>1-5</th>
+<th>2-6</th>
+<th>4-6</th>
+<th>4-7</th>
+<th>6-7</th>
+<th>7-9</th>
+<th>8-9</th>
+</thead>
+<tr class="fs1">
+<th>1</th>
+<td class="fstest-full">F</td>
+<td class="fstest-1-3">F</td>
+<td class="fstest-1-4">F</td>
+<td class="fstest-1-5">F</td>
+<td class="fstest-2-6">F</td>
+<td class="fstest-4-6">F</td>
+<td class="fstest-4-7">F</td>
+<td class="fstest-6-7">F</td>
+<td class="fstest-7-9">F</td>
+<td class="fstest-8-9">F</td>
+</tr>
+<tr class="fs2">
+<th>2</th>
+<td class="fstest-full">F</td>
+<td class="fstest-1-3">F</td>
+<td class="fstest-1-4">F</td>
+<td class="fstest-1-5">F</td>
+<td class="fstest-2-6">F</td>
+<td class="fstest-4-6">F</td>
+<td class="fstest-4-7">F</td>
+<td class="fstest-6-7">F</td>
+<td class="fstest-7-9">F</td>
+<td class="fstest-8-9">F</td>
+</tr>
+<tr class="fs3">
+<th>3</th>
+<td class="fstest-full">F</td>
+<td class="fstest-1-3">F</td>
+<td class="fstest-1-4">F</td>
+<td class="fstest-1-5">F</td>
+<td class="fstest-2-6">F</td>
+<td class="fstest-4-6">F</td>
+<td class="fstest-4-7">F</td>
+<td class="fstest-6-7">F</td>
+<td class="fstest-7-9">F</td>
+<td class="fstest-8-9">F</td>
+</tr>
+<tr class="fs4">
+<th>4</th>
+<td class="fstest-full">F</td>
+<td class="fstest-1-3">F</td>
+<td class="fstest-1-4">F</td>
+<td class="fstest-1-5">F</td>
+<td class="fstest-2-6">F</td>
+<td class="fstest-4-6">F</td>
+<td class="fstest-4-7">F</td>
+<td class="fstest-6-7">F</td>
+<td class="fstest-7-9">F</td>
+<td class="fstest-8-9">F</td>
+</tr>
+<tr class="fs5">
+<th>5</th>
+<td class="fstest-full">F</td>
+<td class="fstest-1-3">F</td>
+<td class="fstest-1-4">F</td>
+<td class="fstest-1-5">F</td>
+<td class="fstest-2-6">F</td>
+<td class="fstest-4-6">F</td>
+<td class="fstest-4-7">F</td>
+<td class="fstest-6-7">F</td>
+<td class="fstest-7-9">F</td>
+<td class="fstest-8-9">F</td>
+</tr>
+<tr class="fs6">
+<th>6</th>
+<td class="fstest-full">F</td>
+<td class="fstest-1-3">F</td>
+<td class="fstest-1-4">F</td>
+<td class="fstest-1-5">F</td>
+<td class="fstest-2-6">F</td>
+<td class="fstest-4-6">F</td>
+<td class="fstest-4-7">F</td>
+<td class="fstest-6-7">F</td>
+<td class="fstest-7-9">F</td>
+<td class="fstest-8-9">F</td>
+</tr>
+<tr class="fs7">
+<th>7</th>
+<td class="fstest-full">F</td>
+<td class="fstest-1-3">F</td>
+<td class="fstest-1-4">F</td>
+<td class="fstest-1-5">F</td>
+<td class="fstest-2-6">F</td>
+<td class="fstest-4-6">F</td>
+<td class="fstest-4-7">F</td>
+<td class="fstest-6-7">F</td>
+<td class="fstest-7-9">F</td>
+<td class="fstest-8-9">F</td>
+</tr>
+<tr class="fs8">
+<th>8</th>
+<td class="fstest-full">F</td>
+<td class="fstest-1-3">F</td>
+<td class="fstest-1-4">F</td>
+<td class="fstest-1-5">F</td>
+<td class="fstest-2-6">F</td>
+<td class="fstest-4-6">F</td>
+<td class="fstest-4-7">F</td>
+<td class="fstest-6-7">F</td>
+<td class="fstest-7-9">F</td>
+<td class="fstest-8-9">F</td>
+</tr>
+<tr class="fs9">
+<th>9</th>
+<td class="fstest-full">F</td>
+<td class="fstest-1-3">F</td>
+<td class="fstest-1-4">F</td>
+<td class="fstest-1-5">F</td>
+<td class="fstest-2-6">F</td>
+<td class="fstest-4-6">F</td>
+<td class="fstest-4-7">F</td>
+<td class="fstest-6-7">F</td>
+<td class="fstest-7-9">F</td>
+<td class="fstest-8-9">F</td>
+</tr>
+</table>
+
+<!--
+
+<p>Results based on spec logic:</p>
+
+<table>
+<thead>
+<th>width</th>
+<th>full</th>
+<th>1-3</th>
+<th>1-4</th>
+<th>1-5</th>
+<th>2-6</th>
+<th>4-6</th>
+<th>4-7</th>
+<th>6-7</th>
+<th>7-9</th>
+<th>8-9</th>
+</thead>
+<tr class="fs1">
+<th>1</th>
+<td class="fstest-full">1</td>
+<td class="fstest-1-3">1</td>
+<td class="fstest-1-4">1</td>
+<td class="fstest-1-5">1</td>
+<td class="fstest-2-6">2</td>
+<td class="fstest-4-6">4</td>
+<td class="fstest-4-7">4</td>
+<td class="fstest-6-7">6</td>
+<td class="fstest-7-9">7</td>
+<td class="fstest-8-9">8</td>
+</tr>
+<tr class="fs2">
+<th>2</th>
+<td class="fstest-full">2</td>
+<td class="fstest-1-3">1</td>
+<td class="fstest-1-4">1</td>
+<td class="fstest-1-5">1</td>
+<td class="fstest-2-6">2</td>
+<td class="fstest-4-6">4</td>
+<td class="fstest-4-7">4</td>
+<td class="fstest-6-7">6</td>
+<td class="fstest-7-9">7</td>
+<td class="fstest-8-9">8</td>
+</tr>
+<tr class="fs3">
+<th>3</th>
+<td class="fstest-full">3</td>
+<td class="fstest-1-3">3</td>
+<td class="fstest-1-4">1</td>
+<td class="fstest-1-5">1</td>
+<td class="fstest-2-6">2</td>
+<td class="fstest-4-6">4</td>
+<td class="fstest-4-7">4</td>
+<td class="fstest-6-7">6</td>
+<td class="fstest-7-9">7</td>
+<td class="fstest-8-9">8</td>
+</tr>
+<tr class="fs4">
+<th>4</th>
+<td class="fstest-full">4</td>
+<td class="fstest-1-3">3</td>
+<td class="fstest-1-4">4</td>
+<td class="fstest-1-5">1</td>
+<td class="fstest-2-6">2</td>
+<td class="fstest-4-6">4</td>
+<td class="fstest-4-7">4</td>
+<td class="fstest-6-7">6</td>
+<td class="fstest-7-9">7</td>
+<td class="fstest-8-9">8</td>
+</tr>
+<tr class="fs5">
+<th>5</th>
+<td class="fstest-full">5</td>
+<td class="fstest-1-3">3</td>
+<td class="fstest-1-4">4</td>
+<td class="fstest-1-5">5</td>
+<td class="fstest-2-6">2</td>
+<td class="fstest-4-6">4</td>
+<td class="fstest-4-7">4</td>
+<td class="fstest-6-7">6</td>
+<td class="fstest-7-9">7</td>
+<td class="fstest-8-9">8</td>
+</tr>
+<tr class="fs6">
+<th>6</th>
+<td class="fstest-full">6</td>
+<td class="fstest-1-3">3</td>
+<td class="fstest-1-4">4</td>
+<td class="fstest-1-5">5</td>
+<td class="fstest-2-6">6</td>
+<td class="fstest-4-6">6</td>
+<td class="fstest-4-7">7</td>
+<td class="fstest-6-7">6</td>
+<td class="fstest-7-9">7</td>
+<td class="fstest-8-9">8</td>
+</tr>
+<tr class="fs7">
+<th>7</th>
+<td class="fstest-full">7</td>
+<td class="fstest-1-3">3</td>
+<td class="fstest-1-4">4</td>
+<td class="fstest-1-5">5</td>
+<td class="fstest-2-6">6</td>
+<td class="fstest-4-6">6</td>
+<td class="fstest-4-7">7</td>
+<td class="fstest-6-7">7</td>
+<td class="fstest-7-9">7</td>
+<td class="fstest-8-9">8</td>
+</tr>
+<tr class="fs8">
+<th>8</th>
+<td class="fstest-full">8</td>
+<td class="fstest-1-3">3</td>
+<td class="fstest-1-4">4</td>
+<td class="fstest-1-5">5</td>
+<td class="fstest-2-6">6</td>
+<td class="fstest-4-6">6</td>
+<td class="fstest-4-7">7</td>
+<td class="fstest-6-7">7</td>
+<td class="fstest-7-9">9</td>
+<td class="fstest-8-9">8</td>
+</tr>
+<tr class="fs9">
+<th>9</th>
+<td class="fstest-full">9</td>
+<td class="fstest-1-3">3</td>
+<td class="fstest-1-4">4</td>
+<td class="fstest-1-5">5</td>
+<td class="fstest-2-6">6</td>
+<td class="fstest-4-6">6</td>
+<td class="fstest-4-7">7</td>
+<td class="fstest-6-7">7</td>
+<td class="fstest-7-9">9</td>
+<td class="fstest-8-9">9</td>
+</tr>
+</table>
+
+-->
+
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/layout/reftests/font-matching/stretchmapping-reverse-ref.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Assure OS/2 usWidthClass isn't referenced</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  
+<style type="text/css">
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd5.ttf);
+  font-stretch: normal;
+}
+
+body {
+  margin: 50px;
+}
+
+p.test {
+  font-family: fstest-full;
+  font-size: 24px;
+}
+
+.fs9 { font-stretch: ultra-condensed; }
+.fs8 { font-stretch: extra-condensed; }
+.fs7 { font-stretch: condensed; }
+.fs6 { font-stretch: semi-condensed; }
+.fs5 { font-stretch: normal; }
+.fs4 { font-stretch: semi-expanded; }
+.fs3 { font-stretch: expanded; }
+.fs2 { font-stretch: extra-expanded; }
+.fs1 { font-stretch: ultra-expanded; }
+
+</style>
+  
+</head>
+<body>
+
+<p>The numbers below should appear in ascending sequence:</p>
+
+<p class="test">
+<span class="fs1">1</span>
+<span class="fs2">2</span>
+<span class="fs3">3</span>
+<span class="fs4">4</span>
+<span class="fs5">5</span>
+<span class="fs6">6</span>
+<span class="fs7">7</span>
+<span class="fs8">8</span>
+<span class="fs9">9</span>
+</p>
+
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/layout/reftests/font-matching/stretchmapping-reverse.html
@@ -0,0 +1,102 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Assure OS/2 usWidthClass isn't referenced</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  
+<style type="text/css">
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd9.ttf);
+  font-stretch: ultra-condensed;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd8.ttf);
+  font-stretch: extra-condensed;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd7.ttf);
+  font-stretch: condensed;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd6.ttf);
+  font-stretch: semi-condensed;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd5.ttf);
+  font-stretch: normal;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd4.ttf);
+  font-stretch: semi-expanded;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd3.ttf);
+  font-stretch: expanded;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd2.ttf);
+  font-stretch: extra-expanded;
+}
+
+@font-face {
+  font-family: fstest-full;
+  src: url(../fonts/csstest-widths-wd1.ttf);
+  font-stretch: ultra-expanded;
+}
+
+body {
+  margin: 50px;
+}
+
+p.test {
+  font-family: fstest-full;
+  font-size: 24px;
+}
+
+.fs9 { font-stretch: ultra-condensed; }
+.fs8 { font-stretch: extra-condensed; }
+.fs7 { font-stretch: condensed; }
+.fs6 { font-stretch: semi-condensed; }
+.fs5 { font-stretch: normal; }
+.fs4 { font-stretch: semi-expanded; }
+.fs3 { font-stretch: expanded; }
+.fs2 { font-stretch: extra-expanded; }
+.fs1 { font-stretch: ultra-expanded; }
+
+</style>
+  
+</head>
+<body>
+
+<p>The numbers below should appear in ascending sequence:</p>
+
+<p class="test">
+<span class="fs1">F</span>
+<span class="fs2">F</span>
+<span class="fs3">F</span>
+<span class="fs4">F</span>
+<span class="fs5">F</span>
+<span class="fs6">F</span>
+<span class="fs7">F</span>
+<span class="fs8">F</span>
+<span class="fs9">F</span>
+</p>
+
+</body>
+</html>
\ No newline at end of file
copy from layout/reftests/svg/smil/anim-indefinite-to-1.svg
copy to layout/reftests/svg/smil/motion/animateMotion-indefinite-to-1.svg
--- a/layout/reftests/svg/smil/anim-indefinite-to-1.svg
+++ b/layout/reftests/svg/smil/motion/animateMotion-indefinite-to-1.svg
@@ -1,7 +1,10 @@
 <svg xmlns="http://www.w3.org/2000/svg">
   <!-- Test that an indefinite to-animation just sticks to the base value for
-       interpolatable attributes. -->
-  <rect x="15" y="15" width="200" height="200" fill="blue">
-    <animate attributeName="height" to="100" dur="indefinite"/>
+       animateMotion. -->
+  <rect width="100%" height="100%" fill="lime"/>
+
+  <rect x="15" y="15" width="100" height="100" fill="red"/>
+  <rect x="15" y="15" width="100" height="100" fill="lime">
+    <animateMotion to="500,500" dur="indefinite"/>
   </rect>
 </svg>
copy from layout/reftests/svg/smil/anim-indefinite-to-2.svg
copy to layout/reftests/svg/smil/motion/animateMotion-indefinite-to-2.svg
--- a/layout/reftests/svg/smil/anim-indefinite-to-2.svg
+++ b/layout/reftests/svg/smil/motion/animateMotion-indefinite-to-2.svg
@@ -1,8 +1,11 @@
 <svg xmlns="http://www.w3.org/2000/svg">
   <!-- Test that an indefinite to-animation with discrete calcMode applies
        the underlying value for the whole time. -->
-  <rect x="15" y="15" width="200" height="200" fill="blue">
-    <animate attributeName="height" to="100" dur="indefinite"
-      calcMode="discrete"/>
+  <rect width="100%" height="100%" fill="lime"/>
+
+  <rect x="15" y="15" width="100" height="100" fill="red"/>
+  <rect x="15" y="15" width="100" height="100" fill="lime">
+    <animateMotion to="500,500" dur="indefinite"
+                   calcMode="discrete"/>
   </rect>
 </svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/smil/motion/animateMotion-to-overridden-1.svg
@@ -0,0 +1,61 @@
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:xlink="http://www.w3.org/1999/xlink"
+     class="reftest-wait">
+  <script xlink:href="../smil-util.js" type="text/javascript"/>
+  <script type="text/javascript">
+    function doTest() {
+      setTimeAndSnapshot(1, true);
+    }
+    window.addEventListener("MozReftestInvalidate", doTest, false);
+  </script>
+
+  <!-- Big green background to match lime.svg -->
+  <rect fill="lime" width="100%" height="100%" />
+
+  <!-- In the following pairs of rects, the only pairwise differences are the
+       fill-color and the presence of the "to" attribute on the animateMotion
+       element.  "to" shouldn't have any effect in these cases, since it has
+       lower priority than "values," "path," and "mpath". So in each case, the
+       lime rect should cover up the red rect at all times. -->
+
+  <!-- Single-point path specified with "values" attribute: -->
+  <g transform="translate(0,0)">
+    <rect width="20" height="20" fill="red">
+      <animateMotion values="20,0" dur="2"/>
+    </rect>
+    <rect width="20" height="20" fill="lime">
+      <animateMotion values="20,0" dur="2" to="-50,0"/>
+    </rect>
+  </g>
+
+  <!-- Multi-point path specified with "values" attribute: -->
+  <g transform="translate(0,30)">
+    <rect width="20" height="20" fill="red">
+      <animateMotion values="20,0; 80,0" dur="2"/>
+    </rect>
+    <rect width="20" height="20" fill="lime">
+      <animateMotion values="20,0; 80,0" dur="2" to="-50,0"/>
+    </rect>
+  </g>
+
+  <!-- Path specified with "path" attribute: -->
+  <g transform="translate(0,60)">
+    <rect width="20" height="20" fill="red">
+      <animateMotion path="m0,0 h100" dur="2"/>
+    </rect>
+    <rect width="20" height="20" fill="lime">
+      <animateMotion path="m0,0 h100" dur="2" to="-50,0"/>
+    </rect>
+  </g>
+
+  <!-- Path specified with "mpath" subelement: -->
+  <path id="p" d="m0,0 h100"/>
+  <g transform="translate(0,90)">
+    <rect width="20" height="20" fill="red">
+      <animateMotion dur="2"><mpath xlink:href="#p"/></animateMotion>
+    </rect>
+    <rect width="20" height="20" fill="lime">
+      <animateMotion dur="2" to="-50,0"><mpath xlink:href="#p"/></animateMotion>
+    </rect>
+  </g>
+</svg>
--- a/layout/reftests/svg/smil/motion/reftest.list
+++ b/layout/reftests/svg/smil/motion/reftest.list
@@ -1,16 +1,19 @@
 # Tests related to SVG Animation (using SMIL), focusing on the animateMotion
 # element.
 
 == animateMotion-by-1.svg      lime.svg
 == animateMotion-from-to-1.svg lime.svg
+== animateMotion-indefinite-to-1.svg lime.svg
+== animateMotion-indefinite-to-2.svg lime.svg
 == animateMotion-rotate-1a.svg lime.svg
 == animateMotion-rotate-1b.svg lime.svg
 == animateMotion-rotate-2.svg  lime.svg
+== animateMotion-to-overridden-1.svg lime.svg
 == animateMotion-values-linear-1.svg animateMotion-values-linear-1-ref.svg
 == animateMotion-values-paced-1a.svg animateMotion-values-paced-1-ref.svg
 == animateMotion-values-paced-1b.svg animateMotion-values-paced-1-ref.svg
 
 # Tests involving <mpath> sub-element
 == animateMotion-mpath-pathLength-1.svg lime.svg
 == animateMotion-mpath-targetChange-1.svg lime.svg
 == animateMotion-mpath-target-transform-1.svg lime.svg
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-by-em-em.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-by-em-em.svg
@@ -1,15 +1,15 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      style="font-size: 2px"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 5em; }
+    rect { stroke: blue; stroke-width: 5em; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "by"            : "10em" };
       testAnimatedRectGrid("animate", [animAttrHash]);
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-by-em-px.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-by-em-px.svg
@@ -1,15 +1,15 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      style="font-size: 2px"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 5em; }
+    rect { stroke: blue; stroke-width: 5em; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "by"            : "20px" };
       testAnimatedRectGrid("animate", [animAttrHash]);
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-by-no-no.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-by-no-no.svg
@@ -1,14 +1,14 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 10; }
+    rect { stroke: blue; stroke-width: 10; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "by"            : "20" };
       testAnimatedRectGrid("animate", [animAttrHash]);
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-by-pct-pct.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-by-pct-pct.svg
@@ -1,15 +1,15 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      width="200px" height="200px"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 5%; }
+    rect { stroke: blue; stroke-width: 5%; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "by"            : "10%" };
       testAnimatedRectGrid("animate", [animAttrHash]);
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-by-px-em.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-by-px-em.svg
@@ -1,15 +1,15 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      style="font-size: 2px"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 10px; }
+    rect { stroke: blue; stroke-width: 10px; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "by"            : "10em" };
       testAnimatedRectGrid("animate", [animAttrHash]);
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-by-px-px.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-by-px-px.svg
@@ -1,14 +1,14 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 10px; }
+    rect { stroke: blue; stroke-width: 10px; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "by"            : "20px" };
       testAnimatedRectGrid("animate", [animAttrHash]);
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-by-em-em.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-by-em-em.svg
@@ -1,15 +1,15 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      style="font-size: 2px"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 10px; }
+    rect { stroke: blue; stroke-width: 10px; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "from"          : "5em",
                            "by"            : "10em" };
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-by-em-px.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-by-em-px.svg
@@ -1,15 +1,15 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      style="font-size: 2px"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 10px; }
+    rect { stroke: blue; stroke-width: 10px; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "from"          : "5em",
                            "by"            : "20px" };
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-by-no-no.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-by-no-no.svg
@@ -1,14 +1,14 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 10px; }
+    rect { stroke: blue; stroke-width: 10px; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "from"          : "10",
                            "by"            : "20" };
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-by-pct-pct.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-by-pct-pct.svg
@@ -1,15 +1,15 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      width="200px" height="200px"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 5%; }
+    rect { stroke: blue; stroke-width: 5%; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "from"          : "5%",
                            "by"            : "10%" };
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-by-px-em.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-by-px-em.svg
@@ -1,15 +1,15 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      style="font-size: 2px"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 10px; }
+    rect { stroke: blue; stroke-width: 10px; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "from"          : "10px",
                            "by"            : "10em" };
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-by-px-px.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-by-px-px.svg
@@ -1,14 +1,14 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 10px; }
+    rect { stroke: blue; stroke-width: 10px; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "from"          : "10px",
                            "by"            : "20px" };
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-to-em-em.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-to-em-em.svg
@@ -1,15 +1,15 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      style="font-size: 2px"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 10px; }
+    rect { stroke: blue; stroke-width: 10px; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "from"          : "5em",
                            "to"            : "15em" };
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-to-em-px.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-to-em-px.svg
@@ -1,15 +1,15 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      style="font-size: 2px"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 10px; }
+    rect { stroke: blue; stroke-width: 10px; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "from"          : "5em",
                            "to"            : "30px" };
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-to-no-no.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-to-no-no.svg
@@ -1,14 +1,14 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 10px; }
+    rect { stroke: blue; stroke-width: 10px; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "from"          : "10",
                            "to"            : "30" };
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-to-pct-pct.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-to-pct-pct.svg
@@ -1,15 +1,15 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      width="200px" height="200px"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 5%; }
+    rect { stroke: blue; stroke-width: 5%; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "from"          : "5%",
                            "to"            : "15%" };
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-to-px-em.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-to-px-em.svg
@@ -1,15 +1,15 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      style="font-size: 2px"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 10px; }
+    rect { stroke: blue; stroke-width: 10px; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "from"          : "10px",
                            "to"            : "15em" };
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-to-px-px.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-from-to-px-px.svg
@@ -1,14 +1,14 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 10px; }
+    rect { stroke: blue; stroke-width: 10px; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "from"          : "10px",
                            "to"            : "30px" };
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-ref.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-ref.svg
@@ -1,9 +1,9 @@
-<svg xmlns="http://www.w3.org/2000/svg">
+<svg xmlns="http://www.w3.org/2000/svg" shape-rendering="crispEdges">
   <rect x="20px" y="20px" width="15px" height="15px" stroke="blue"
         style="stroke-width: 10px">
   </rect>
   <rect x="70px" y="20px" width="15px" height="15px" stroke="blue"
         style="stroke-width: 10px">
   </rect>
   <rect x="120px" y="20px" width="15px" height="15px" stroke="blue"
         style="stroke-width: 13px">
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-to-em-em.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-to-em-em.svg
@@ -1,15 +1,15 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      style="font-size: 2px"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 5em; }
+    rect { stroke: blue; stroke-width: 5em; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "to"            : "15em" };
       testAnimatedRectGrid("animate", [animAttrHash]);
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-to-em-px.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-to-em-px.svg
@@ -1,15 +1,15 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      style="font-size: 2px"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 5em; }
+    rect { stroke: blue; stroke-width: 5em; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "to"            : "30px" };
       testAnimatedRectGrid("animate", [animAttrHash]);
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-to-no-no.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-to-no-no.svg
@@ -1,14 +1,14 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 10; }
+    rect { stroke: blue; stroke-width: 10; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "to"            : "30" };
       testAnimatedRectGrid("animate", [animAttrHash]);
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-to-pct-pct.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-to-pct-pct.svg
@@ -1,15 +1,15 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      width="200px" height="200px"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 5%; }
+    rect { stroke: blue; stroke-width: 5%; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "to"            : "15%" };
       testAnimatedRectGrid("animate", [animAttrHash]);
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-to-px-em.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-to-px-em.svg
@@ -1,15 +1,15 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      style="font-size: 2px"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 10px; }
+    rect { stroke: blue; stroke-width: 10px; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "to"            : "15em" };
       testAnimatedRectGrid("animate", [animAttrHash]);
--- a/layout/reftests/svg/smil/style/anim-css-strokewidth-1-to-px-px.svg
+++ b/layout/reftests/svg/smil/style/anim-css-strokewidth-1-to-px-px.svg
@@ -1,14 +1,14 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      class="reftest-wait"
      onload="go()">
   <style>
-    rect { stroke: blue; stroke-width: 10px; }
+    rect { stroke: blue; stroke-width: 10px; shape-rendering: crispEdges; }
   </style>
   <script xlink:href="../smil-grid.js" type="text/javascript"/>
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <script>
     function go() {
       var animAttrHash = { "attributeName" : "stroke-width",
                            "to"            : "30px" };
       testAnimatedRectGrid("animate", [animAttrHash]);
--- a/layout/tables/crashtests/crashtests.list
+++ b/layout/tables/crashtests/crashtests.list
@@ -75,17 +75,17 @@ load 391898-1.html
 load 391901-1.html
 load 392132-1.xhtml
 load 397448-1.html
 load 398157-1.xhtml
 load 399209-1.xhtml
 load 403249-1.html
 load 403579-1.html
 load 404301-1.xhtml
-asserts(2) load 408753-1.xhtml # Bug 512749
+asserts(1-2) load 408753-1.xhtml # Bug 512749
 load 410426-1.html
 load 411582.xhtml
 load 413091.xhtml
 load 413180-1.html
 load 416845-1.xhtml
 load 416845-2.xhtml
 load 416845-3.html   
 asserts(12) load 420654-1.xhtml # Bug 575011
@@ -100,11 +100,11 @@ load 467141-1.html
 load 488388-1.html
 load 513732-1.html
 asserts(0-1) load 533380-1.xhtml # Bug 614457
 load 534716-1.html
 load 573354-1.xhtml
 load 576890-1.html
 load 576890-2.html
 load 576890-3.html
-asserts(0-1) load 595758-1.xhtml # Bug 453871
+asserts(0-3) load 595758-1.xhtml # Bug 453871
 load 595758-2.xhtml
 load 678447-1.html
--- a/layout/xul/base/src/tree/src/crashtests/crashtests.list
+++ b/layout/xul/base/src/tree/src/crashtests/crashtests.list
@@ -1,12 +1,12 @@
 load 307298-1.xul
 load 309732-1.xul
 load 309732-2.xul
-load 366583-1.xul
+asserts-if(Android,3) load 366583-1.xul
 asserts-if(winWidget,0-4) load 380217-1.xul # bug 616710
 load 382444-1.html
 load 391178-1.xhtml
 load 391178-2.xul
 load 393665-1.xul
 load 399227-1.xul
 load 399227-2.xul
 load 399692-1.xhtml
--- a/mobile/app/mobile.js
+++ b/mobile/app/mobile.js
@@ -568,16 +568,18 @@ pref("services.sync.prefs.sync.signon.re
 
 // threshold where a tap becomes a drag, in 1/240" reference pixels
 // The names of the preferences are to be in sync with nsEventStateManager.cpp
 pref("ui.dragThresholdX", 25);
 pref("ui.dragThresholdY", 25);
 
 #if MOZ_PLATFORM_MAEMO == 6
 pref("layers.acceleration.disabled", false);
+#elifdef ANDROID
+pref("layers.acceleration.disabled", false);
 #else
 pref("layers.acceleration.disabled", true);
 #endif
 
 pref("notification.feature.enabled", true);
 
 // prevent tooltips from showing up
 pref("browser.chrome.toolbar_tips", false);
--- a/mobile/chrome/content/Util.js
+++ b/mobile/chrome/content/Util.js
@@ -156,25 +156,39 @@ let Util = {
     Services.io.offline = false;
   },
 
   isParentProcess: function isInParentProcess() {
     let appInfo = Cc["@mozilla.org/xre/app-info;1"];
     return (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT);
   },
 
-  isTablet: function isTablet() {
+  isTablet: function isTablet(options) {
+    let forceUpdate = options && 'forceUpdate' in options && options.forceUpdate;
+
+    if ('_isTablet' in this && !forceUpdate)
+      return this._isTablet;
+
+    let tabletPref = Services.prefs.getIntPref("browser.ui.layout.tablet");
+
+    // Act according to user prefs if tablet mode has been
+    // explicitly disabled or enabled.
+    if (tabletPref == 0)
+      return this._isTablet = false;
+    else if (tabletPref == 1)
+      return this._isTablet = true;
+
     let dpi = this.displayDPI;
     if (dpi <= 96)
-      return (window.innerWidth > 1024);
+      return this._isTablet = (window.innerWidth > 1024);
 
     // See the tablet_panel_minwidth from mobile/themes/core/defines.inc
     let tablet_panel_minwidth = 124;
     let dpmm = 25.4 * window.innerWidth / dpi;
-    return (dpmm >= tablet_panel_minwidth);
+    return this._isTablet = (dpmm >= tablet_panel_minwidth);
   },
 
   isPortrait: function isPortrait() {
 #ifdef MOZ_PLATFORM_MAEMO
     return (screen.width <= screen.height);
 #elifdef ANDROID
     return (screen.width <= screen.height);
 #else
--- a/mobile/chrome/content/browser-ui.js
+++ b/mobile/chrome/content/browser-ui.js
@@ -181,16 +181,18 @@ var BrowserUI = {
 
   _toolbarLocked: 0,
 
   isToolbarLocked: function isToolbarLocked() {
     return this._toolbarLocked;
   },
 
   lockToolbar: function lockToolbar() {
+    if (Util.isTablet())
+      return;
     this._toolbarLocked++;
     document.getElementById("toolbar-moveable-container").top = "0";
     if (this._toolbarLocked == 1)
       Browser.forceChromeReflow();
   },
 
   unlockToolbar: function unlockToolbar() {
     if (!this._toolbarLocked)
@@ -374,21 +376,16 @@ var BrowserUI = {
   get toolbarH() {
     if (!this._toolbarH) {
       let toolbar = document.getElementById("toolbar-main");
       this._toolbarH = toolbar.boxObject.height;
     }
     return this._toolbarH;
   },
 
-  get sidebarW() {
-    delete this._sidebarW;
-    return this._sidebarW = Elements.controls.getBoundingClientRect().width;
-  },
-
   sizeControls: function(windowW, windowH) {
     // tabs
     document.getElementById("tabs").resize();
     AwesomeScreen.doResize(windowW, windowH);
 
     // content navigator helper
     document.getElementById("content-navigator").contentHasChanged();
   },
@@ -547,21 +544,37 @@ var BrowserUI = {
   },
 
   observe: function observe(aSubject, aTopic, aData) {
     if (aTopic == "nsPref:changed" && aData == "browser.ui.layout.tablet")
       this.updateTabletLayout();
   },
 
   updateTabletLayout: function updateTabletLayout() {
-    let tabletPref = Services.prefs.getIntPref("browser.ui.layout.tablet");
-    if (tabletPref == 1 || (tabletPref == -1 && Util.isTablet()))
+    if (Util.isTablet({ forceUpdate: true })) {
+      this.unlockToolbar();
       Elements.urlbarState.setAttribute("tablet", "true");
-    else
+    } else {
       Elements.urlbarState.removeAttribute("tablet");
+    }
+
+    // Tablet mode changes the size of the thumbnails
+    // in the tabs container. Hence we have to force a
+    // thumbnail update on all tabs.
+    setTimeout(function(self) {
+      self._updateAllTabThumbnails();
+    }, 0, this);
+  },
+
+  _updateAllTabThumbnails: function() {
+    let tabs = Browser.tabs;
+
+    tabs.forEach(function(tab) {
+      tab.updateThumbnail({ force: true });
+    });
   },
 
   update: function(aState) {
     let browser = Browser.selectedBrowser;
 
     switch (aState) {
       case TOOLBARSTATE_LOADED:
         this._updateToolbar();
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -1033,17 +1033,17 @@ var Browser = {
         snappedX = -ritevis * ritew * dirVal;
       }
     }
 
     return Math.round(snappedX);
   },
 
   tryFloatToolbar: function tryFloatToolbar(dx, dy) {
-    if (this.floatedWhileDragging)
+    if (this.floatedWhileDragging || Util.isTablet())
       return;
 
     let [leftvis, ritevis, leftw, ritew] = Browser.computeSidebarVisibility(dx, dy);
     if (leftvis > 0 || ritevis > 0) {
       BrowserUI.lockToolbar();
       this.floatedWhileDragging = true;
     }
   },
@@ -1284,17 +1284,17 @@ Browser.MainDragger.prototype = {
     return { x: true, y: true };
   },
 
   dragStart: function dragStart(clientX, clientY, target, scroller) {
     let browser = getBrowser();
     let bcr = browser.getBoundingClientRect();
     this._contentView = browser.getViewAt(clientX - bcr.left, clientY - bcr.top);
     this._stopAtSidebar = 0;
-    this._panToolbars = !Elements.urlbarState.getAttribute("tablet");
+    this._panToolbars = !Util.isTablet();
     if (this._sidebarTimeout) {
       clearTimeout(this._sidebarTimeout);
       this._sidebarTimeout = null;
     }
   },
 
   dragStop: function dragStop(dx, dy, scroller) {
     if (this._contentView && this._contentView._updateCacheViewport)
@@ -1903,17 +1903,17 @@ const ContentTouchHandler = {
     let bcr = browser.getBoundingClientRect();
     let rect = new Rect(0, 0, window.innerWidth, window.innerHeight);
     rect.restrictTo(Rect.fromRect(bcr));
 
     // Check if the user touched near to one of the edges of the browser area
     // or if the urlbar is showing
     this.canCancelPan = (aX >= rect.left + kSafetyX) && (aX <= rect.right - kSafetyX) &&
                         (aY >= rect.top  + kSafetyY) &&
-                        (bcr.top == 0 || Elements.urlbarState.getAttribute("tablet"));
+                        (bcr.top == 0 || Util.isTablet());
   },
 
   tapDown: function tapDown(aX, aY) {
     let browser = getBrowser();
     browser.focus();
 
     // if the page might capture touch events, we give it the option
     this.updateCanCancel(aX, aY);
@@ -2892,17 +2892,16 @@ Tab.prototype = {
   _createBrowser: function _createBrowser(aURI, aInsertBefore) {
     if (this._browser)
       throw "Browser already exists";
 
     // Create a notification box around the browser
     let notification = this._notification = document.createElement("notificationbox");
     notification.classList.add("inputHandler");
 
-    // Create the browser using the current width the dynamically size the height
     let browser = this._browser = document.createElement("browser");
     browser.setAttribute("class", "viewable-width viewable-height");
     this._chromeTab.linkedBrowser = browser;
 
     browser.setAttribute("type", "content");
 
     let useRemote = Services.prefs.getBoolPref("browser.tabs.remote");
     let useLocal = Util.isLocalScheme(aURI);
@@ -3146,25 +3145,28 @@ function rendererFactory(aBrowser, aCanv
 
 /* ViewableAreaObserver is an helper object where width/height represents the
  * size of the currently viewable area in pixels. This is use instead of
  * window.innerHeight/innerWidth because some keyboards does not resize the
  * window but floats over it.
  */
 var ViewableAreaObserver = {
   get width() {
-    return this._width || window.innerWidth;
+    let width = this._width || window.innerWidth;
+    if (Util.isTablet()) {
+      let sidebarWidth = Math.round(Elements.tabs.getBoundingClientRect().width);
+      width -= sidebarWidth;
+    }
+    return width;
   },
 
   get height() {
     let height = (this._height || window.innerHeight);
-    if (Elements.urlbarState.getAttribute("tablet")) {
-      let toolbarHeight = Math.round(document.getElementById("toolbar-main").getBoundingClientRect().height);
-      height -= toolbarHeight;
-    }
+    if (Util.isTablet())
+      height -= BrowserUI.toolbarH;
     return height;
   },
 
   _isKeyboardOpened: true,
   get isKeyboardOpened() {
     return this._isKeyboardOpened;
   },
 
--- a/mobile/chrome/content/browser.xul
+++ b/mobile/chrome/content/browser.xul
@@ -193,32 +193,32 @@
     <key id="key_newTab" key="t" modifiers="accel" command="cmd_newTab"/>
     <key id="key_closeTab" key="w" modifiers="accel" command="cmd_closeTab"/>
     <key id="key_undoCloseTab" key="t" modifiers="accel,shift" command="cmd_undoCloseTab"/>
   </keyset>
 
   <stack flex="1" id="stack">
     <scrollbox id="controls-scrollbox" style="overflow: hidden; -moz-box-orient: horizontal; position: relative;" flex="1" observes="bcast_urlbarState">
       <vbox id="tabs-sidebar" class="sidebar" observes="bcast_uidiscovery">
-        <spacer class="toolbar-height"/>
+        <spacer class="toolbar-height" id="tabs-spacer" observes="bcast_urlbarState"/>
         <!-- Left toolbar -->
-        <vbox id="tabs-container" class="panel-dark" flex="1">
-          <vbox id="tabs" flex="1"
+        <vbox id="tabs-container" class="panel-dark" flex="1" observes="bcast_urlbarState">
+          <vbox id="tabs" flex="1" observes="bcast_urlbarState"
                 onselect="BrowserUI.selectTab(this);"
                 onreloadtab="BrowserUI.undoCloseTab()"
                 onclosetab="BrowserUI.closeTab(this)"
                 onclosereloadtab="this._container.removeTab(this)"/>
           <hbox id="tabs-controls">
-            <toolbarbutton id="newtab-button" class="button-control" command="cmd_newTab"/>
+            <toolbarbutton id="newtab-button" class="button-control" command="cmd_newTab" observes="bcast_urlbarState"/>
           </hbox>
         </vbox>
       </vbox>
 
       <!-- Page Area -->
-      <stack>
+      <stack id="page-stack" observes="bcast_urlbarState">
         <scrollbox id="page-scrollbox">
           <vbox>
             <!-- Main Toolbar -->
             <box id="toolbar-container" class="panel-dark toolbar-height">
               <box id="toolbar-moveable-container" observes="bcast_uidiscovery">
                 <toolbar id="toolbar-main" class="panel-dark viewable-width" observes="bcast_urlbarState">
                   <toolbarbutton id="tool-back2" class="tool-back button-actionbar" command="cmd_back"/>
                   <toolbarbutton id="tool-forward2" class="tool-forward button-actionbar" command="cmd_forward"/>
--- a/mobile/chrome/content/tabs.xml
+++ b/mobile/chrome/content/tabs.xml
@@ -2,31 +2,71 @@
 
 <bindings
     xmlns="http://www.mozilla.org/xbl"
     xmlns:xbl="http://www.mozilla.org/xbl"
     xmlns:html="http://www.w3.org/1999/xhtml"
     xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <binding id="documenttab">
-    <content>
+    <content observes="bcast_urlbarState">
       <xul:stack anonid="page" class="documenttab-container" flex="1">
-        <html:canvas anonid="thumbnail" class="documenttab-thumbnail" left="0" width="104" height="65" moz-opaque="true" empty="true"
-          onclick="document.getBindingParent(this)._onClick()"/>
-        <xul:hbox class="documenttab-reload" left="0" top="0" width="104" height="65" onclick="document.getBindingParent(this)._onUndo();"/>
-        <xul:hbox class="documenttab-close-container" start="-16" top="0" height="65" width="55" align="center" onclick="document.getBindingParent(this)._onClose()">
-          <xul:image anonid="close" class="documenttab-close" mousethrough="always"/>
+        <html:canvas anonid="thumbnail" class="documenttab-thumbnail" left="0" moz-opaque="true" empty="true"
+          onclick="document.getBindingParent(this)._onClick()" observes="bcast_urlbarState"/>
+        <xul:hbox anonid="reload" class="documenttab-reload" left="0" top="0" onclick="document.getBindingParent(this)._onUndo();" observes="bcast_urlbarState"/>
+        <xul:hbox anonid="close-container" class="documenttab-close-container" top="0" align="center" onclick="document.getBindingParent(this)._onClose()" observes="bcast_urlbarState">
+          <xul:image anonid="close" class="documenttab-close" mousethrough="always" observes="bcast_urlbarState"/>
         </xul:hbox>
       </xul:stack>
     </content>
 
     <implementation>
       <field name="ignoreUndo">false</field>
-      <field name="thumbnail">document.getAnonymousElementByAttribute(this, "anonid", "thumbnail");</field>
-      <field name="_container">this.parentNode.parentNode;</field>
+      <field name="thumbnail" readonly="true">document.getAnonymousElementByAttribute(this, "anonid", "thumbnail");</field>
+      <field name="_reload" readonly="true">document.getAnonymousElementByAttribute(this, "anonid", "reload");</field>
+      <field name="_closeContainer" readonly="true">document.getAnonymousElementByAttribute(this, "anonid", "close-container");</field>
+      <field name="_container" readonly="true">this.parentNode.parentNode;</field>
+
+      <constructor>
+        <![CDATA[
+          this.updateTabletLayout(this.thumbnail);
+        ]]>
+      </constructor>
+
+      <method name="updateTabletLayout">
+        <parameter name="thumbnail"/>
+        <body>
+          <![CDATA[
+            let tabWidth, tabHeight, closeWidth, closeHeight;
+
+            if (Util.isTablet()) {
+              tabWidth = 176;
+              tabHeight = 110;
+              closeWidth = 41;
+              closeHeight = 117;
+            } else {
+              tabWidth = 104;
+              tabHeight = 65;
+              closeWidth = 55;
+              closeHeight = 65;
+            }
+
+            if (tabWidth != thumbnail.width) {
+              let reload = this._reload;
+              let closeContainer = this._closeContainer;
+
+              thumbnail.width = reload.width = tabWidth;
+              thumbnail.height = reload.height = tabHeight;
+              closeContainer.width = closeWidth;
+              closeContainer.height = closeHeight;
+            }
+          ]]>
+        </body>
+      </method>
+
       <method name="_onClick">
         <body>
           <![CDATA[
             this._container.selectedTab = this;
 
             let selectFn = new Function("event", this._container.parentNode.getAttribute("onselect"));
             selectFn.call(this);
           ]]>
@@ -56,24 +96,28 @@
 
       <method name="updateThumbnail">
         <parameter name="browser"/>
         <parameter name="width"/>
         <parameter name="height"/>
         <body>
           <![CDATA[
             let thumbnail = this.thumbnail;
+            // Ensure the thumbnail will have the correct
+            // dimensions for tablet and phone modes
+            this.updateTabletLayout(thumbnail);
+
             if (browser.currentURI.spec == "about:blank") {
               thumbnail.setAttribute("empty", "true");
               return;
             }
             thumbnail.removeAttribute("empty");
 
-            const tabWidth = 104;
-            const tabHeight = 65;
+            const tabWidth = thumbnail.width;
+            const tabHeight = thumbnail.height;
 
             let ratio = tabHeight / tabWidth;
             if (browser.contentDocumentWidth > 0)
               width = Math.min(width, browser.contentDocumentWidth);
 
             if (browser.contentDocumentHeight > 0)
               height = Math.min(height, browser.contentDocumentHeight);
 
--- a/mobile/themes/core/browser.css
+++ b/mobile/themes/core/browser.css
@@ -981,16 +981,17 @@ documenttab[selected="true"] {
 documenttab:hover:active > stack > .documenttab-thumbnail,
 documenttab[selected="true"] > stack > .documenttab-thumbnail {
   opacity: 1.0;
 }
 
 .documenttab-close-container {
   position: relative;
   left: -16px;
+  -moz-margin-start: -16px;
   -moz-margin-end: 49px;
 }
 
 .documenttab-close {
   width: 40px;
   height: 40px;
   list-style-image: url("chrome://browser/skin/images/close-inactive-tab-hdpi.png");
 }
@@ -1570,56 +1571,16 @@ setting {
   from { -moz-transform: translateX(0); }
   10% { -moz-transform: translateX(-moz-calc(-121px - @border_width_large@ - 2*@padding_normal@)); }
   45% { -moz-transform: translateX(-moz-calc(-121px - @border_width_large@ - 2*@padding_normal@)); }
   55% { -moz-transform: translateX(@sidebar_width_minimum@); }
   90% { -moz-transform: translateX(@sidebar_width_minimum@); }
   to { -moz-transform: translateX(0); }
 }
 
-/* Tablet mode */
-
-.spacer-actionbar,
-.button-actionbar {
-  visibility: collapse;
-}
-
-.button-actionbar[disabled="true"] {
-  opacity: 0.5;
-}
-
-.button-actionbar:hover:active {
-  background-color: #8db8d8;
-}
-
-#toolbar-main[tablet="true"] > .spacer-actionbar,
-#toolbar-main[tablet="true"] > .button-actionbar {
-  visibility: visible;
-}
-
-#controls-scrollbox[tablet="true"] > #controls-sidebar {
-  visibility: collapse;
-}
-
-#controls-scrollbox[tablet="true"] > #tabs-sidebar {
-  border: none;
-  position: fixed;
-  top: -moz-calc(@touch_button_xlarge@ + @margin_normal@);
-  visibility: collapse;
-}
-#controls-scrollbox[tablet="true"] > #tabs-sidebar:-moz-locale-dir(ltr) {
-  right: 0;
-}
-#controls-scrollbox[tablet="true"] > #tabs-sidebar:-moz-locale-dir(rtl) {
-  left: 0;
-}
-#controls-scrollbox[tablet="true"] > #tabs-sidebar[open] {
-  visibility: visible;
-}
-
 /* Text selection handles */
 
 #selectionhandle-start,
 #selectionhandle-end {
   min-width: 35px !important;
   width: 35px !important;
   padding: 0 !important;
   margin: 0 !important;
@@ -1635,9 +1596,11 @@ setting {
 
 @media (min-width: @tablet_panel_minwidth@) {
   #awesome-panels {
     -moz-box-shadow: 0px 0px @shadow_width_small@ black;
   }
   #search-engines-popup {
     max-width: -moz-calc(@tablet_panel_minwidth@);
   }
-}
\ No newline at end of file
+}
+
+%include tablet.css
--- a/mobile/themes/core/gingerbread/browser.css
+++ b/mobile/themes/core/gingerbread/browser.css
@@ -930,16 +930,17 @@ documenttab[selected="true"] {
 documenttab:hover:active > stack > .documenttab-thumbnail,
 documenttab[selected="true"] > stack > .documenttab-thumbnail {
   opacity: 1.0;
 }
 
 .documenttab-close-container {
   position: relative;
   left: -16px;
+  -moz-margin-start: -16px;
   -moz-margin-end: 49px;
 }
 
 .documenttab-close {
   width: 40px;
   height: 40px;
   list-style-image: url("chrome://browser/skin/images/close-inactive-tab-hdpi.png");
 }
@@ -1540,56 +1541,16 @@ setting {
   from { -moz-transform: translateX(0); }
   10% { -moz-transform: translateX(-moz-calc(-121px - @border_width_large@ - 2*@padding_normal@)); }
   45% { -moz-transform: translateX(-moz-calc(-121px - @border_width_large@ - 2*@padding_normal@)); }
   55% { -moz-transform: translateX(@sidebar_width_minimum@); }
   90% { -moz-transform: translateX(@sidebar_width_minimum@); }
   to { -moz-transform: translateX(0); }
 }
 
-/* Tablet mode */
-
-.spacer-actionbar,
-.button-actionbar {
-  visibility: collapse;
-}
-
-.button-actionbar[disabled="true"] {
-  opacity: 0.5;
-}
-
-.button-actionbar:hover:active {
-  background-color: #8db8d8;
-}
-
-#toolbar-main[tablet="true"] > .spacer-actionbar,
-#toolbar-main[tablet="true"] > .button-actionbar {
-  visibility: visible;
-}
-
-#controls-scrollbox[tablet="true"] > #controls-sidebar {
-  visibility: collapse;
-}
-
-#controls-scrollbox[tablet="true"] > #tabs-sidebar {
-  border: none;
-  position: fixed;
-  top: -moz-calc(@touch_button_xlarge@ + @margin_normal@);
-  visibility: collapse;
-}
-#controls-scrollbox[tablet="true"] > #tabs-sidebar:-moz-locale-dir(ltr) {
-  right: 0;
-}
-#controls-scrollbox[tablet="true"] > #tabs-sidebar:-moz-locale-dir(rtl) {
-  left: 0;
-}
-#controls-scrollbox[tablet="true"] > #tabs-sidebar[open] {
-  visibility: visible;
-}
-
 /* Text selection handles */
 
 #selectionhandle-start,
 #selectionhandle-end {
   min-width: 35px !important;
   width: 35px !important;
   padding: 0 !important;
   margin: 0 !important;
@@ -1598,16 +1559,9 @@ setting {
 #selectionhandle-start {
   list-style-image: url("chrome://browser/skin/images/handle-start.png");
 }
 
 #selectionhandle-end {
   list-style-image: url("chrome://browser/skin/images/handle-end.png");
 }
 
-@media (min-width: @tablet_panel_minwidth@) {
-  #awesome-panels {
-    -moz-box-shadow: 0px 0px @shadow_width_small@ black;
-  }
-  #search-engines-popup {
-    max-width: -moz-calc(@tablet_panel_minwidth@);
-  }
-}
+%include ../tablet.css
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1e616b6698a5fc77fbf709cf62af43e7aeb949df
GIT binary patch
literal 626
zc$@)p0*(ENP)<h;3K|Lk000e1NJLTq0015U001lq1^@s6a)Jm10000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!6iGxuRCwC#mcdKHa1_V2Hj5-78pD={
zu!D4vAS08gLxiB-Iz}L<;3fSB^c>|Su(NjQU+`YtyJ_KZ5D^sw#lq6C_u&0tjNF!k
z?C|@+2Y%bWd*8kHd%tb&e!uS;#TavqXmDe0%#FD*H~#;|f(^|$FiG<c@MWPBNcZ8y
z7_TdUkB(n~7vRmH^8kL*iKM$TGq)<W1jyxbc@Kg491sAe4W{^Te$?c0xgyMGiNOPZ
z1WZ@}wnL$i77PaaiA3TOj-$X5FbzzQX01>tR8fP#*a3oOv8^)3wR(-m<25{Jx7%CE
zWU@jf4G?m%Sln+k8U@s(QmIoab;n7@BFm^$Djoiic{H2Np0P|ZYt+&`9<$hP8~<Fa
zapZcvzFw(Rj=SCN6g<Qgs{+fkTCJYL^bxoRKAmLD5C8>Ot<`D=Ec0P9wY$b_^k@rd
znM~$dQIuPD!Rz%t=kxgs+B)x+nf~(4B~c^!pt+7zRgH+E_>O3rCZ*HqlUA#>NZU=e
z712gnWMCQC#HPa1VyUs@NH`pR!gG;GL~S;kyQGz^;#!%`0AUP>f%T@i-oT3fn!#Lh
zVmt?I#A30VA50Zi4Wl_$2M9PZ#+x@W7-BFL^h?3a@!{}oM;$)&KE|e+H+&?XXs`Bk
zI++^F_>p)R6xhxSL^6C9pDlEPPS<l{%zu5jF*oMM+?X5x?f4d804qkI*d{1O6951J
M07*qoM6N<$f_zRRW&i*H
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..478e9c85e270e51428f181c423d04d5aa448eadb
GIT binary patch
literal 1572
zc$@(w2HW|GP)<h;3K|Lk000e1NJLTq001cf004Ce1^@s6(=5n(0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU%#z{m$RCwC#oJ&ljRTRhjwWSZ~3{wh%
z2xYVsoz~8Dzz$HW22;mOjERYf0|~e@aUmv#4GR;L$4UY$hBX)sgoH3ApbH{sT(AHm
z8Uh3Y0enDG1r$mV`ncW$_mT@~g)+1~Cf`X;zJZkFm;XKY-1FTzrxGDVAxV<rEQ8M_
z(<A{(tw3lD5H}<P<W8_cf+?9t)JT^a;8g5Mlt`Ca#eHUG#;QgPsevEz^7335AptOr
zK}K{s-AihO@yJ!wQWc3-t9?_AP(=XLQ`hzP_m@*{qZ*NlN|v_)@G)3&r_=c^nq)34
zvyOT?Kn@HHyl5~OJaL`L@VP{|u$v9k^Qk)>4u>}o2>eQzr4&*C1ofVvZl~^9Sy}m(
z2$nKPcABIy1p)8|b@%l2^dLE9Nrx2FgZR6~me^iaR(5xFb@h7^#gYcelv6XftJEK-
z{xrm3TU*<EySuyVB!(pnk}1Z)v@GsGxg6@(LA}=2)*2dr-;guxQXmB&exzwxuDe3r
z$W()6E%JK3<wHY54L+Z5lAP1jkC@v|R4hz24hsKHD=I2VZ)|KVwb^XWf`WpItgNg%
zEODRP)E5Nf%a|q<1BcJ%=4Ok><0&aDEWDkao$aIvx%g3&y*ds)=~RWH<KErfUG8?f
zUoo4_cWKp<bLmIYIbu>0&Qyr6JnB}v-R>G6AODn|3~MC8b{3?PsdkkmTq}($*Tlrc
zgM)*EZIUGWFGwX@&P?is)E!MtP4D>q{$EIvEfypPG_izRLaUNb!r^d`q`;y<Dp{Tb
z1ufK{@9XRPI1-73Ns8<=q{MbFoD5G<FYW2+`6yKi#)9N!)05P1(R}wtGB?P1ASJfU
z+0>t<{=&k-!U#cN$|&gu&Rj!FOG~NMYJC;UeT!J*@xnk~TU&b{)1{DjssN<EqN2h?
zlXf{~NKIW`UEGyQG9bmOMorIU8@4+@F(v_0m6MZm9V;ZStW~rI%*6`HK_#tLYrqJ3
z;+|TiQt7cma!>`PogGa{@rhPRwEqnuL&}gcqzoxT%8)Xo3@Jm(kTRqUDMQMTGNcSC
zL&}gcqzoxT%8)65B$y$||3ygvC81F0AIwTd;292w_b@_oz(dHry}d1rkN_8^9)joA
z*4A%Wl?2EG09{^Qp2w<Wh(QL2hlhW_1SzpWHr^AIp*ZTf&D`19`P^VI<YQZIP;#Go
z0G^YRlV78eQs}S(VCV^gCeB+no9$j85cm^YhZWEUnUXuRv$Go`BO~3|l;mnc-z2nL
zL%*7v?)2|4Dam&^sJTo1Z*Z^I+qAj4Igd%n!yT_UYGg97__SA6R=(!*`F_UIKN$@a
zdW4=SE-v=W&(D8}2~q@w9S=Q~(3yI(x3{-G8ExC~v~Y`KDUj%)joV^2n@h*W##;S;
z|1t(hao6*P_-iZ#Kv~=1;NS=A>+7SzV9=i^NGYEAZr0Sqfi;3_Ef!09XJ_Zj^bjb|
z%*=FTWMnuls|hMD$m2gcIg~3-jU2Z(noK5rM@L7A-EMd0=H}is8jW_nUY~ziDJbUW
z&KRfSb2xgI6(B6KSZJ837uVO<-<z76da$vvF_nmzyy!#|pEdz#Bdf4rMBzq5L&IB3
zOH0G&>0wX!jMyn?0KUQ$26b&UH8rm<E-rqRQpgygp<(JmjR2zyC0$)zAMWq(|CMsc
z7-NA(76Q)d>gu;??)@DF<f$=14Lc|R^mbKM)qVQ5`Ue_FK~)V?6vk>??d|RFM<S5}
zG?0R#;@riZxw*L>RFDEFOt3)0f6nD{xkI6lFIv%?($bc_Qp4*@fW8QBt*xznhU$Kj
z9LdQqDBvz?pVk6j!0#?}b|>r-;0Q#+mK~1Q5Us8rqWWTl!?H}0xSC3KdG-+F_h5)u
zKGOE~_Kz4Ld2GU4t8#R7^e0p?Da0nPQ(?)&Sig$r_|{p0`1^u5B>FEk;_*fP6<`2{
WE)xgo3A0520000<MNUMnLSTY9jN{n=
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1e616b6698a5fc77fbf709cf62af43e7aeb949df
GIT binary patch
literal 626
zc$@)p0*(ENP)<h;3K|Lk000e1NJLTq0015U001lq1^@s6a)Jm10000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!6iGxuRCwC#mcdKHa1_V2Hj5-78pD={
zu!D4vAS08gLxiB-Iz}L<;3fSB^c>|Su(NjQU+`YtyJ_KZ5D^sw#lq6C_u&0tjNF!k
z?C|@+2Y%bWd*8kHd%tb&e!uS;#TavqXmDe0%#FD*H~#;|f(^|$FiG<c@MWPBNcZ8y
z7_TdUkB(n~7vRmH^8kL*iKM$TGq)<W1jyxbc@Kg491sAe4W{^Te$?c0xgyMGiNOPZ
z1WZ@}wnL$i77PaaiA3TOj-$X5FbzzQX01>tR8fP#*a3oOv8^)3wR(-m<25{Jx7%CE
zWU@jf4G?m%Sln+k8U@s(QmIoab;n7@BFm^$Djoiic{H2Np0P|ZYt+&`9<$hP8~<Fa
zapZcvzFw(Rj=SCN6g<Qgs{+fkTCJYL^bxoRKAmLD5C8>Ot<`D=Ec0P9wY$b_^k@rd
znM~$dQIuPD!Rz%t=kxgs+B)x+nf~(4B~c^!pt+7zRgH+E_>O3rCZ*HqlUA#>NZU=e
z712gnWMCQC#HPa1VyUs@NH`pR!gG;GL~S;kyQGz^;#!%`0AUP>f%T@i-oT3fn!#Lh
zVmt?I#A30VA50Zi4Wl_$2M9PZ#+x@W7-BFL^h?3a@!{}oM;$)&KE|e+H+&?XXs`Bk
zI++^F_>p)R6xhxSL^6C9pDlEPPS<l{%zu5jF*oMM+?X5x?f4d804qkI*d{1O6951J
M07*qoM6N<$f_zRRW&i*H
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fd8e46b0c15e533f5c6360a659fbddc5a386b7fa
GIT binary patch
literal 546
zc$@(u0^R+IP)<h;3K|Lk000e1NJLTq0015U001lq1^@s6a)Jm10000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz#7RU!RCwC#mN84iKp2Kwn^sX2gb-}(
zAUZjSprV54ApQX9>`$nJlm9@}MW}<5xcCSB2kPYFYA1(^sI&#a(pn`F-@`X}grvDP
zU>)w@fnM*;_ws%B-6cuabrZc9eTg0oZLE#8u{PGm|KHe9)TO`xf49I_gwCMuBaX4q
z*kFY7H}DGTK3xWkQJ1FfG0a@W*aQ~HbAADa7_=^#+SF}=EI0x0;3+Vw_z;L-0<43E
z`!lY<5|{?Vpr4vWP;`IC2AB+stI}L8mhF`DHE_t1=7`923v5$!%x7AmQ57;yOBwA2
zWG*<9GA&Xop2>v8O)7qKd5t47TLuSU5L`=D@G?CI74Ge4oQypTV1orvkTUNm(@yr-
z8xFg;0d7G_TC0Ie9-U^}OuM+bOg55es(mm|lP1@Wz!Z;?6&X#j%odmht86Nlr7n;v
z|0{z$wN|^BDyE}gh5^eyQ?cK3zBSq0jANVyE8s4`)RwB@Hy72(#c8e-dqG^24`3JE
z@VHdSGq?vk)R?@lL$73&b1Z_4`(6@N8ak5BVq^JV5-;5vd*<?Mu@<2-B%Kq-SbzFx
kV{NRBwXrt-yYVf+01?=dN6%R1uK)l507*qoM6N<$f(;q;0ssI2
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1d9d1ae2308f8adcb70fddb823b04e25b12d456a
GIT binary patch
literal 263
zc%17D@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%k|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*A(MJzX3_DsH_AG3076;8`Pd<mAbVC-;B3`tRt)lP6d1xDwIi
zvGPmHB~5mB&)Z)(GS_{)CoLdbobpY``q?>~i77@Fc@sM=J!($unkx3nHD%(BeXC9{
zGM&1>Nh>72LrD0)c=0nE3l3GaeM?R}R+uuQLgdBY2MVFpPnOvH-YoRx-`{P@8>^V>
z+IFaGPxxHZCcNd>`eW-~@n|i1$E#d6!TDPk_fft_an+GAOgs#;BNY2GFZ%8RI-0@L
L)z4*}Q$iB}x3+FW
--- a/mobile/themes/core/honeycomb/browser.css
+++ b/mobile/themes/core/honeycomb/browser.css
@@ -32,16 +32,17 @@
  * 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 ***** */
 
 %filter substitution
 %include defines.inc
+%define honeycomb 1
 
 /* main toolbar (URL bar) -------------------------------------------------- */
 #toolbar-main {
   -moz-appearance: none;
   -moz-box-align: center;
   padding: 0;
   background: @color_toolbar_background@;
   border: none;
@@ -1013,16 +1014,17 @@ documenttab[selected="true"] {
 documenttab:hover:active > stack > .documenttab-thumbnail,
 documenttab[selected="true"] > stack > .documenttab-thumbnail {
   opacity: 1.0;
 }
 
 .documenttab-close-container {
   position: relative;
   left: -16px;
+  -moz-margin-start: -16px;
   -moz-margin-end: 49px;
 }
 
 .documenttab-close {
   width: 40px;
   height: 40px;
   list-style-image: url("chrome://browser/skin/images/close-inactive-tab-hdpi.png");
 }
@@ -1689,52 +1691,16 @@ setting {
   from { -moz-transform: translateX(0); }
   10% { -moz-transform: translateX(-moz-calc(-121px - @border_width_large@ - 2*@padding_normal@)); }
   45% { -moz-transform: translateX(-moz-calc(-121px - @border_width_large@ - 2*@padding_normal@)); }
   55% { -moz-transform: translateX(@sidebar_width_minimum@); }
   90% { -moz-transform: translateX(@sidebar_width_minimum@); }
   to { -moz-transform: translateX(0); }
 }
 
-/* Tablet mode */
-
-.spacer-actionbar,
-.button-actionbar {
-  visibility: collapse;
-}
-
-.button-actionbar[disabled="true"] {
-  opacity: 0.5;
-}
-
-#toolbar-main[tablet="true"] > .spacer-actionbar,
-#toolbar-main[tablet="true"] > .button-actionbar {
-  visibility: visible;
-}
-
-#controls-scrollbox[tablet="true"] > #controls-sidebar {
-  visibility: collapse;
-}
-
-#controls-scrollbox[tablet="true"] > #tabs-sidebar {
-  border: none;
-  position: fixed;
-  top: @touch_button_xlarge@;
-  visibility: collapse;
-}
-#controls-scrollbox[tablet="true"] > #tabs-sidebar:-moz-locale-dir(ltr) {
-  left: 0;
-}
-#controls-scrollbox[tablet="true"] > #tabs-sidebar:-moz-locale-dir(rtl) {
-  right: 0;
-}
-#controls-scrollbox[tablet="true"] > #tabs-sidebar[open] {
-  visibility: visible;
-}
-
 /* Text selection handles */
 
 #selectionhandle-start,
 #selectionhandle-end {
   min-width: 35px !important;
   width: 35px !important;
   padding: 0 !important;
   margin: 0 !important;
@@ -1809,8 +1775,10 @@ setting {
   }
   
   #search-engines-list > .action-button > .button-box > .button-text {
     text-align: start;
     font-size: @font_tiny@ !important;
   }
 
 }
+
+%include ../tablet.css
index 935b7555e4d8aceb67a15f9eb137b6ddade69522..1f19cd10638b54797e21db629ef041bcedc54f17
GIT binary patch
literal 1202
zc$@*U1Wo&iP)<h;3K|Lk000e1NJLTq001Ze001Zm1^@s6jQ+T70000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU$R7pfZRCwCVm`P|9K@^5-dX~(h&V;BW
z;t~Y)pu~6;k?28i0moYu!5jnyAvx;BC3?}5C<qFI5k$Sk;07Kvh=?bNq8A01-~thy
znIyAszQ3&+I^A8pO$>QZ=_K9n{a?STdev3FdcDr(vngzz+q?%1;Kx><ubCL#)DqNs
zbpIcvmZmo5HSlv9egO}DfJsu@%dav!t@-^PwGn<zyAktYlJqTDYWv`)?5|EPn&gnG
zg_HpEQxAmwp&8E?swGyX*ri%U`|mV|99$h+^2JVbXnMj~1_|yAT?PQA5KPS9!lHqY
zdX-u*+W0kFEwWstglnQ!ulM04Ddr`DJkwMLDF`w(jPVul`B`fyszNCq$1K6Au&Gjx
zRq9p7$LBTzP0KQ<SY!=@|1;oPLov2I(#jSF!k*#Ol0m+Rfmn#iC)j7M<-E*rhi4Qp
z(GgCtR_ZRLxtVSNMNEJ~16ndjMb@n}_!BE5Z7kvs{<j*32?h;lL6d9SX7C0%bS|UJ
z&1TlDvI#9{LfaCM-XKX1$@cJ~If2tca!t(cq*VqlE@@fFFk@x5vTFm|a<JDm1bpBt
zUD8Ms+F&p&bv%20R6;tfY8wPjJRWAzcwGJa#jU%J;SOKD%yO9wJHK-u8-M%G^f_pQ
z0W4H{hV&U6XlsdCifG{==p>T@4hG+|FP~caafX2zU5sUn>QlE>*P6XGgoU`79k_7L
za35KeWl(fASoqS~$Y4)A7_rO*f}(pMAj^;*e#fyR1~{uO7RFh68h}B?zZo^j&Jg(2
z=IsUnJ)~Lpix;$m6ZH{HjkS1JF#Kj|%c3r)GZJG7<552=#iWtJ>9cQT6UE85kIIFO
zD&XEw>;tWhYuuC#8Kl#pVP~mQ_Txw?yH@SufZ~t1t!qxklUFz`Q&W2q2w&cRNO~Xl
zyucY&l1i<b_u`Ch?!R+WdLQ>h-E?b$Nd>I3`g<>Mc4JV#^0+a<qyiSJmC@ON!z|V>
ze_kO4(?7skc|^Clk=o)_E2MDOkM^rg25C3rg@FZ34M6O$rYePTJ4Xm$EtSCuYZekL
zV%OK0#hG&cG~dX$8c%vSE##9c*IbWVFo4DIJ&4bnKc(!1Ro9w9n869Vef*^9eJemP
zh)*p;9h|Ndk6>G9X0Pu*o>6qoy3x$E85YG|<_B#sSni9z=6*lu2*-EJJ|6J)Xih&?
zwI38%S!62@y7qfM{cu&ZZI5<eYyia0Dy#%wwTI*D=4xMp4gJqT`bV)=S+Cv1n{M3k
zK%rLdC5Nfn92{<PxG93$ZFa(7x)#%eW8|=PJpVhBua^HC9O@l3pao4=2bgf6x9g<0
z8%>pSY&NrrScv&8pHeksaJFAFNIA7_^ldiyJ)fGS0@@TPd=Ue&5R+nWk{uj*J|Cos
zvyZlhaogiJUHRb0ZyACdc5^=H7*Kb1(>P&uc!1eBVYSPcDd2oQqy8(v04{5M+MdAo
QYybcN07*qoM6N<$f?N<W0ssI2
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1e616b6698a5fc77fbf709cf62af43e7aeb949df
GIT binary patch
literal 626
zc$@)p0*(ENP)<h;3K|Lk000e1NJLTq0015U001lq1^@s6a)Jm10000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!6iGxuRCwC#mcdKHa1_V2Hj5-78pD={
zu!D4vAS08gLxiB-Iz}L<;3fSB^c>|Su(NjQU+`YtyJ_KZ5D^sw#lq6C_u&0tjNF!k
z?C|@+2Y%bWd*8kHd%tb&e!uS;#TavqXmDe0%#FD*H~#;|f(^|$FiG<c@MWPBNcZ8y
z7_TdUkB(n~7vRmH^8kL*iKM$TGq)<W1jyxbc@Kg491sAe4W{^Te$?c0xgyMGiNOPZ
z1WZ@}wnL$i77PaaiA3TOj-$X5FbzzQX01>tR8fP#*a3oOv8^)3wR(-m<25{Jx7%CE
zWU@jf4G?m%Sln+k8U@s(QmIoab;n7@BFm^$Djoiic{H2Np0P|ZYt+&`9<$hP8~<Fa
zapZcvzFw(Rj=SCN6g<Qgs{+fkTCJYL^bxoRKAmLD5C8>Ot<`D=Ec0P9wY$b_^k@rd
znM~$dQIuPD!Rz%t=kxgs+B)x+nf~(4B~c^!pt+7zRgH+E_>O3rCZ*HqlUA#>NZU=e
z712gnWMCQC#HPa1VyUs@NH`pR!gG;GL~S;kyQGz^;#!%`0AUP>f%T@i-oT3fn!#Lh
zVmt?I#A30VA50Zi4Wl_$2M9PZ#+x@W7-BFL^h?3a@!{}oM;$)&KE|e+H+&?XXs`Bk
zI++^F_>p)R6xhxSL^6C9pDlEPPS<l{%zu5jF*oMM+?X5x?f4d804qkI*d{1O6951J
M07*qoM6N<$f_zRRW&i*H
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..478e9c85e270e51428f181c423d04d5aa448eadb
GIT binary patch
literal 1572
zc$@(w2HW|GP)<h;3K|Lk000e1NJLTq001cf004Ce1^@s6(=5n(0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU%#z{m$RCwC#oJ&ljRTRhjwWSZ~3{wh%
z2xYVsoz~8Dzz$HW22;mOjERYf0|~e@aUmv#4GR;L$4UY$hBX)sgoH3ApbH{sT(AHm
z8Uh3Y0enDG1r$mV`ncW$_mT@~g)+1~Cf`X;zJZkFm;XKY-1FTzrxGDVAxV<rEQ8M_
z(<A{(tw3lD5H}<P<W8_cf+?9t)JT^a;8g5Mlt`Ca#eHUG#;QgPsevEz^7335AptOr
zK}K{s-AihO@yJ!wQWc3-t9?_AP(=XLQ`hzP_m@*{qZ*NlN|v_)@G)3&r_=c^nq)34
zvyOT?Kn@HHyl5~OJaL`L@VP{|u$v9k^Qk)>4u>}o2>eQzr4&*C1ofVvZl~^9Sy}m(
z2$nKPcABIy1p)8|b@%l2^dLE9Nrx2FgZR6~me^iaR(5xFb@h7^#gYcelv6XftJEK-
z{xrm3TU*<EySuyVB!(pnk}1Z)v@GsGxg6@(LA}=2)*2dr-;guxQXmB&exzwxuDe3r
z$W()6E%JK3<wHY54L+Z5lAP1jkC@v|R4hz24hsKHD=I2VZ)|KVwb^XWf`WpItgNg%
zEODRP)E5Nf%a|q<1BcJ%=4Ok><0&aDEWDkao$aIvx%g3&y*ds)=~RWH<KErfUG8?f
zUoo4_cWKp<bLmIYIbu>0&Qyr6JnB}v-R>G6AODn|3~MC8b{3?PsdkkmTq}($*Tlrc
zgM)*EZIUGWFGwX@&P?is)E!MtP4D>q{$EIvEfypPG_izRLaUNb!r^d`q`;y<Dp{Tb
z1ufK{@9XRPI1-73Ns8<=q{MbFoD5G<FYW2+`6yKi#)9N!)05P1(R}wtGB?P1ASJfU
z+0>t<{=&k-!U#cN$|&gu&Rj!FOG~NMYJC;UeT!J*@xnk~TU&b{)1{DjssN<EqN2h?
zlXf{~NKIW`UEGyQG9bmOMorIU8@4+@F(v_0m6MZm9V;ZStW~rI%*6`HK_#tLYrqJ3
z;+|TiQt7cma!>`PogGa{@rhPRwEqnuL&}gcqzoxT%8)Xo3@Jm(kTRqUDMQMTGNcSC
zL&}gcqzoxT%8)65B$y$||3ygvC81F0AIwTd;292w_b@_oz(dHry}d1rkN_8^9)joA
z*4A%Wl?2EG09{^Qp2w<Wh(QL2hlhW_1SzpWHr^AIp*ZTf&D`19`P^VI<YQZIP;#Go
z0G^YRlV78eQs}S(VCV^gCeB+no9$j85cm^YhZWEUnUXuRv$Go`BO~3|l;mnc-z2nL
zL%*7v?)2|4Dam&^sJTo1Z*Z^I+qAj4Igd%n!yT_UYGg97__SA6R=(!*`F_UIKN$@a
zdW4=SE-v=W&(D8}2~q@w9S=Q~(3yI(x3{-G8ExC~v~Y`KDUj%)joV^2n@h*W##;S;
z|1t(hao6*P_-iZ#Kv~=1;NS=A>+7SzV9=i^NGYEAZr0Sqfi;3_Ef!09XJ_Zj^bjb|
z%*=FTWMnuls|hMD$m2gcIg~3-jU2Z(noK5rM@L7A-EMd0=H}is8jW_nUY~ziDJbUW
z&KRfSb2xgI6(B6KSZJ837uVO<-<z76da$vvF_nmzyy!#|pEdz#Bdf4rMBzq5L&IB3
zOH0G&>0wX!jMyn?0KUQ$26b&UH8rm<E-rqRQpgygp<(JmjR2zyC0$)zAMWq(|CMsc
z7-NA(76Q)d>gu;??)@DF<f$=14Lc|R^mbKM)qVQ5`Ue_FK~)V?6vk>??d|RFM<S5}
zG?0R#;@riZxw*L>RFDEFOt3)0f6nD{xkI6lFIv%?($bc_Qp4*@fW8QBt*xznhU$Kj
z9LdQqDBvz?pVk6j!0#?}b|>r-;0Q#+mK~1Q5Us8rqWWTl!?H}0xSC3KdG-+F_h5)u
zKGOE~_Kz4Ld2GU4t8#R7^e0p?Da0nPQ(?)&Sig$r_|{p0`1^u5B>FEk;_*fP6<`2{
WE)xgo3A0520000<MNUMnLSTY9jN{n=
index 3961ad1baaa1e26175cdf58f16e54b1801996206..7e4b9f7d8d82e74551c48a938a16606d2d041901
GIT binary patch
literal 1087
zc$@)01i<@=P)<h;3K|Lk000e1NJLTq001Ze001Zm1^@s6jQ+T70000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU#;Ymb6RCwCFnN3JlK@`X5`IJCJ-zFE8
z@S--A;0s!0P+058C$$J#WUFYCxM~rh5iMGYZK9R72wD_sMJ)<5f)o;bg4xDUup)Hx
zeE9jkZu7sMvGIP)ojdP64-BKuJ?H%HoVjOajuFeU*xSaVtOQB$7UQkW@%J&_(!8Zi
z4PRWEW7P(FfJyS!PQ9P>NIwtrHbQ+mjI*i`&&GKh;BB7zWC-1)LpNS-z+T>_c<ZDY
zG?f_Hm?E1c1H#}Z3Rfv$UUqv3G-e8zppdk&%8Bri2n(2?nTxT?i-=M}7Z3_VdjuEg
z(+e=vS5`(5Swabz3`!sM&Bs{N)ytv1LkGGV>1daKXQJ*4f@>Xm&T1O!?cWz)ywZki
zdHjgwRx)h7;~LA%{7^mKM+x0EgPp3-!ifwAhdMJU;2_XFH~J<>FHS5jz%G^6%FL|m
zZ*VM}d&!9hcU|L{MK4<p>2d<bRk;X)upm5e;5S1~_`^4ExZpHGEYe(D2GmN%F#P4h
zC6@yyq*wUG3u?eInMr&kExKCki@$6~Sda2oDFgYzIcGmWY^Dg#gCmVc#-l89I*c|J
zyc06a(g>0QvnJY?ezw{n&RSOJT|;L*nZn6THelXjbtb7Fjwi3*@*T&R37pKd4ah7b
zK!o|!vnRge7!!FjG$1imF+<T=gU+4DL~OuJvA9|eIBb2+?avfaFxh}B#ez0qZPOuN
zxar$>?B)llaaj1ja}kpb__vtXx@p0|+0oa&a6-xfDVRivC(^}2Ae>jIoNzMa{L=xW
z+zA#i$sft|Ts|8ZS}zDMI3eHfJ@g!JXg;p=MJ&@Y;MhVw$JVT(|CGP~uq)|$h0#mo
z85YT1r3VJEP-S9!t3&DI<$7l7K(sn>W?yY!s4)Y&hgErh#xX1Cu<&(jo&71~Q&(#1
zPdZB<{d{16H^xDg+gFGa$*!3U68J^~i|fG3i3fSN@GZN+f<Bl^2to_rU?3LHOH+4_
zhkP=-$<XhWz}NWJhVa?#d#mH*xU39g20!z)uosZ<0bdlgVPa6;i*Zg*LE+uzDqG%O
z6BQBRgWwj(xBBAF-yls7rp4RM=C;Z@o3I6&A2-*8UHI%E-@&yR{vfKN=S8tm7(;$4
z1r)ll0b8&sCKA5Lr%NKL5-`t=qGqylsj7)Y*g>9#4n%8|>ByZva_l$n9WR(7IM1^H
z@?b=#M$JKc>8|R!8pNuiHuQep%d*VZ6<~Z)7J&LWn6iku1K3&Ds9W6Wq1uUQ<tt5P
zjr;UbC}nVUDHNbwD$^;V%VJbSHwE;n0#xMR5CHrqzyS6nJ3M6*QC$E4002ovPDHLk
FV1hM@1Hb?P
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1e616b6698a5fc77fbf709cf62af43e7aeb949df
GIT binary patch
literal 626
zc$@)p0*(ENP)<h;3K|Lk000e1NJLTq0015U001lq1^@s6a)Jm10000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!6iGxuRCwC#mcdKHa1_V2Hj5-78pD={
zu!D4vAS08gLxiB-Iz}L<;3fSB^c>|Su(NjQU+`YtyJ_KZ5D^sw#lq6C_u&0tjNF!k
z?C|@+2Y%bWd*8kHd%tb&e!uS;#TavqXmDe0%#FD*H~#;|f(^|$FiG<c@MWPBNcZ8y
z7_TdUkB(n~7vRmH^8kL*iKM$TGq)<W1jyxbc@Kg491sAe4W{^Te$?c0xgyMGiNOPZ
z1WZ@}wnL$i77PaaiA3TOj-$X5FbzzQX01>tR8fP#*a3oOv8^)3wR(-m<25{Jx7%CE
zWU@jf4G?m%Sln+k8U@s(QmIoab;n7@BFm^$Djoiic{H2Np0P|ZYt+&`9<$hP8~<Fa
zapZcvzFw(Rj=SCN6g<Qgs{+fkTCJYL^bxoRKAmLD5C8>Ot<`D=Ec0P9wY$b_^k@rd
znM~$dQIuPD!Rz%t=kxgs+B)x+nf~(4B~c^!pt+7zRgH+E_>O3rCZ*HqlUA#>NZU=e
z712gnWMCQC#HPa1VyUs@NH`pR!gG;GL~S;kyQGz^;#!%`0AUP>f%T@i-oT3fn!#Lh
zVmt?I#A30VA50Zi4Wl_$2M9PZ#+x@W7-BFL^h?3a@!{}oM;$)&KE|e+H+&?XXs`Bk
zI++^F_>p)R6xhxSL^6C9pDlEPPS<l{%zu5jF*oMM+?X5x?f4d804qkI*d{1O6951J
M07*qoM6N<$f_zRRW&i*H
index 105d7852eddc5783d5936d836efcc94d08a38450..77d71107fa1bc1016d6119bcbea054e9765fd36b
GIT binary patch
literal 1150
zc$@)#1cCdBP)<h;3K|Lk000e1NJLTq001Ze001Zm1^@s6jQ+T70000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU$AW1|)RCwCFnN4UDK@`VllQd1*DygCs
zFQ$6*U@Crs2a5+Uq7gq%wp2wyFQw>BF|FuLDZS`H)S{k5F^U%tejEhr2c`uJo-~SR
zt6-yTt=2a2{ns~PlkCUrCh3D=m)&{q{dQjF&6|mq%jLvrO%r8Ej9P@+=A!3MsAZ@P
zdNq8C*a9B(028OSgRfSSFx)4p-Q{b>jWeH%zENsdslDfG+=XtuNH<z(z;0?OY8^a+
zUM0ddQf#wqKp1??;VK8r%x;1~BVGYx9FonVdLn(q+ycgU<RYT_BBK;j1%$$#If8Ta
zX$I(OmQ_$>maqkkJEe~$%T|imu6^!*Y@`ESg>+Qlzc^9%I>EKSekwu>C=$DAiMV}3
z8E*Tn>*DwKjJURXlNk9hY}dV)6MD%AcG!g$PV#UhaHukp5)K00!|69pdQoO60qnHX
z8hMo}c?QSZFI=|N*?Q(&9!?5I(actnbQS|f?Q)S0NMS*E;GkfHjvO$B#IyA$j+MYE
zgjlAzs1Z;p8N=|U=t?pAGGz;idpt7=bQIx)kx5RHRjOKJ<DbQ~b(=){i>IP#ZA$^9
z*?k_4bf&~FHxplH(ohffXufBf$Zc?=9Ts&ZkY?f$PUM6(kjP~>>LH%hG}o&J9KvyN
zxGMo?WYPh1n%3YY^~3SaE!!;L<DC~cBa;r872W_5=DiQ^TfWCT^zkB+$tOID%5M<w
z(8nue9&p+hn5YEY;KeI?s|2KE3b+MqoVQdDof+J{qX$h>jfA|rr%gEzN+x{-fBAz-
zJ1rCohtk82aJV-eNm|PlDjH#A(gFYa`~yVn2xlx7tl*50&(EGOcm`b+NU(s(I7x<n
z)P(Iz-WAQI5WCw<;iNn`d0g*P^08~|lRL8v83CV+2SQ>-^IIyteRRK|Sb$@ddJugi
zq%0Qf^uPcXKAHHx)ZyskUHzg|{p_Du)9;^-p~eWP7OTd(5M`FrBpD6O7nA<l!R3?R
zT8fW8`sl?~YJxy*D;gISNx?`u34Ei0rKDgb;(ofMztzqYP7|gYg3!V@7?{O$)6|uv
zaDSza+44@j+%0S5YlK3}KD#V;bwrNMN)jXZITV=_Ncey+j#`o#Z1=_c@sokV$M8Zi
z<*%t4ob<tPY4&Zuai=fHaK{Y3?hAe0SWR6;M-#SS^HaD{+J(=Z?A!TlhC1R@v{fE9
zjs@#=W5`eCfI=5GU<)=`;G>m&s-JGLLbFVma+V<^xN<sB67)6d8WsfIhZUUJ$%0w9
zTPcZm^IkO~M}f1w2xe!5pAu?lcDitj=?|i8w@O*C+eh{t4>9$Xq@!W6>fug;&rZCa
zd}a7pqlYJjt@KZPbyZQzS=P+gqzm0-k#1U5G2n3&`nkzdfU5ir0r@Au0H<ui;K+$Q
QAOHXW07*qoM6N<$f&xb#MF0Q*
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fd8e46b0c15e533f5c6360a659fbddc5a386b7fa
GIT binary patch
literal 546
zc$@(u0^R+IP)<h;3K|Lk000e1NJLTq0015U001lq1^@s6a)Jm10000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz#7RU!RCwC#mN84iKp2Kwn^sX2gb-}(
zAUZjSprV54ApQX9>`$nJlm9@}MW}<5xcCSB2kPYFYA1(^sI&#a(pn`F-@`X}grvDP
zU>)w@fnM*;_ws%B-6cuabrZc9eTg0oZLE#8u{PGm|KHe9)TO`xf49I_gwCMuBaX4q
z*kFY7H}DGTK3xWkQJ1FfG0a@W*aQ~HbAADa7_=^#+SF}=EI0x0;3+Vw_z;L-0<43E
z`!lY<5|{?Vpr4vWP;`IC2AB+stI}L8mhF`DHE_t1=7`923v5$!%x7AmQ57;yOBwA2
zWG*<9GA&Xop2>v8O)7qKd5t47TLuSU5L`=D@G?CI74Ge4oQypTV1orvkTUNm(@yr-
z8xFg;0d7G_TC0Ie9-U^}OuM+bOg55es(mm|lP1@Wz!Z;?6&X#j%odmht86Nlr7n;v
z|0{z$wN|^BDyE}gh5^eyQ?cK3zBSq0jANVyE8s4`)RwB@Hy72(#c8e-dqG^24`3JE
z@VHdSGq?vk)R?@lL$73&b1Z_4`(6@N8ak5BVq^JV5-;5vd*<?Mu@<2-B%Kq-SbzFx
kV{NRBwXrt-yYVf+01?=dN6%R1uK)l507*qoM6N<$f(;q;0ssI2
index aacf3b927b0da779ef18c830863e3109604c3b9f..e71e89cd79b51c9a0ba31ecafd73760dff9adc8f
GIT binary patch
literal 208
zc%17D@N?(olHy`uVBq!ia0vp^8X(NU1|)m_?Z^dEk|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*D5XiacE$Ln>~)x#q}qK!L|4FxX~w`=?Eh_ccvOO3kRh<|wCT
z*tX=6Ot>L`b%O7+{WtkPc1q`T-|^#TGMVv6U0BnLr{Jpg$@5J{(Fw;Tzh00!eduxd
z`JRe2hFNQ^0+SjT7@1f&1QZVZF4x}S*ud~yf{BOW?mvN0wrr-$K-(ESUHx3vIVCg!
E0J9BAjsO4v
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1d9d1ae2308f8adcb70fddb823b04e25b12d456a
GIT binary patch
literal 263
zc%17D@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%k|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*A(MJzX3_DsH_AG3076;8`Pd<mAbVC-;B3`tRt)lP6d1xDwIi
zvGPmHB~5mB&)Z)(GS_{)CoLdbobpY``q?>~i77@Fc@sM=J!($unkx3nHD%(BeXC9{
zGM&1>Nh>72LrD0)c=0nE3l3GaeM?R}R+uuQLgdBY2MVFpPnOvH-YoRx-`{P@8>^V>
z+IFaGPxxHZCcNd>`eW-~@n|i1$E#d6!TDPk_fft_an+GAOgs#;BNY2GFZ%8RI-0@L
L)z4*}Q$iB}x3+FW
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1e616b6698a5fc77fbf709cf62af43e7aeb949df
GIT binary patch
literal 626
zc$@)p0*(ENP)<h;3K|Lk000e1NJLTq0015U001lq1^@s6a)Jm10000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!6iGxuRCwC#mcdKHa1_V2Hj5-78pD={
zu!D4vAS08gLxiB-Iz}L<;3fSB^c>|Su(NjQU+`YtyJ_KZ5D^sw#lq6C_u&0tjNF!k
z?C|@+2Y%bWd*8kHd%tb&e!uS;#TavqXmDe0%#FD*H~#;|f(^|$FiG<c@MWPBNcZ8y
z7_TdUkB(n~7vRmH^8kL*iKM$TGq)<W1jyxbc@Kg491sAe4W{^Te$?c0xgyMGiNOPZ
z1WZ@}wnL$i77PaaiA3TOj-$X5FbzzQX01>tR8fP#*a3oOv8^)3wR(-m<25{Jx7%CE
zWU@jf4G?m%Sln+k8U@s(QmIoab;n7@BFm^$Djoiic{H2Np0P|ZYt+&`9<$hP8~<Fa
zapZcvzFw(Rj=SCN6g<Qgs{+fkTCJYL^bxoRKAmLD5C8>Ot<`D=Ec0P9wY$b_^k@rd
znM~$dQIuPD!Rz%t=kxgs+B)x+nf~(4B~c^!pt+7zRgH+E_>O3rCZ*HqlUA#>NZU=e
z712gnWMCQC#HPa1VyUs@NH`pR!gG;GL~S;kyQGz^;#!%`0AUP>f%T@i-oT3fn!#Lh
zVmt?I#A30VA50Zi4Wl_$2M9PZ#+x@W7-BFL^h?3a@!{}oM;$)&KE|e+H+&?XXs`Bk
zI++^F_>p)R6xhxSL^6C9pDlEPPS<l{%zu5jF*oMM+?X5x?f4d804qkI*d{1O6951J
M07*qoM6N<$f_zRRW&i*H
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..478e9c85e270e51428f181c423d04d5aa448eadb
GIT binary patch
literal 1572
zc$@(w2HW|GP)<h;3K|Lk000e1NJLTq001cf004Ce1^@s6(=5n(0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU%#z{m$RCwC#oJ&ljRTRhjwWSZ~3{wh%
z2xYVsoz~8Dzz$HW22;mOjERYf0|~e@aUmv#4GR;L$4UY$hBX)sgoH3ApbH{sT(AHm
z8Uh3Y0enDG1r$mV`ncW$_mT@~g)+1~Cf`X;zJZkFm;XKY-1FTzrxGDVAxV<rEQ8M_
z(<A{(tw3lD5H}<P<W8_cf+?9t)JT^a;8g5Mlt`Ca#eHUG#;QgPsevEz^7335AptOr
zK}K{s-AihO@yJ!wQWc3-t9?_AP(=XLQ`hzP_m@*{qZ*NlN|v_)@G)3&r_=c^nq)34
zvyOT?Kn@HHyl5~OJaL`L@VP{|u$v9k^Qk)>4u>}o2>eQzr4&*C1ofVvZl~^9Sy}m(
z2$nKPcABIy1p)8|b@%l2^dLE9Nrx2FgZR6~me^iaR(5xFb@h7^#gYcelv6XftJEK-
z{xrm3TU*<EySuyVB!(pnk}1Z)v@GsGxg6@(LA}=2)*2dr-;guxQXmB&exzwxuDe3r
z$W()6E%JK3<wHY54L+Z5lAP1jkC@v|R4hz24hsKHD=I2VZ)|KVwb^XWf`WpItgNg%
zEODRP)E5Nf%a|q<1BcJ%=4Ok><0&aDEWDkao$aIvx%g3&y*ds)=~RWH<KErfUG8?f
zUoo4_cWKp<bLmIYIbu>0&Qyr6JnB}v-R>G6AODn|3~MC8b{3?PsdkkmTq}($*Tlrc
zgM)*EZIUGWFGwX@&P?is)E!MtP4D>q{$EIvEfypPG_izRLaUNb!r^d`q`;y<Dp{Tb
z1ufK{@9XRPI1-73Ns8<=q{MbFoD5G<FYW2+`6yKi#)9N!)05P1(R}wtGB?P1ASJfU
z+0>t<{=&k-!U#cN$|&gu&Rj!FOG~NMYJC;UeT!J*@xnk~TU&b{)1{DjssN<EqN2h?
zlXf{~NKIW`UEGyQG9bmOMorIU8@4+@F(v_0m6MZm9V;ZStW~rI%*6`HK_#tLYrqJ3
z;+|TiQt7cma!>`PogGa{@rhPRwEqnuL&}gcqzoxT%8)Xo3@Jm(kTRqUDMQMTGNcSC
zL&}gcqzoxT%8)65B$y$||3ygvC81F0AIwTd;292w_b@_oz(dHry}d1rkN_8^9)joA
z*4A%Wl?2EG09{^Qp2w<Wh(QL2hlhW_1SzpWHr^AIp*ZTf&D`19`P^VI<YQZIP;#Go
z0G^YRlV78eQs}S(VCV^gCeB+no9$j85cm^YhZWEUnUXuRv$Go`BO~3|l;mnc-z2nL
zL%*7v?)2|4Dam&^sJTo1Z*Z^I+qAj4Igd%n!yT_UYGg97__SA6R=(!*`F_UIKN$@a
zdW4=SE-v=W&(D8}2~q@w9S=Q~(3yI(x3{-G8ExC~v~Y`KDUj%)joV^2n@h*W##;S;
z|1t(hao6*P_-iZ#Kv~=1;NS=A>+7SzV9=i^NGYEAZr0Sqfi;3_Ef!09XJ_Zj^bjb|
z%*=FTWMnuls|hMD$m2gcIg~3-jU2Z(noK5rM@L7A-EMd0=H}is8jW_nUY~ziDJbUW
z&KRfSb2xgI6(B6KSZJ837uVO<-<z76da$vvF_nmzyy!#|pEdz#Bdf4rMBzq5L&IB3
zOH0G&>0wX!jMyn?0KUQ$26b&UH8rm<E-rqRQpgygp<(JmjR2zyC0$)zAMWq(|CMsc
z7-NA(76Q)d>gu;??)@DF<f$=14Lc|R^mbKM)qVQ5`Ue_FK~)V?6vk>??d|RFM<S5}
zG?0R#;@riZxw*L>RFDEFOt3)0f6nD{xkI6lFIv%?($bc_Qp4*@fW8QBt*xznhU$Kj
z9LdQqDBvz?pVk6j!0#?}b|>r-;0Q#+mK~1Q5Us8rqWWTl!?H}0xSC3KdG-+F_h5)u
zKGOE~_Kz4Ld2GU4t8#R7^e0p?Da0nPQ(?)&Sig$r_|{p0`1^u5B>FEk;_*fP6<`2{
WE)xgo3A0520000<MNUMnLSTY9jN{n=
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1e616b6698a5fc77fbf709cf62af43e7aeb949df
GIT binary patch
literal 626
zc$@)p0*(ENP)<h;3K|Lk000e1NJLTq0015U001lq1^@s6a)Jm10000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!6iGxuRCwC#mcdKHa1_V2Hj5-78pD={
zu!D4vAS08gLxiB-Iz}L<;3fSB^c>|Su(NjQU+`YtyJ_KZ5D^sw#lq6C_u&0tjNF!k
z?C|@+2Y%bWd*8kHd%tb&e!uS;#TavqXmDe0%#FD*H~#;|f(^|$FiG<c@MWPBNcZ8y
z7_TdUkB(n~7vRmH^8kL*iKM$TGq)<W1jyxbc@Kg491sAe4W{^Te$?c0xgyMGiNOPZ
z1WZ@}wnL$i77PaaiA3TOj-$X5FbzzQX01>tR8fP#*a3oOv8^)3wR(-m<25{Jx7%CE
zWU@jf4G?m%Sln+k8U@s(QmIoab;n7@BFm^$Djoiic{H2Np0P|ZYt+&`9<$hP8~<Fa
zapZcvzFw(Rj=SCN6g<Qgs{+fkTCJYL^bxoRKAmLD5C8>Ot<`D=Ec0P9wY$b_^k@rd
znM~$dQIuPD!Rz%t=kxgs+B)x+nf~(4B~c^!pt+7zRgH+E_>O3rCZ*HqlUA#>NZU=e
z712gnWMCQC#HPa1VyUs@NH`pR!gG;GL~S;kyQGz^;#!%`0AUP>f%T@i-oT3fn!#Lh
zVmt?I#A30VA50Zi4Wl_$2M9PZ#+x@W7-BFL^h?3a@!{}oM;$)&KE|e+H+&?XXs`Bk
zI++^F_>p)R6xhxSL^6C9pDlEPPS<l{%zu5jF*oMM+?X5x?f4d804qkI*d{1O6951J
M07*qoM6N<$f_zRRW&i*H
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fd8e46b0c15e533f5c6360a659fbddc5a386b7fa
GIT binary patch
literal 546
zc$@(u0^R+IP)<h;3K|Lk000e1NJLTq0015U001lq1^@s6a)Jm10000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz#7RU!RCwC#mN84iKp2Kwn^sX2gb-}(
zAUZjSprV54ApQX9>`$nJlm9@}MW}<5xcCSB2kPYFYA1(^sI&#a(pn`F-@`X}grvDP
zU>)w@fnM*;_ws%B-6cuabrZc9eTg0oZLE#8u{PGm|KHe9)TO`xf49I_gwCMuBaX4q
z*kFY7H}DGTK3xWkQJ1FfG0a@W*aQ~HbAADa7_=^#+SF}=EI0x0;3+Vw_z;L-0<43E
z`!lY<5|{?Vpr4vWP;`IC2AB+stI}L8mhF`DHE_t1=7`923v5$!%x7AmQ57;yOBwA2
zWG*<9GA&Xop2>v8O)7qKd5t47TLuSU5L`=D@G?CI74Ge4oQypTV1orvkTUNm(@yr-
z8xFg;0d7G_TC0Ie9-U^}OuM+bOg55es(mm|lP1@Wz!Z;?6&X#j%odmht86Nlr7n;v
z|0{z$wN|^BDyE}gh5^eyQ?cK3zBSq0jANVyE8s4`)RwB@Hy72(#c8e-dqG^24`3JE
z@VHdSGq?vk)R?@lL$73&b1Z_4`(6@N8ak5BVq^JV5-;5vd*<?Mu@<2-B%Kq-SbzFx
kV{NRBwXrt-yYVf+01?=dN6%R1uK)l507*qoM6N<$f(;q;0ssI2
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1d9d1ae2308f8adcb70fddb823b04e25b12d456a
GIT binary patch
literal 263
zc%17D@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%k|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*A(MJzX3_DsH_AG3076;8`Pd<mAbVC-;B3`tRt)lP6d1xDwIi
zvGPmHB~5mB&)Z)(GS_{)CoLdbobpY``q?>~i77@Fc@sM=J!($unkx3nHD%(BeXC9{
zGM&1>Nh>72LrD0)c=0nE3l3GaeM?R}R+uuQLgdBY2MVFpPnOvH-YoRx-`{P@8>^V>
z+IFaGPxxHZCcNd>`eW-~@n|i1$E#d6!TDPk_fft_an+GAOgs#;BNY2GFZ%8RI-0@L
L)z4*}Q$iB}x3+FW
--- a/mobile/themes/core/jar.mn
+++ b/mobile/themes/core/jar.mn
@@ -85,16 +85,17 @@ chrome.jar:
   skin/images/panelrow-selected-hdpi.png    (images/panelrow-selected-hdpi.png)
   skin/images/forward-default-hdpi.png        (images/forward-default-hdpi.png)
   skin/images/downloads-default-hdpi.png      (images/downloads-default-hdpi.png)
   skin/images/settings-default-hdpi.png       (images/settings-default-hdpi.png)
   skin/images/preferences-default-hdpi.png    (images/preferences-default-hdpi.png)
   skin/images/row-header-bg.png             (images/row-header-bg.png)
   skin/images/console-default-hdpi.png        (images/console-default-hdpi.png)
   skin/images/newtab-default-hdpi.png         (images/newtab-default-hdpi.png)
+  skin/images/newtab-default-tablet-hdpi.png (images/newtab-default-tablet-hdpi.png)
   skin/images/tab-active-hdpi.png           (images/tab-active-hdpi.png)
   skin/images/tab-inactive-hdpi.png         (images/tab-inactive-hdpi.png)
   skin/images/tab-closed-hdpi.png           (images/tab-closed-hdpi.png)
   skin/images/tab-reopen-hdpi.png           (images/tab-reopen-hdpi.png)
   skin/images/remotetabs-48.png             (images/remotetabs-48.png)
   skin/images/remotetabs-32.png             (images/remotetabs-32.png)
   skin/images/mozilla-32.png                (images/mozilla-32.png)
   skin/images/toggle-on.png                 (images/toggle-on.png)
@@ -105,18 +106,22 @@ chrome.jar:
   skin/images/next-hdpi.png                 (images/next-hdpi.png)
   skin/images/next-disabled-hdpi.png        (images/next-disabled-hdpi.png)
   skin/images/identity-default-hdpi.png     (images/identity-default-hdpi.png)
   skin/images/identity-ssl-hdpi.png         (images/identity-ssl-hdpi.png)
   skin/images/identity-ev-hdpi.png          (images/identity-ev-hdpi.png)
   skin/images/unlocked-hdpi.png             (images/unlocked-hdpi.png)
   skin/images/locked-hdpi.png               (images/locked-hdpi.png)
   skin/images/close-default-hdpi.png        (images/close-default-hdpi.png)
+  skin/images/close-default-tablet-hdpi.png (images/close-default-tablet-hdpi.png)
   skin/images/close-active-hdpi.png         (images/close-active-hdpi.png)
+  skin/images/close-active-tablet-hdpi.png  (images/close-active-tablet-hdpi.png)
   skin/images/close-inactive-tab-hdpi.png   (images/close-inactive-tab-hdpi.png)
+  skin/images/close-inactive-tab-tablet-hdpi.png   (images/close-inactive-tab-tablet-hdpi.png)
+  skin/images/close-background-hdpi.png     (images/close-background-hdpi.png)
   skin/images/check-30.png                  (images/check-30.png)
   skin/images/search-glass-30.png           (images/search-glass-30.png)
   skin/images/search-clear-30.png           (images/search-clear-30.png)
   skin/images/section-expanded-16.png       (images/section-expanded-16.png)
   skin/images/section-collapsed-16.png      (images/section-collapsed-16.png)
   skin/images/task-switch-hdpi.png          (images/task-switch-hdpi.png)
   skin/images/task-close-hdpi.png           (images/task-close-hdpi.png)
   skin/images/task-back-hdpi.png            (images/task-back-hdpi.png)
@@ -209,16 +214,17 @@ chrome.jar:
   skin/gingerbread/images/bookmark-starred-hdpi.png     (gingerbread/images/bookmark-starred-hdpi.png)
   skin/gingerbread/images/forward-default-hdpi.png        (gingerbread/images/forward-default-hdpi.png)
   skin/gingerbread/images/downloads-default-hdpi.png      (gingerbread/images/downloads-default-hdpi.png)
   skin/gingerbread/images/settings-default-hdpi.png       (gingerbread/images/settings-default-hdpi.png)
   skin/gingerbread/images/preferences-default-hdpi.png    (gingerbread/images/preferences-default-hdpi.png)
   skin/gingerbread/images/row-header-bg.png             (gingerbread/images/row-header-bg.png)
   skin/gingerbread/images/console-default-hdpi.png        (gingerbread/images/console-default-hdpi.png)
   skin/gingerbread/images/newtab-default-hdpi.png         (gingerbread/images/newtab-default-hdpi.png)
+  skin/gingerbread/images/newtab-default-tablet-hdpi.png (gingerbread/images/newtab-default-tablet-hdpi.png)
   skin/gingerbread/images/tab-active-hdpi.png           (gingerbread/images/tab-active-hdpi.png)
   skin/gingerbread/images/tab-inactive-hdpi.png         (gingerbread/images/tab-inactive-hdpi.png)
   skin/gingerbread/images/tab-closed-hdpi.png           (gingerbread/images/tab-closed-hdpi.png)
   skin/gingerbread/images/tab-reopen-hdpi.png           (gingerbread/images/tab-reopen-hdpi.png)
   skin/gingerbread/images/remotetabs-48.png             (gingerbread/images/remotetabs-48.png)
   skin/gingerbread/images/remotetabs-32.png             (gingerbread/images/remotetabs-32.png)
   skin/gingerbread/images/mozilla-32.png                (images/mozilla-32.png)
   skin/gingerbread/images/toggle-on.png                 (gingerbread/images/toggle-on.png)
@@ -228,18 +234,22 @@ chrome.jar:
   skin/gingerbread/images/next-hdpi.png                 (gingerbread/images/next-hdpi.png)
   skin/gingerbread/images/next-disabled-hdpi.png        (gingerbread/images/next-disabled-hdpi.png)
   skin/gingerbread/images/identity-default-hdpi.png     (gingerbread/images/identity-default-hdpi.png)
   skin/gingerbread/images/identity-ssl-hdpi.png         (gingerbread/images/identity-ssl-hdpi.png)
   skin/gingerbread/images/identity-ev-hdpi.png          (gingerbread/images/identity-ev-hdpi.png)
   skin/gingerbread/images/unlocked-hdpi.png             (gingerbread/images/unlocked-hdpi.png)
   skin/gingerbread/images/locked-hdpi.png               (gingerbread/images/locked-hdpi.png)
   skin/gingerbread/images/close-default-hdpi.png        (gingerbread/images/close-default-hdpi.png)
+  skin/gingerbread/images/close-default-tablet-hdpi.png (gingerbread/images/close-default-tablet-hdpi.png)
   skin/gingerbread/images/close-active-hdpi.png         (gingerbread/images/close-active-hdpi.png)
+  skin/gingerbread/images/close-active-tablet-hdpi.png  (gingerbread/images/close-active-tablet-hdpi.png)
+  skin/gingerbread/images/close-background-hdpi.png     (gingerbread/images/close-background-hdpi.png)
   skin/gingerbread/images/close-inactive-tab-hdpi.png   (gingerbread/images/close-inactive-tab-hdpi.png)
+  skin/gingerbread/images/close-inactive-tab-tablet-hdpi.png   (gingerbread/images/close-inactive-tab-tablet-hdpi.png)
   skin/gingerbread/images/check-30.png                  (gingerbread/images/check-30.png)
   skin/gingerbread/images/search-glass-30.png           (gingerbread/images/search-glass-30.png)
   skin/gingerbread/images/search-clear-30.png           (gingerbread/images/search-clear-30.png)
   skin/gingerbread/images/section-expanded-16.png       (images/section-expanded-16.png)
   skin/gingerbread/images/section-collapsed-16.png      (images/section-collapsed-16.png)
   skin/gingerbread/images/task-switch-hdpi.png          (gingerbread/images/task-switch-hdpi.png)
   skin/gingerbread/images/task-close-hdpi.png           (gingerbread/images/task-close-hdpi.png)
   skin/gingerbread/images/task-back-hdpi.png            (gingerbread/images/task-back-hdpi.png)
@@ -334,16 +344,17 @@ chrome.jar:
   skin/honeycomb/images/panelrow-selected-hdpi.png    (honeycomb/images/panelrow-selected-hdpi.png)
   skin/honeycomb/images/forward-default-hdpi.png        (honeycomb/images/forward-default-hdpi.png)
   skin/honeycomb/images/downloads-default-hdpi.png      (honeycomb/images/downloads-default-hdpi.png)
   skin/honeycomb/images/settings-default-hdpi.png       (honeycomb/images/settings-default-hdpi.png)
   skin/honeycomb/images/preferences-default-hdpi.png    (honeycomb/images/preferences-default-hdpi.png)
   skin/honeycomb/images/row-header-bg.png             (honeycomb/images/row-header-bg.png)
   skin/honeycomb/images/console-default-hdpi.png        (honeycomb/images/console-default-hdpi.png)
   skin/honeycomb/images/newtab-default-hdpi.png         (honeycomb/images/newtab-default-hdpi.png)
+  skin/honeycomb/images/newtab-default-tablet-hdpi.png (honeycomb/images/newtab-default-tablet-hdpi.png)
   skin/honeycomb/images/tab-active-hdpi.png           (honeycomb/images/tab-active-hdpi.png)
   skin/honeycomb/images/tab-inactive-hdpi.png         (honeycomb/images/tab-inactive-hdpi.png)
   skin/honeycomb/images/tab-closed-hdpi.png           (honeycomb/images/tab-closed-hdpi.png)
   skin/honeycomb/images/tab-reopen-hdpi.png           (honeycomb/images/tab-reopen-hdpi.png)
   skin/honeycomb/images/remotetabs-48.png             (honeycomb/images/remotetabs-48.png)
   skin/honeycomb/images/remotetabs-32.png             (honeycomb/images/remotetabs-32.png)
   skin/honeycomb/images/mozilla-32.png                (images/mozilla-32.png)
   skin/honeycomb/images/toggle-on.png                 (honeycomb/images/toggle-on.png)
@@ -354,18 +365,22 @@ chrome.jar:
   skin/honeycomb/images/next-hdpi.png                 (honeycomb/images/next-hdpi.png)
   skin/honeycomb/images/next-disabled-hdpi.png        (honeycomb/images/next-disabled-hdpi.png)
   skin/honeycomb/images/identity-default-hdpi.png     (honeycomb/images/identity-default-hdpi.png)
   skin/honeycomb/images/identity-ssl-hdpi.png         (honeycomb/images/identity-ssl-hdpi.png)
   skin/honeycomb/images/identity-ev-hdpi.png          (honeycomb/images/identity-ev-hdpi.png)
   skin/honeycomb/images/unlocked-hdpi.png             (honeycomb/images/unlocked-hdpi.png)
   skin/honeycomb/images/locked-hdpi.png               (honeycomb/images/locked-hdpi.png)
   skin/honeycomb/images/close-default-hdpi.png        (honeycomb/images/close-default-hdpi.png)
+  skin/honeycomb/images/close-default-tablet-hdpi.png (honeycomb/images/close-default-tablet-hdpi.png)
   skin/honeycomb/images/close-active-hdpi.png         (honeycomb/images/close-active-hdpi.png)
+  skin/honeycomb/images/close-active-tablet-hdpi.png  (honeycomb/images/close-active-tablet-hdpi.png)
+  skin/honeycomb/images/close-background-hdpi.png     (honeycomb/images/close-background-hdpi.png)
   skin/honeycomb/images/close-inactive-tab-hdpi.png   (honeycomb/images/close-inactive-tab-hdpi.png)
+  skin/honeycomb/images/close-inactive-tab-tablet-hdpi.png   (honeycomb/images/close-inactive-tab-tablet-hdpi.png)
   skin/honeycomb/images/check-30.png                  (images/check-30.png)
   skin/honeycomb/images/check-selected-hdpi.png       (honeycomb/images/check-selected-hdpi.png)
   skin/honeycomb/images/check-unselected-hdpi.png     (honeycomb/images/check-unselected-hdpi.png)
   skin/honeycomb/images/search-glass-30.png           (honeycomb/images/search-glass-30.png)
   skin/honeycomb/images/search-clear-30.png           (honeycomb/images/search-clear-30.png)
   skin/honeycomb/images/section-expanded-16.png       (images/section-expanded-16.png)
   skin/honeycomb/images/section-collapsed-16.png      (images/section-collapsed-16.png)
   skin/honeycomb/images/task-switch-hdpi.png          (honeycomb/images/task-switch-hdpi.png)
new file mode 100644
--- /dev/null
+++ b/mobile/themes/core/tablet.css
@@ -0,0 +1,134 @@
+
+.spacer-actionbar,
+.button-actionbar {
+  visibility: collapse;
+}
+
+.button-actionbar[disabled="true"] {
+  opacity: 0.5;
+}
+
+%ifndef honeycomb
+.button-actionbar:hover:active {
+  background-color: #8db8d8;
+}
+%endif
+
+#toolbar-main[tablet="true"] > .spacer-actionbar,
+#toolbar-main[tablet="true"] > .button-actionbar {
+  visibility: visible;
+}
+#toolbar-main[tablet="true"] > #tool-tabs {
+  visibility: collapse;
+}
+
+#controls-scrollbox[tablet="true"] > #controls-sidebar {
+  visibility: collapse;
+}
+
+#tabs-spacer[tablet="true"]  {
+  visibility: collapse;
+}
+
+#tabs-container[tablet="true"] {
+  -moz-border-end: 0px;
+  background: #000;
+}
+
+#tabs[tablet="true"] > scrollbox {
+  max-width: 200px;
+}
+
+#tabs[tablet="true"] .tabs-list {
+  -moz-column-width: 200px;
+  -moz-padding-end: 0px;
+  -moz-padding-start: 0px;
+}
+
+documenttab[tablet="true"] {
+  width: 200px;
+  padding: @padding_xxnormal@;
+  -moz-margin-start: 0px;
+  background: none;
+}
+
+documenttab[tablet="true"][selected="true"] {
+  background: none;
+}
+
+.documenttab-thumbnail[tablet="true"] {
+  border-radius: @border_radius_tiny@;
+}
+
+.documenttab-close-container[tablet="true"] {
+  left: 0px;
+  -moz-margin-end: 0px;
+  -moz-margin-start: 135px;
+  -moz-box-pack: end;
+  -moz-box-align: center;
+}
+
+documenttab[selected="true"] > stack > .documenttab-close-container[tablet="true"] {
+  background: url("chrome://browser/skin/images/close-background-hdpi.png");
+  background-repeat: no-repeat;
+  background-position: right;
+  -moz-margin-end: -@padding_xxnormal@;
+  padding-right: 2px;
+}
+
+.documenttab-close[tablet="true"] {
+  width: 30px;
+  height: 44px;
+  list-style-image: url("chrome://browser/skin/images/close-inactive-tab-tablet-hdpi.png");
+}
+
+documenttab[selected="true"] > stack > hbox > .documenttab-close[tablet="true"] {
+  list-style-image: url("chrome://browser/skin/images/close-default-tablet-hdpi.png");
+}
+
+.documenttab-close-container:hover:active > .documenttab-close[tablet="true"] {
+  list-style-image: url("chrome://browser/skin/images/close-active-tablet-hdpi.png");
+}
+
+#newtab-button[tablet="true"] {
+  list-style-image: url("images/newtab-default-tablet-hdpi.png");
+}
+
+@media (@orientation@: portrait) {
+  #toolbar-main[tablet="true"] > #tool-tabs {
+    visibility: visible;
+  }
+
+  #controls-scrollbox[tablet="true"] > #tabs-sidebar {
+    border: none;
+%ifdef honeycomb
+    top: @touch_button_xlarge@;
+%else
+    top: -moz-calc(@touch_button_xlarge@ + @margin_normal@);
+%endif
+    visibility: collapse;
+  }
+
+  #controls-scrollbox[tablet="true"] > #tabs-sidebar:-moz-locale-dir(ltr) {
+    left: 0;
+  }
+  #controls-scrollbox[tablet="true"] > #tabs-sidebar:-moz-locale-dir(rtl) {
+    right: 0;
+  }
+
+  #controls-scrollbox[tablet="true"] > #tabs-sidebar[open] {
+    position: fixed;
+    visibility: visible;
+  }
+}
+
+%ifndef honeycomb
+@media (min-width: @tablet_panel_minwidth@) {
+  #awesome-panels {
+    -moz-box-shadow: 0px 0px @shadow_width_small@ black;
+  }
+  #search-engines-popup {
+    max-width: -moz-calc(@tablet_panel_minwidth@);
+  }
+}
+%endif
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -3346,11 +3346,15 @@ pref("alerts.slideIncrement", 1);
 pref("alerts.slideIncrementTime", 10);
 pref("alerts.totalOpenTime", 4000);
 pref("alerts.disableSlidingEffect", false);
 
 // DOM full-screen API.
 pref("full-screen-api.enabled", false);
 pref("full-screen-api.allow-trusted-requests-only", true);
 pref("full-screen-api.key-input-restricted", true);
+
+// Time limit, in milliseconds, for nsEventStateManager::IsHandlingUserInput().
+// Used to detect long running handlers of user-generated events.
+pref("dom.event.handling-user-input-time-limit", 1000);
  
 //3D Transforms
 pref("layout.3d-transforms.enabled", false);
--- a/netwerk/cache/nsDiskCacheDevice.cpp
+++ b/netwerk/cache/nsDiskCacheDevice.cpp
@@ -81,16 +81,48 @@
 
 #include "mozilla/FunctionTimer.h"
 #include "nsThreadUtils.h"
 #include "mozilla/Telemetry.h"
 
 static const char DISK_CACHE_DEVICE_ID[] = { "disk" };
 using namespace mozilla;
 
+class nsDiskCacheDeviceDeactivateEntryEvent : public nsRunnable {
+public:
+    nsDiskCacheDeviceDeactivateEntryEvent(nsDiskCacheDevice *device,
+                                          nsCacheEntry * entry,
+                                          nsDiskCacheBinding * binding)
+        : mCanceled(PR_FALSE),
+          mEntry(entry),
+          mDevice(device),
+          mBinding(binding)
+    {
+    }
+
+    NS_IMETHOD Run()
+    {
+        nsCacheServiceAutoLock lock;
+#ifdef PR_LOGGING
+        CACHE_LOG_DEBUG(("nsDiskCacheDeviceDeactivateEntryEvent[%p]\n", this));
+#endif
+        if (!mCanceled) {
+            (void) mDevice->DeactivateEntry_Private(mEntry, mBinding);
+        }
+        return NS_OK;
+    }
+
+    void CancelEvent() { mCanceled = PR_TRUE; }
+private:
+    PRBool mCanceled;
+    nsCacheEntry *mEntry;
+    nsDiskCacheDevice *mDevice;
+    nsDiskCacheBinding *mBinding;
+};
+
 /******************************************************************************
  *  nsDiskCacheEvictor
  *
  *  Helper class for nsDiskCacheDevice.
  *
  *****************************************************************************/
 
 class nsDiskCacheEvictor : public nsDiskCacheRecordVisitor
@@ -136,16 +168,22 @@ nsDiskCacheEvictor::VisitRecord(nsDiskCa
             (diskEntry->Key()[mClientIDSize] != ':') ||
             (memcmp(diskEntry->Key(), mClientID, mClientIDSize) != 0)) {
             return kVisitNextRecord;  // clientID doesn't match, skip it
         }
     }
     
     nsDiskCacheBinding * binding = mBindery->FindActiveBinding(mapRecord->HashNumber());
     if (binding) {
+        // If the entry is pending deactivation, cancel deactivation and doom
+        // the entry
+        if (binding->mDeactivateEvent) {
+            binding->mDeactivateEvent->CancelEvent();
+            binding->mDeactivateEvent = nsnull;
+        }
         // We are currently using this entry, so all we can do is doom it.
         // Since we're enumerating the records, we don't want to call
         // DeleteRecord when nsCacheService::DoomEntry() calls us back.
         binding->mDoomed = PR_TRUE;         // mark binding record as 'deleted'
         nsCacheService::DoomEntry(binding->mCacheEntry);
     } else {
         // entry not in use, just delete storage because we're enumerating the records
         (void) mCacheMap->DeleteStorage(mapRecord);
@@ -448,49 +486,16 @@ nsDiskCacheDevice::Shutdown_Private(PRBo
 
 
 const char *
 nsDiskCacheDevice::GetDeviceID()
 {
     return DISK_CACHE_DEVICE_ID;
 }
 
-class nsDiskCacheDeviceDeactivateEntryEvent : public nsRunnable {
-public:
-    nsDiskCacheDeviceDeactivateEntryEvent(nsDiskCacheDevice *device,
-                                          nsCacheEntry * entry,
-                                          nsDiskCacheBinding * binding)
-        : mCanceled(PR_FALSE),
-          mEntry(entry),
-          mDevice(device),
-          mBinding(binding)
-    {
-    }
-
-    NS_IMETHOD Run()
-    {
-        nsCacheServiceAutoLock lock;
-#ifdef PR_LOGGING
-        CACHE_LOG_DEBUG(("nsDiskCacheDeviceDeactivateEntryEvent[%p]\n", this));
-#endif
-        if (!mCanceled) {
-            (void) mDevice->DeactivateEntry_Private(mEntry, mBinding);
-        }
-        return NS_OK;
-    }
-    
-    void CancelEvent() { mCanceled = PR_TRUE; }
-private:
-    PRBool mCanceled;
-    nsCacheEntry *mEntry;
-    nsDiskCacheDevice *mDevice;
-    nsDiskCacheBinding *mBinding;
-};
-
-
 /**
  *  FindEntry -
  *
  *      cases:  key not in disk cache, hash number free
  *              key not in disk cache, hash number used
  *              key in disk cache
  *
  *  NOTE: called while holding the cache service lock
@@ -630,16 +635,21 @@ nsDiskCacheDevice::BindEntry(nsCacheEntr
     // Find out if there is already an active binding for this hash. If yes it
     // should have another key since BindEntry() shouldn't be called twice for
     // the same entry. Doom the old entry, the new one will get another
     // generation number so files won't collide.
     binding = mBindery.FindActiveBinding(hashNumber);
     if (binding) {
         NS_ASSERTION(!binding->mCacheEntry->Key()->Equals(*entry->Key()),
                      "BindEntry called for already bound entry!");
+        // If the entry is pending deactivation, cancel deactivation
+        if (binding->mDeactivateEvent) {
+            binding->mDeactivateEvent->CancelEvent();
+            binding->mDeactivateEvent = nsnull;
+        }
         nsCacheService::DoomEntry(binding->mCacheEntry);
         binding = nsnull;
     }
 
     // Lookup hash number in cache map. There can be a colliding inactive entry.
     // See bug #321361 comment 21 for the scenario. If there is such entry,
     // delete it.
     rv = mCacheMap.FindRecord(hashNumber, &record);
@@ -671,16 +681,21 @@ nsDiskCacheDevice::BindEntry(nsCacheEntr
         PRUint32    oldHashNumber = oldRecord.HashNumber();
         if (oldHashNumber) {
             // gotta evict this one first
             nsDiskCacheBinding * oldBinding = mBindery.FindActiveBinding(oldHashNumber);
             if (oldBinding) {
                 // XXX if debug : compare keys for hashNumber collision
 
                 if (!oldBinding->mCacheEntry->IsDoomed()) {
+                    // If the old entry is pending deactivation, cancel deactivation
+                    if (oldBinding->mDeactivateEvent) {
+                        oldBinding->mDeactivateEvent->CancelEvent();
+                        oldBinding->mDeactivateEvent = nsnull;
+                    }
                 // we've got a live one!
                     nsCacheService::DoomEntry(oldBinding->mCacheEntry);
                     // storage will be delete when oldBinding->mCacheEntry is Deactivated
                 }
             } else {
                 // delete storage
                 // XXX if debug : compare keys for hashNumber collision
                 rv = mCacheMap.DeleteStorage(&oldRecord);
--- a/netwerk/test/unit/test_bug650955.js
+++ b/netwerk/test/unit/test_bug650955.js
@@ -67,17 +67,39 @@ function nextTest() {
     }
     do_execute_soon(function() { aTest.start(); } );
 }
 
 // Just make sure devices are created
 function InitializeCacheDevices(memDevice, diskDevice) {
     this.start = function() {
         prefService.setBoolPref("browser.cache.memory.enable", memDevice);
+        if (memDevice) {
+            try {
+                cap = prefService.getIntPref("browser.cache.memory.capacity");
+            }
+            catch(ex) {
+                cap = 0;
+            }
+            if (cap == 0) {
+                prefService.setIntPref("browser.cache.memory.capacity", 1024);
+            }
+        }
         prefService.setBoolPref("browser.cache.disk.enable", diskDevice);
+        if (diskDevice) {
+            try {
+                cap = prefService.getIntPref("browser.cache.disk.capacity");
+            }
+            catch(ex) {
+                cap = 0;
+            }
+            if (cap == 0) {
+                prefService.setIntPref("browser.cache.disk.capacity", 1024);
+            }
+        }
         var channel = setupChannel("/bug650995", "Initial value");
         channel.asyncOpen(new ChannelListener(
             nextTest, null),
             null);
     }
 }
 
 function TestCacheEntrySize(setSizeFunc, firstRequest, secondRequest, secondExpectedReply) {
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -62,18 +62,16 @@ skip-if = os == "android"
 [test_bug561276.js]
 [test_bug580508.js]
 [test_bug586908.js]
 [test_bug588389.js]
 [test_bug596443.js]
 [test_bug618835.js]
 [test_bug633743.js]
 [test_bug650955.js]
-# Bug 677427: test fails consistently on Android
-fail-if = os == "android"
 [test_bug652761.js]
 [test_bug651100.js]
 # Bug 675044: test fails consistently on Android
 fail-if = os == "android"  
 [test_bug654926.js]
 # Bug 675049: test fails consistently on Android
 fail-if = os == "android"  
 [test_bug654926_doom_and_read.js]
--- a/other-licenses/android/APKOpen.cpp
+++ b/other-licenses/android/APKOpen.cpp
@@ -245,36 +245,16 @@ SHELL_WRAPPER1(reportJavaCrash, jstring)
 static void * xul_handle = NULL;
 static time_t apk_mtime = 0;
 #ifdef DEBUG
 extern "C" int extractLibs = 1;
 #else
 extern "C" int extractLibs = 0;
 #endif
 
-static uint32_t simple_write(int fd, const void *buf, uint32_t count)
-{
-  uint32_t out_offset = 0;
-  while (out_offset < count) {
-    uint32_t written = write(fd, (const char *)buf + out_offset,
-                             count - out_offset);
-    if (written == -1) {
-      if (errno == EAGAIN || errno == EWOULDBLOCK)
-        continue;
-      else {
-        __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "simple_write failed");
-        break;
-      }
-    }
-
-    out_offset += written;
-  }
-  return out_offset;
-}
-
 static void
 extractFile(const char * path, const struct cdir_entry *entry, void * data)
 {
   uint32_t size = letoh32(entry->uncompressed_size);
 
   struct stat status;
   if (!stat(path, &status) &&
       status.st_size == size &&
@@ -282,58 +262,57 @@ extractFile(const char * path, const str
     return;
 
   int fd = open(path, O_CREAT | O_NOATIME | O_TRUNC | O_RDWR, S_IRWXU);
   if (fd == -1) {
     __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't open %s to decompress library", path);
     return;
   }
 
-  void * buf = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
-                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  if (ftruncate(fd, size) == -1) {
+    __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't ftruncate %s to decompress library", path);
+    close(fd);
+    return;
+  }
+
+  void * buf = mmap(NULL, size, PROT_READ | PROT_WRITE,
+                    MAP_SHARED, fd, 0);
   if (buf == (void *)-1) {
     __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't mmap decompression buffer");
     close(fd);
     return;
   }
 
   z_stream strm = {
     next_in: (Bytef *)data,
     avail_in: letoh32(entry->compressed_size),
     total_in: 0,
 
     next_out: (Bytef *)buf,
-    avail_out: 4096,
+    avail_out: size,
     total_out: 0
   };
 
   int ret;
   ret = inflateInit2(&strm, -MAX_WBITS);
   if (ret != Z_OK)
     __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflateInit failed: %s", strm.msg);
 
-  while ((ret = inflate(&strm, Z_SYNC_FLUSH)) != Z_STREAM_END) {
-    simple_write(fd, buf, 4096 - strm.avail_out);
-    strm.next_out = (Bytef *)buf;
-    strm.avail_out = 4096;
-  }
-  simple_write(fd, buf, 4096 - strm.avail_out);
-
-  if (ret != Z_STREAM_END)
+  if (inflate(&strm, Z_FINISH) != Z_STREAM_END)
     __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflate failed: %s", strm.msg);
 
   if (strm.total_out != size)
     __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "extracted %d, expected %d!", strm.total_out, size);
 
   ret = inflateEnd(&strm);
   if (ret != Z_OK)
     __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflateEnd failed: %s", strm.msg);
 
   close(fd);
-  munmap(buf, 4096);
+  munmap(buf, size);
 }
 
 static void
 extractLib(const struct cdir_entry *entry, void * data, void * dest)
 {
   z_stream strm = {
     next_in: (Bytef *)data,
     avail_in: letoh32(entry->compressed_size),
--- a/parser/html/javasrc/MetaScanner.java
+++ b/parser/html/javasrc/MetaScanner.java
@@ -573,18 +573,18 @@ public abstract class MetaScanner {
                                 continue stateloop;
                             case 'c':
                             case 'C':
                                 contentIndex = 0;
                                 charsetIndex = 0;
                                 state = MetaScanner.ATTRIBUTE_NAME;
                                 continue stateloop;
                             default:
-                                contentIndex = -1;
-                                charsetIndex = -1;
+                                contentIndex = Integer.MAX_VALUE;
+                                charsetIndex = Integer.MAX_VALUE;
                                 state = MetaScanner.ATTRIBUTE_NAME;
                                 continue stateloop;
                         }
                     }
                     // XXX reorder point
                 case MARKUP_DECLARATION_OPEN:
                     markupdeclarationopenloop: for (;;) {
                         c = read();
--- a/parser/html/nsHtml5MetaScanner.cpp
+++ b/parser/html/nsHtml5MetaScanner.cpp
@@ -519,18 +519,18 @@ nsHtml5MetaScanner::stateLoop(PRInt32 st
             case 'c':
             case 'C': {
               contentIndex = 0;
               charsetIndex = 0;
               state = NS_HTML5META_SCANNER_ATTRIBUTE_NAME;
               NS_HTML5_CONTINUE(stateloop);
             }
             default: {
-              contentIndex = -1;
-              charsetIndex = -1;
+              contentIndex = PR_INT32_MAX;
+              charsetIndex = PR_INT32_MAX;
               state = NS_HTML5META_SCANNER_ATTRIBUTE_NAME;
               NS_HTML5_CONTINUE(stateloop);
             }
           }
         }
       }
       case NS_HTML5META_SCANNER_MARKUP_DECLARATION_OPEN: {
         for (; ; ) {
--- a/parser/htmlparser/tests/crashtests/crashtests.list
+++ b/parser/htmlparser/tests/crashtests/crashtests.list
@@ -25,17 +25,17 @@ load 188474-1.html
 load 194329-1.html
 load 197052-1.html
 load 220542-1.html
 load 253979-1.html
 load 269095-1.html
 load 286733-1.html
 load 286733-2.html
 load 299036-1.html
-load 328751-1.html
+asserts-if(Android,1) load 328751-1.html
 load 408939-1.html
 load 423373-1.html
 load 445171-1.html
 skip load 460706-1.xhtml # Bug 479499
 load 468538-1.xhtml
 load 515278-1.html
 load 515533-1.html
 load 515816-1.html
--- a/security/manager/ssl/crashtests/crashtests.list
+++ b/security/manager/ssl/crashtests/crashtests.list
@@ -1,2 +1,2 @@
-asserts-if(browserIsRemote,1) load 327524-1.html # bug 582297
+asserts-if(browserIsRemote,0-1) load 327524-1.html # bug 582297
 asserts-if(browserIsRemote,1) load 398665-1.html # bug 582297
--- a/services/sync/tests/unit/test_errorhandler.js
+++ b/services/sync/tests/unit/test_errorhandler.js
@@ -762,80 +762,83 @@ add_test(function test_syncAndReportErro
 });
 
 add_test(function test_sync_engine_generic_fail() {
   let server = sync_httpd_setup();
 
   let engine = Engines.get("catapult");
   engine.enabled = true;
   engine.sync = function sync() {
-    Svc.Obs.notify("weave:engine:sync:error", "", "steam");
+    Svc.Obs.notify("weave:engine:sync:error", "", "catapult");
   };
 
   let log = Log4Moz.repository.getLogger("Sync.ErrorHandler");
   Svc.Prefs.set("log.appender.file.logOnError", true);
 
   Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
     Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
 
+    // Put these checks here, not after sync(), so that we aren't racing the
+    // log handler... which resets everything just a few lines below!
+    _("Status.engines: " + JSON.stringify(Status.engines));
+    do_check_eq(Status.engines["catapult"], ENGINE_UNKNOWN_FAIL);
+    do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
+
     // Test Error log was written on SYNC_FAILED_PARTIAL.
     let entries = logsdir.directoryEntries;
     do_check_true(entries.hasMoreElements());
     let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
     do_check_eq(logfile.leafName.slice(0, LOG_PREFIX_ERROR.length),
                 LOG_PREFIX_ERROR);
 
     Status.resetSync();
     Service.startOver();
 
     server.stop(run_next_test);
   });
 
-  do_check_eq(Status.engines["steam"], undefined);
+  do_check_eq(Status.engines["catapult"], undefined);
 
   do_check_true(setUp());
 
   Service.sync();
-
-  do_check_eq(Status.engines["steam"], ENGINE_UNKNOWN_FAIL);
-  do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
 });
 
 // This test should be the last one since it monkeypatches the engine object
 // and we should only have one engine object throughout the file (bug 629664).
 add_test(function test_engine_applyFailed() {
   let server = sync_httpd_setup();
 
   let engine = Engines.get("catapult");
   engine.enabled = true;
   delete engine.exception;
   engine.sync = function sync() {
-    Svc.Obs.notify("weave:engine:sync:applied", {newFailed:1}, "steam");
+    Svc.Obs.notify("weave:engine:sync:applied", {newFailed:1}, "catapult");
   };
 
   let log = Log4Moz.repository.getLogger("Sync.ErrorHandler");
   Svc.Prefs.set("log.appender.file.logOnError", true);
 
   Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
     Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
 
+    do_check_eq(Status.engines["catapult"], ENGINE_APPLY_FAIL);
+    do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
+
     // Test Error log was written on SYNC_FAILED_PARTIAL.
     let entries = logsdir.directoryEntries;
     do_check_true(entries.hasMoreElements());
     let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
     do_check_eq(logfile.leafName.slice(0, LOG_PREFIX_ERROR.length),
                 LOG_PREFIX_ERROR);
 
     Status.resetSync();
     Service.startOver();
 
     server.stop(run_next_test);
   });
 
-  do_check_eq(Status.engines["steam"], undefined);
+  do_check_eq(Status.engines["catapult"], undefined);
 
   do_check_true(setUp());
 
   Service.sync();
-
-  do_check_eq(Status.engines["steam"], ENGINE_APPLY_FAIL);
-  do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
 });
--- a/testing/crashtest/sanity/crashtests.list
+++ b/testing/crashtest/sanity/crashtests.list
@@ -1,2 +1,2 @@
-load data:text/html,
+asserts-if(Android,10) load data:text/html,
 load data:text/html,PASS
--- a/testing/mochitest/specialpowers/content/specialpowers.js
+++ b/testing/mochitest/specialpowers/content/specialpowers.js
@@ -396,16 +396,22 @@ SpecialPowers.prototype = {
 
   log: function(data) {
     this._mfl.log(data);
   },
 
   closeLogFile: function() {
     this._mfl.close();
   },
+
+  addCategoryEntry: function(category, entry, value, persists, replace) {
+    Cc["@mozilla.org/categorymanager;1"].
+      getService(Components.interfaces.nsICategoryManager).
+      addCategoryEntry(category, entry, value, persists, replace);
+  },
 };
 
 // Expose everything but internal APIs (starting with underscores) to
 // web content.
 SpecialPowers.prototype.__exposedProps__ = {};
 for each (i in Object.keys(SpecialPowers.prototype).filter(function(v) {return v.charAt(0) != "_";})) {
   SpecialPowers.prototype.__exposedProps__[i] = "r";
 }
--- a/toolkit/content/tests/chrome/Makefile.in
+++ b/toolkit/content/tests/chrome/Makefile.in
@@ -79,16 +79,17 @@ include $(topsrcdir)/config/rules.mk
 		window_largemenu.xul \
 		test_popup_anchor.xul \
 		window_popup_anchor.xul \
 		frame_popup_anchor.xul \
 		test_preferences.xul \
 		window_preferences.xul \
 		window_preferences2.xul \
 		window_preferences3.xul \
+		window_preferences_commandretarget.xul \
 		test_autocomplete2.xul \
 		test_autocomplete3.xul \
 		test_autocomplete4.xul \
 		test_keys.xul \
 		window_keys.xul \
 		test_showcaret.xul \
 		window_showcaret.xul \
 		test_righttoleft.xul \
--- a/toolkit/content/tests/chrome/test_preferences.xul
+++ b/toolkit/content/tests/chrome/test_preferences.xul
@@ -416,16 +416,24 @@
       ok(GetXULElement(aPrefWindow, "tests.static_preference_file"   ).hasUserValue === false, "non-instant reset hasUserValue file"   );
     }
 
     function RunNonInstantPrefTestClose(aPrefWindow)
     {
       WritePrefsToPreferences(aPrefWindow, kPrefValueSet2);
     }
 
+    function RunCheckCommandRedirect(aPrefWindow)
+    {
+      GetXULElement(aPrefWindow, "checkbox").click();
+      ok(GetXULElement(aPrefWindow, "tests.static_preference_bool").value, "redirected command bool");
+      GetXULElement(aPrefWindow, "checkbox").click();
+      ok(!GetXULElement(aPrefWindow, "tests.static_preference_bool").value, "redirected command bool");
+    }
+
     function RunResetPrefTest(aPrefWindow)
     {
       // try resetting the prefs to default values
       GetXULElement(aPrefWindow, "tests.static_preference_int"    ).reset();
       GetXULElement(aPrefWindow, "tests.static_preference_bool"   ).reset();
       GetXULElement(aPrefWindow, "tests.static_preference_string" ).reset();
       GetXULElement(aPrefWindow, "tests.static_preference_wstring").reset();
       GetXULElement(aPrefWindow, "tests.static_preference_unichar").reset();
@@ -497,20 +505,26 @@
       ok(found.int          === expected.int,          "non-instant reset deferred int"    );
       ok(found.bool         === expected.bool,         "non-instant reset deferred bool"   );
       ok(found.string       === expected.string,       "non-instant reset deferred string" );
       ok(found.wstring_data === expected.wstring_data, "non-instant reset deferred wstring");
       ok(found.unichar_data === expected.unichar_data, "non-instant reset deferred unichar");
       ok(found.file_data    === expected.file_data,    "non-instant reset deferred file"   );
     }
 
+    function RunTestCommandRedirect()
+    {
+      openDialog("window_preferences_commandretarget.xul", "", "modal", RunCheckCommandRedirect, true);
+    }
+
     function RunTest()
     {
       RunTestInstant();
       RunTestNonInstant();
+      RunTestCommandRedirect();
       SimpleTest.finish();
     }
   ]]>
   </script>
 
   <body xmlns="http://www.w3.org/1999/xhtml">
     <p id="display"></p>
     <div id="content" style="display: none"></div>
new file mode 100644
--- /dev/null
+++ b/toolkit/content/tests/chrome/window_preferences_commandretarget.xul
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<!--
+  XUL Widget Test for preferences window. This particular test ensures that
+  a checkbox with a command attribute properly updates even though the command
+  event gets retargeted.
+-->
+<prefwindow xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+            title="preferences window"
+            windowtype="test:preferences"
+            buttons="accept,cancel"
+            onload="RunTest(window.arguments)">
+  <script type="application/javascript">
+  <![CDATA[
+    function RunTest(aArgs)
+    {
+      aArgs[0](this);
+      document.documentElement.cancelDialog();
+    }
+  ]]>
+  </script>
+
+  <prefpane id="sample_pane" label="Sample Prefpane">
+    <preferences id="sample_preferences">
+      <preference id="tests.static_preference_bool"
+                  name="tests.static_preference_bool"
+                  type="bool"/>
+    </preferences>
+
+    <commandset>
+      <command id="cmd_test" preference="tests.static_preference_bool"/>
+    </commandset>
+
+    <checkbox id="checkbox" label="Enable Option" preference="tests.static_preference_bool" command="cmd_test"/>
+  </prefpane>
+</prefwindow>
--- a/toolkit/content/widgets/preferences.xml
+++ b/toolkit/content/widgets/preferences.xml
@@ -1248,17 +1248,19 @@
       </property>
       <field name="_content">
         document.getAnonymousElementByAttribute(this, "class", "content-box");
       </field>
     </implementation>
     <handlers>
       <handler event="command">
         // This "command" event handler tracks changes made to preferences by 
-        // the user in this window. 
+        // the user in this window.
+        if (event.sourceEvent)
+          event = event.sourceEvent;
         this.userChangedValue(event.target);
       </handler>
       <handler event="select">
         // This "select" event handler tracks changes made to colorpicker 
         // preferences by the user in this window.
         if (event.target.localName == "colorpicker") 
           this.userChangedValue(event.target);
       </handler>
--- a/toolkit/mozapps/downloads/nsHelperAppDlg.js
+++ b/toolkit/mozapps/downloads/nsHelperAppDlg.js
@@ -606,17 +606,18 @@ nsUnknownContentTypeDialog.prototype = {
       catch (ex) {
       }
       if (primaryExtension != "")
         typeString = this.dialogElement("strings").getFormattedString("fileType", [primaryExtension.toUpperCase()]);
       // 3. If we can't even do that, just give up and show the MIME type.
       else
         typeString = mimeInfo.MIMEType;
     }
-    if (this.mLauncher.contentLength) {
+    // When the length is unknown, contentLength would be -1
+    if (this.mLauncher.contentLength >= 0) {
       let [size, unit] = DownloadUtils.
                          convertByteUnits(this.mLauncher.contentLength);
       type.value = this.dialogElement("strings")
                        .getFormattedString("fileSizeWithType", 
                                            [typeString, size, unit]);
     }
     else {
       type.value = typeString;
--- a/widget/public/nsIJumpListBuilder.idl
+++ b/widget/public/nsIJumpListBuilder.idl
@@ -44,34 +44,34 @@ interface nsIMutableArray;
 [scriptable, uuid(1FE6A9CD-2B18-4dd5-A176-C2B32FA4F683)]
 interface nsIJumpListBuilder : nsISupports
 {
   /**
    * JumpLists
    *
    * Jump lists are built and then applied. Modifying an applied jump list is not
    * permitted. Callers should begin the creation of a new jump list using
-   * initListBuild, add sub lists using addListBuild, then commit the jump list
+   * initListBuild, add sub lists using addListToBuild, then commit the jump list
    * using commitListBuild. Lists are built in real-time during the sequence of
    * build calls, make sure to check for errors on each individual step.
    *
    * The default number of allowed items in a jump list is ten. Users can change
    * the number through system preferences. User may also pin items to jump lists,
    * which take up additional slots. Applications do not have control over the
    * number of items allowed in jump lists; excess items added are dropped by the
    * system. Item insertion priority is defined as first to last added. 
    *
    * Users may remove items from jump lists after they are commited. The system
    * tracks removed items between commits. A list of these items is returned by
    * a call to initListBuild. nsIJumpListBuilder does not filter entries added that
    * have been removed since the last commit. To prevent repeatedly adding entries
    * users have removed, applications are encoraged to track removed items 
    * internally.
    *
-   * Each list is made up of an array of nsIWinJumpListItems representing items
+   * Each list is made up of an array of nsIJumpListItem representing items
    * such as shortcuts, links, and separators. See nsIJumpListItem for information
    * on adding additional jump list types.
    */
 
   /**
    * List Types
    */
 
--- a/widget/public/nsIJumpListItem.idl
+++ b/widget/public/nsIJumpListItem.idl
@@ -124,28 +124,47 @@ interface nsIJumpListLink : nsIJumpListI
    */
   boolean compareHash(in nsIURI uri);
 };
 
 /**
  * A generic application shortcut with command line support.
  */
 
-[scriptable, uuid(9664389E-11D6-4bea-B68C-D70232162068)]
+[scriptable, uuid(CBE3A37C-BCE1-4fec-80A5-5FFBC7F33EEA)]
 interface nsIJumpListShortcut : nsIJumpListItem
 {
   /**
    * Set or get the handler app for this shortcut item.
+   *
+   * The handler app may also be used along with iconIndex to generate an icon
+   * for the jump list item.
    * 
    * @throw NS_ERROR_FILE_NOT_FOUND if the handler app can
    * not be found on  the system.
+   *
+   * @see faviconPageUri
    */
   attribute nsILocalHandlerApp app;
 
   /**
    * Set or get the icon displayed with the jump list item.
    *
-   * Indicates the resource index of the icon contained
-   * within the the handler executable.
+   * Indicates the resource index of the icon contained within the handler
+   * executable which may be used as the jump list icon.
+   *
+   * @see faviconPageUri
    */
   attribute long iconIndex;
+
+  /**
+   * Set or get the URI of a page whose favicon may be used as the icon.
+   *
+   * When a jump list build occurs, the favicon to be used for the item is
+   * obtained using the following steps:
+   * - First, attempt to use the asynchronously retrieved and scaled favicon
+   * associated with the faviconPageUri.
+   * - If faviconPageUri is null, or if retrieving the favicon fails, fall
+   * back to using the handler executable and iconIndex.  
+   */
+  attribute nsIURI faviconPageUri;
 };
 
--- a/widget/src/android/GfxInfo.cpp
+++ b/widget/src/android/GfxInfo.cpp
@@ -266,20 +266,23 @@ GfxInfo::GetFeatureStatusImpl(PRInt32 aF
 
   // For now, we don't implement the downloaded blacklist.
   if (aDriverInfo) {
     *aStatus = status;
     return NS_OK;
   }
 
   if (aFeature == FEATURE_OPENGL_LAYERS) {
-      nsAutoString str;
-      /* Whitelist Galaxy S phones */
-      if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "HARDWARE", str)) {
-          if (str != NS_LITERAL_STRING("smdkc110")) {
-            status = FEATURE_BLOCKED_DEVICE;
-          }
-      }
+    /* XXX: Use this code when we're ready to whitelist devices. */
+    // nsAutoString str;
+    // /* Whitelist Galaxy S phones */
+    // if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "HARDWARE", str)) {
+    //   if (str != NS_LITERAL_STRING("smdkc110")) {
+    //     status = FEATURE_BLOCKED_DEVICE;
+    //   }
+    // }
+
+    status = FEATURE_BLOCKED_DEVICE;
   }
 
   *aStatus = status;
   return NS_OK;
 }
--- a/widget/src/windows/JumpListBuilder.cpp
+++ b/widget/src/windows/JumpListBuilder.cpp
@@ -16,16 +16,17 @@
  *
  * The Initial Developer of the Original Code is
  * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Jim Mathies <jmathies@mozilla.com>
+ *   Brian R. Bondy <netzen@gmail.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
@@ -44,43 +45,61 @@
 #include "nsCOMPtr.h"
 #include "nsServiceManagerUtils.h"
 #include "nsAutoPtr.h"
 #include "nsString.h"
 #include "nsArrayUtils.h"
 #include "nsIMutableArray.h"
 #include "nsWidgetsCID.h"
 #include "WinTaskbar.h"
+#include "nsDirectoryServiceUtils.h"
+#include "nsISimpleEnumerator.h"
+#include "mozilla/Preferences.h"
+#include "imgIContainer.h"
+#include "imgITools.h"
+#include "nsStringStream.h"
+#include "nsNetUtil.h"
+#include "nsThreadUtils.h"
 
 namespace mozilla {
 namespace widget {
 
 static NS_DEFINE_CID(kJumpListItemCID,     NS_WIN_JUMPLISTITEM_CID);
 static NS_DEFINE_CID(kJumpListLinkCID,     NS_WIN_JUMPLISTLINK_CID);
 static NS_DEFINE_CID(kJumpListShortcutCID, NS_WIN_JUMPLISTSHORTCUT_CID);
 
 // defined in WinTaskbar.cpp
 extern const wchar_t *gMozillaJumpListIDGeneric;
 
 PRPackedBool JumpListBuilder::sBuildingList = PR_FALSE;
+const char kPrefTaskbarEnabled[] = "browser.taskbar.lists.enabled";
 
-NS_IMPL_ISUPPORTS1(JumpListBuilder, nsIJumpListBuilder)
+NS_IMPL_ISUPPORTS2(JumpListBuilder, nsIJumpListBuilder, nsIObserver)
+NS_IMPL_ISUPPORTS1(AsyncFaviconDataReady, nsIFaviconDataCallback)
+NS_IMPL_THREADSAFE_ISUPPORTS1(AsyncWriteIconToDisk, nsIRunnable)
+NS_IMPL_THREADSAFE_ISUPPORTS1(AsyncDeleteIconFromDisk, nsIRunnable)
+NS_IMPL_THREADSAFE_ISUPPORTS1(AsyncDeleteAllFaviconsFromDisk, nsIRunnable)
 
 JumpListBuilder::JumpListBuilder() :
   mMaxItems(0),
   mHasCommit(PR_FALSE)
 {
   ::CoInitialize(NULL);
   
   CoCreateInstance(CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER,
                    IID_ICustomDestinationList, getter_AddRefs(mJumpListMgr));
+
+  NS_NewThread(getter_AddRefs(mIOThread));
+  Preferences::AddStrongObserver(this, kPrefTaskbarEnabled);
 }
 
 JumpListBuilder::~JumpListBuilder()
 {
+  mIOThread->Shutdown();
+  Preferences::RemoveObserver(this, kPrefTaskbarEnabled);
   mJumpListMgr = nsnull;
   ::CoUninitialize();
 }
 
 /* readonly attribute short available; */
 NS_IMETHODIMP JumpListBuilder::GetAvailable(PRInt16 *aAvailable)
 {
   *aAvailable = PR_FALSE;
@@ -140,24 +159,124 @@ NS_IMETHODIMP JumpListBuilder::InitListB
 
   IObjectArray *objArray;
 
   if (SUCCEEDED(mJumpListMgr->BeginList(&mMaxItems, IID_PPV_ARGS(&objArray)))) {
     if (objArray) {
       TransferIObjectArrayToIMutableArray(objArray, removedItems);
       objArray->Release();
     }
+
+    RemoveIconCacheForItems(removedItems);
+
     sBuildingList = PR_TRUE;
     *_retval = PR_TRUE;
     return NS_OK;
   }
 
   return NS_OK;
 }
 
+// Ensures that we don't have old ICO files that aren't in our jump lists 
+// anymore left over in the cache.
+nsresult JumpListBuilder::RemoveIconCacheForItems(nsIMutableArray *items) 
+{
+  NS_ENSURE_ARG_POINTER(items);
+  
+  nsresult rv;
+  PRUint32 length;
+  items->GetLength(&length);
+  for (PRUint32 i = 0; i < length; ++i) {
+
+    //Obtain an IJumpListItem and get the type
+    nsCOMPtr<nsIJumpListItem> item = do_QueryElementAt(items, i);
+    if (!item) {
+      continue;
+    }
+    PRInt16 type;
+    if (NS_FAILED(item->GetType(&type))) {
+      continue;
+    }
+
+    // If the item is a shortcut, remove its associated icon if any
+    if (type == nsIJumpListItem::JUMPLIST_ITEM_SHORTCUT) {
+      nsCOMPtr<nsIJumpListShortcut> shortcut = do_QueryInterface(item);
+      if (shortcut) {
+        nsCOMPtr<nsIURI> uri;
+        rv = shortcut->GetFaviconPageUri(getter_AddRefs(uri));
+        if (NS_SUCCEEDED(rv) && uri) {
+          
+          // The local file path is stored inside the nsIURI
+          // Get the nsIURI spec which stores the local path for the icon to remove
+          nsCAutoString spec;
+          nsresult rv = uri->GetSpec(spec);
+          NS_ENSURE_SUCCESS(rv, rv);
+
+          nsCOMPtr<nsIRunnable> event 
+            = new AsyncDeleteIconFromDisk(NS_ConvertUTF8toUTF16(spec));
+          mIOThread->Dispatch(event, NS_DISPATCH_NORMAL);
+
+          // The shortcut was generated from an IShellLinkW so IShellLinkW can
+          // only tell us what the original icon is and not the URI.
+          // So this field was used only temporarily as the actual icon file
+          // path.  It should be cleared.
+          shortcut->SetFaviconPageUri(nsnull);
+        }
+      }
+    }
+
+  } // end for
+
+  return NS_OK;
+}
+
+// Ensures that we have no old ICO files left in the jump list cache
+nsresult JumpListBuilder::RemoveIconCacheForAllItems() 
+{
+  // Construct the path of our jump list cache
+  nsCOMPtr<nsIFile> jumpListCacheDir;
+  nsresult rv = NS_GetSpecialDirectory("ProfLDS", 
+                                       getter_AddRefs(jumpListCacheDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = jumpListCacheDir->AppendNative(nsDependentCString(JumpListItem::kJumpListCacheDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsISimpleEnumerator> entries;
+  rv = jumpListCacheDir->GetDirectoryEntries(getter_AddRefs(entries));
+  NS_ENSURE_SUCCESS(rv, rv);
+  
+  // Loop through each directory entry and remove all ICO files found
+  do {
+    PRBool hasMore = PR_FALSE;
+    if (NS_FAILED(entries->HasMoreElements(&hasMore)) || !hasMore)
+      break;
+
+    nsCOMPtr<nsISupports> supp;
+    if (NS_FAILED(entries->GetNext(getter_AddRefs(supp))))
+      break;
+
+    nsCOMPtr<nsIFile> currFile(do_QueryInterface(supp));
+    nsAutoString path;
+    if (NS_FAILED(currFile->GetPath(path)))
+      continue;
+
+    PRInt32 len = path.Length();
+    if (StringTail(path, 4).LowerCaseEqualsASCII(".ico")) {
+      // Check if the cached ICO file exists
+      PRBool exists;
+      if (NS_FAILED(currFile->Exists(&exists)) || !exists)
+        continue;
+
+      // We found an ICO file that exists, so we should remove it
+      currFile->Remove(PR_FALSE);
+    }
+  } while(true);
+
+  return NS_OK;
+}
+
 /* boolean addListToBuild(in short aCatType, [optional] in nsIArray items, [optional] in AString catName); */
 NS_IMETHODIMP JumpListBuilder::AddListToBuild(PRInt16 aCatType, nsIArray *items, const nsAString &catName, PRBool *_retval)
 {
   nsresult rv;
 
   *_retval = PR_FALSE;
 
   if (!mJumpListMgr)
@@ -188,17 +307,17 @@ NS_IMETHODIMP JumpListBuilder::AddListTo
           rv = JumpListSeparator::GetSeparator(link);
           if (NS_FAILED(rv))
             return rv;
           collection->AddObject(link);
           continue;
         }
         // These should all be ShellLinks
         nsRefPtr<IShellLinkW> link;
-        rv = JumpListShortcut::GetShellLink(item, link);
+        rv = JumpListShortcut::GetShellLink(item, link, mIOThread);
         if (NS_FAILED(rv))
           return rv;
         collection->AddObject(link);
       }
 
       // We need IObjectArray to submit
       nsRefPtr<IObjectArray> pArray;
       hr = collection->QueryInterface(IID_IObjectArray, getter_AddRefs(pArray));
@@ -266,17 +385,17 @@ NS_IMETHODIMP JumpListBuilder::AddListTo
             if (NS_FAILED(rv))
               return rv;
             collection->AddObject(shellItem);
           }
           break;
           case nsIJumpListItem::JUMPLIST_ITEM_SHORTCUT:
           {
             nsRefPtr<IShellLinkW> shellItem;
-            rv = JumpListShortcut::GetShellLink(item, shellItem);
+            rv = JumpListShortcut::GetShellLink(item, shellItem, mIOThread);
             if (NS_FAILED(rv))
               return rv;
             collection->AddObject(shellItem);
           }
           break;
         }
       }
 
@@ -406,12 +525,247 @@ nsresult JumpListBuilder::TransferIObjec
 
     if (NS_SUCCEEDED(rv)) {
       removedItems->AppendElement(item, PR_FALSE);
     }
   }
   return NS_OK;
 }
 
+NS_IMETHODIMP JumpListBuilder::Observe(nsISupports* aSubject,
+                                        const char* aTopic,
+                                        const PRUnichar* aData)
+{
+  if (nsDependentString(aData).EqualsASCII(kPrefTaskbarEnabled)) {
+    PRBool enabled = Preferences::GetBool(kPrefTaskbarEnabled, true);
+    if (!enabled) {
+      
+      nsCOMPtr<nsIRunnable> event = new AsyncDeleteAllFaviconsFromDisk();
+      mIOThread->Dispatch(event, NS_DISPATCH_NORMAL);
+    }
+  }
+  return NS_OK;
+}
+
+
+AsyncFaviconDataReady::AsyncFaviconDataReady(nsIURI *aNewURI, 
+                                             nsCOMPtr<nsIThread> &aIOThread) 
+                      : mNewURI(aNewURI), 
+                        mIOThread(aIOThread)
+{
+}
+
+NS_IMETHODIMP
+AsyncFaviconDataReady::OnFaviconDataAvailable(nsIURI *aFaviconURI, 
+                                              PRUint32 aDataLen,
+                                              const PRUint8 *aData, 
+                                              const nsACString &aMimeType)
+{
+  if (!aDataLen || !aData) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIFile> icoFile;
+  nsresult rv = JumpListShortcut::GetOutputIconPath(mNewURI, icoFile);
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsAutoString path;
+  rv = icoFile->GetPath(path);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Allocate a new buffer that we own and can use out of line in 
+  // another thread.  Copy the favicon raw data into it.
+  const fallible_t fallible = fallible_t();
+  PRUint8 *data = new (fallible) PRUint8[aDataLen];
+  if (!data) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  memcpy(data, aData, aDataLen);
+
+  //AsyncWriteIconToDisk takes ownership of the heap allocated buffer.
+  nsCOMPtr<nsIRunnable> event = new AsyncWriteIconToDisk(path, aMimeType, 
+                                                         data, 
+                                                         aDataLen);
+  mIOThread->Dispatch(event, NS_DISPATCH_NORMAL);
+
+  return NS_OK;
+}
+
+// Warning: AsyncWriteIconToDisk assumes ownership of the aData buffer passed in
+AsyncWriteIconToDisk::AsyncWriteIconToDisk(const nsAString &aIconPath,
+                                           const nsACString &aMimeTypeOfInputData,
+                                           PRUint8 *aBuffer, 
+                                           PRUint32 aBufferLength)
+                     : mIconPath(aIconPath),
+                       mMimeTypeOfInputData(aMimeTypeOfInputData),
+                       mBuffer(aBuffer),
+                       mBufferLength(aBufferLength)
+
+{
+}
+
+NS_IMETHODIMP AsyncWriteIconToDisk::Run()
+{
+  NS_PRECONDITION(!NS_IsMainThread(), "Should not be called on the main thread.");
+
+  // Convert the obtained favicon data to an input stream
+  nsCOMPtr<nsIInputStream> stream;
+  nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
+                                      reinterpret_cast<const char*>(mBuffer.get()), 
+                                      mBufferLength,
+                                      NS_ASSIGNMENT_DEPEND);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Decode the image from the format it was returned to us in (probably PNG)
+  nsCOMPtr<imgIContainer> container;
+  nsCOMPtr<imgITools> imgtool = do_CreateInstance("@mozilla.org/image/tools;1");
+  rv = imgtool->DecodeImageData(stream, mMimeTypeOfInputData, 
+                                getter_AddRefs(container));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Get the recommended icon width and height, or if failure to obtain 
+  // these settings, fall back to 16x16 ICOs.  These values can be different
+  // if the user has a different DPI setting other than 100%.
+  // Windows would scale the 16x16 icon themselves, but it's better
+  // we let our ICO encoder do it.
+  PRInt32 systemIconWidth = GetSystemMetrics(SM_CXSMICON);
+  PRInt32 systemIconHeight = GetSystemMetrics(SM_CYSMICON);
+  if (systemIconWidth == 0 || systemIconHeight == 0) {
+    systemIconWidth = 16;
+    systemIconHeight = 16;
+  }
+  // Scale the image to the needed size and in ICO format
+  mMimeTypeOfInputData.AssignLiteral("image/vnd.microsoft.icon");
+  nsCOMPtr<nsIInputStream> iconStream;
+  rv = imgtool->EncodeScaledImage(container, mMimeTypeOfInputData,
+                                  systemIconWidth,
+                                  systemIconHeight,
+                                  getter_AddRefs(iconStream));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsILocalFile> icoFile
+    = do_CreateInstance("@mozilla.org/file/local;1");
+  NS_ENSURE_TRUE(icoFile, NS_ERROR_FAILURE);
+  rv = icoFile->InitWithPath(mIconPath);
+
+  // Setup the output stream for the ICO file on disk
+  nsCOMPtr<nsIOutputStream> outputStream;
+  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), icoFile);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Obtain the ICO buffer size from the re-encoded ICO stream
+  PRUint32 bufSize;
+  rv = iconStream->Available(&bufSize);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Setup a buffered output stream from the stream object
+  // so that we can simply use WriteFrom with the stream object
+  nsCOMPtr<nsIOutputStream> bufferedOutputStream;
+  rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream),
+                                  outputStream, bufSize);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Write out the icon stream to disk and make sure we wrote everything
+  PRUint32 wrote;
+  rv = bufferedOutputStream->WriteFrom(iconStream, bufSize, &wrote);
+  NS_ASSERTION(bufSize == wrote, "Icon wrote size should be equal to requested write size");
+
+  // Cleanup
+  bufferedOutputStream->Close();
+  outputStream->Close();
+  return rv;
+}
+
+AsyncWriteIconToDisk::~AsyncWriteIconToDisk()
+{
+}
+
+AsyncDeleteIconFromDisk::AsyncDeleteIconFromDisk(const nsAString &aIconPath)
+                        : mIconPath(aIconPath)
+{
+}
+
+NS_IMETHODIMP AsyncDeleteIconFromDisk::Run()
+{
+  // Construct the parent path of the passed in path
+  nsCOMPtr<nsILocalFile> icoFile = do_CreateInstance("@mozilla.org/file/local;1");
+  NS_ENSURE_TRUE(icoFile, NS_ERROR_FAILURE);
+  nsresult rv = icoFile->InitWithPath(mIconPath);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Check if the cached ICO file exists
+  PRBool exists;
+  rv = icoFile->Exists(&exists);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Check that we aren't deleting some arbitrary file that is not an icon
+  if (StringTail(mIconPath, 4).LowerCaseEqualsASCII(".ico")) {
+    // Check if the cached ICO file exists
+    PRBool exists;
+    if (NS_FAILED(icoFile->Exists(&exists)) || !exists)
+      return NS_ERROR_FAILURE;
+
+    // We found an ICO file that exists, so we should remove it
+    icoFile->Remove(PR_FALSE);
+  }
+
+  return NS_OK;
+}
+
+AsyncDeleteIconFromDisk::~AsyncDeleteIconFromDisk()
+{
+}
+
+AsyncDeleteAllFaviconsFromDisk::AsyncDeleteAllFaviconsFromDisk()
+{
+}
+
+NS_IMETHODIMP AsyncDeleteAllFaviconsFromDisk::Run()
+{
+  // Construct the path of our jump list cache
+  nsCOMPtr<nsIFile> jumpListCacheDir;
+  nsresult rv = NS_GetSpecialDirectory("ProfLDS", 
+    getter_AddRefs(jumpListCacheDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = jumpListCacheDir->AppendNative(nsDependentCString(JumpListItem::kJumpListCacheDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsISimpleEnumerator> entries;
+  rv = jumpListCacheDir->GetDirectoryEntries(getter_AddRefs(entries));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Loop through each directory entry and remove all ICO files found
+  do {
+    PRBool hasMore = PR_FALSE;
+    if (NS_FAILED(entries->HasMoreElements(&hasMore)) || !hasMore)
+      break;
+
+    nsCOMPtr<nsISupports> supp;
+    if (NS_FAILED(entries->GetNext(getter_AddRefs(supp))))